/******************************************************************************* * Copyright (c) 2005, 2015 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Code 9 - Additional function and fixes * EclipseSource - ongoing development * Felix Riegger (SAP AG) - consolidation of publishers for PDE formats (bug 331974) * SAP AG - ongoing development * Rapicorp - additional features * Red Hat Inc. - Bug 460967 *******************************************************************************/ package org.eclipse.equinox.internal.p2.publisher.eclipse; import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.util.*; import java.util.Map.Entry; import javax.xml.parsers.*; import org.eclipse.core.runtime.*; import org.eclipse.equinox.frameworkadmin.BundleInfo; import org.eclipse.equinox.internal.p2.core.helpers.ServiceHelper; import org.eclipse.equinox.internal.p2.core.helpers.URLUtil; import org.eclipse.equinox.p2.metadata.IVersionedId; import org.eclipse.equinox.p2.metadata.VersionedId; import org.eclipse.equinox.p2.publisher.eclipse.FeatureEntry; import org.eclipse.equinox.p2.repository.IRepository; import org.eclipse.equinox.p2.repository.IRepositoryReference; import org.eclipse.equinox.p2.repository.spi.RepositoryReference; import org.eclipse.osgi.service.datalocation.Location; import org.eclipse.osgi.util.NLS; import org.eclipse.pde.internal.publishing.Activator; import org.xml.sax.*; import org.xml.sax.helpers.DefaultHandler; /** * Used to parse a .product file. */ public class ProductFile extends DefaultHandler implements IProductDescriptor { public final static String GENERIC_VERSION_NUMBER = "0.0.0"; //$NON-NLS-1$ private static final String ATTRIBUTE_PATH = "path"; //$NON-NLS-1$ private static final String ATTRIBUTE_ICON = "icon"; //$NON-NLS-1$ protected static final String ATTRIBUTE_FRAGMENT = "fragment"; //$NON-NLS-1$ private static final String ATTRIBUTE_APPLICATION = "application"; //$NON-NLS-1$ private static final String ATTRIBUTE_INCLUDE_LAUNCHERS = "includeLaunchers"; //$NON-NLS-1$ private static final String ATTRIBUTE_NAME = "name"; //$NON-NLS-1$ private static final String ATTRIBUTE_VALUE = "value"; //$NON-NLS-1$ private static final String ATTRIBUTE_LOCATION = "location"; //$NON-NLS-1$ private static final String ATTRIBUTE_AUTO_START = "autoStart"; //$NON-NLS-1$ private static final String ATTRIBUTE_START_LEVEL = "startLevel"; //$NON-NLS-1$ protected static final String ATTRIBUTE_VERSION = "version"; //$NON-NLS-1$ protected static final String ATTRIBUTE_ID = "id"; //$NON-NLS-1$ private static final String ATTRIBUTE_UID = "uid"; //$NON-NLS-1$ private static final String ATTRIBUTE_CONTENT_TYPE = "type"; //$NON-NLS-1$ private static final String ATTRIBUTE_OS = "os"; //$NON-NLS-1$ private static final String ATTRIBUTE_ARCH = "arch"; //$NON-NLS-1$ private static final String ATTRIBUTE_ENABLED = "enabled"; //$NON-NLS-1$ private static final String ATTRIBUTE_FEATURE_INSTALL_MODE = "installMode"; //$NON-NLS-1$ private static final String PROPERTY_ECLIPSE_APPLICATION = "eclipse.application"; //$NON-NLS-1$ private static final String PROPERTY_ECLIPSE_PRODUCT = "eclipse.product"; //$NON-NLS-1$ private final static SAXParserFactory parserFactory = SAXParserFactory.newInstance(); private static final String PROGRAM_ARGS = "programArgs"; //$NON-NLS-1$ private static final String PROGRAM_ARGS_LINUX = "programArgsLin"; //$NON-NLS-1$ private static final String PROGRAM_ARGS_MAC = "programArgsMac"; //$NON-NLS-1$ private static final String PROGRAM_ARGS_SOLARIS = "programArgsSol"; //$NON-NLS-1$ private static final String PROGRAM_ARGS_WIN = "programArgsWin"; //$NON-NLS-1$ private static final String VM_ARGS = "vmArgs"; //$NON-NLS-1$ private static final String VM_ARGS_LINUX = "vmArgsLin"; //$NON-NLS-1$ private static final String VM_ARGS_MAC = "vmArgsMac"; //$NON-NLS-1$ private static final String VM_ARGS_SOLARIS = "vmArgsSol"; //$NON-NLS-1$ private static final String VM_ARGS_WIN = "vmArgsWin"; //$NON-NLS-1$ private static final String SOLARIS_LARGE = "solarisLarge"; //$NON-NLS-1$ private static final String SOLARIS_MEDIUM = "solarisMedium"; //$NON-NLS-1$ private static final String SOLARIS_SMALL = "solarisSmall"; //$NON-NLS-1$ private static final String SOLARIS_TINY = "solarisTiny"; //$NON-NLS-1$ private static final String WIN32_16_LOW = "winSmallLow"; //$NON-NLS-1$ private static final String WIN32_16_HIGH = "winSmallHigh"; //$NON-NLS-1$ private static final String WIN32_24_LOW = "win24Low"; //$NON-NLS-1$ private static final String WIN32_32_LOW = "winMediumLow"; //$NON-NLS-1$ private static final String WIN32_32_HIGH = "winMediumHigh"; //$NON-NLS-1$ private static final String WIN32_48_LOW = "winLargeLow"; //$NON-NLS-1$ private static final String WIN32_48_HIGH = "winLargeHigh"; //$NON-NLS-1$ private static final String WIN32_256_HIGH = "winExtraLargeHigh"; //$NON-NLS-1$ private static final String OS_WIN32 = "win32";//$NON-NLS-1$ private static final String OS_LINUX = "linux";//$NON-NLS-1$ private static final String OS_SOLARIS = "solaris";//$NON-NLS-1$ private static final String OS_MACOSX = "macosx";//$NON-NLS-1$ // These must match Platform constant values private static final String ARCH_X86 = "x86"; //$NON-NLS-1$ private static final String ARCH_X86_64 = "x86_64"; //$NON-NLS-1$ private static final String ARCH_PPC = "ppc"; //$NON-NLS-1$ private static final String ARCH_IA_64 = "ia64"; //$NON-NLS-1$ private static final String ARCH_IA_64_32 = "ia64_32"; //$NON-NLS-1$ private static final String ARCH_PA_RISC = "PA_RISC"; //$NON-NLS-1$ private static final String ARCH_SPARC = "sparc"; //$NON-NLS-1$ //element names private static final String EL_FEATURES = "features"; //$NON-NLS-1$ private static final String EL_FEATURE = "feature"; //$NON-NLS-1$ private static final String EL_PLUGINS = "plugins"; //$NON-NLS-1$ private static final String EL_PLUGIN = "plugin"; //$NON-NLS-1$ private static final String EL_PRODUCT = "product"; //$NON-NLS-1$ private static final String EL_PROPERTY = "property"; //$NON-NLS-1$ private static final String EL_CONFIG_INI = "configIni"; //$NON-NLS-1$ private static final String EL_LAUNCHER = "launcher"; //$NON-NLS-1$ private static final String EL_LAUNCHER_ARGS = "launcherArgs"; //$NON-NLS-1$ private static final String EL_SPLASH = "splash"; //$NON-NLS-1$ private static final String EL_CONFIGURATIONS = "configurations"; //$NON-NLS-1$ private static final String EL_LICENSE = "license"; //$NON-NLS-1$ private static final String EL_URL = "url"; //$NON-NLS-1$ private static final String EL_TEXT = "text"; //$NON-NLS-1$ private static final String EL_ARCH_X86 = "argsX86"; //$NON-NLS-1$ private static final String EL_ARCH_X86_64 = "argsX86_64"; //$NON-NLS-1$ private static final String EL_ARCH_PPC = "argsPPC"; //$NON-NLS-1$ private static final String EL_ARCH_IA_64 = "argsIA_64"; //$NON-NLS-1$ private static final String EL_ARCH_IA_64_32 = "argsIA_64_32"; //$NON-NLS-1$ private static final String EL_ARCH_PA_RISC = "argsPA_RISC"; //$NON-NLS-1$ private static final String EL_ARCH_SPARC = "argsSPARC"; //$NON-NLS-1$ private static final String EL_REPOSITORIES = "repositories"; //$NON-NLS-1$ private static final String EL_REPOSITORY = "repository"; //$NON-NLS-1$ //These constants form a small state machine to parse the .product file private static final int STATE_START = 0; private static final int STATE_PRODUCT = 1; private static final int STATE_LAUNCHER = 2; private static final int STATE_LAUNCHER_ARGS = 3; private static final int STATE_PLUGINS = 4; private static final int STATE_FEATURES = 5; private static final int STATE_PROGRAM_ARGS = 6; private static final int STATE_PROGRAM_ARGS_LINUX = 7; private static final int STATE_PROGRAM_ARGS_MAC = 8; private static final int STATE_PROGRAM_ARGS_SOLARIS = 9; private static final int STATE_PROGRAM_ARGS_WIN = 10; private static final int STATE_VM_ARGS = 11; private static final int STATE_VM_ARGS_LINUX = 12; private static final int STATE_VM_ARGS_MAC = 13; private static final int STATE_VM_ARGS_SOLARIS = 14; private static final int STATE_VM_ARGS_WIN = 15; private static final int STATE_CONFIG_INI = 16; private static final int STATE_CONFIGURATIONS = 17; private static final int STATE_LICENSE = 18; private static final int STATE_LICENSE_URL = 19; private static final int STATE_LICENSE_TEXT = 20; private static final int STATE_ARCH_X86 = 21; private static final int STATE_ARCH_X86_64 = 22; private static final int STATE_ARCH_PPC = 23; private static final int STATE_ARCH_IA_64 = 24; private static final int STATE_ARCH_IA_64_32 = 25; private static final int STATE_ARCH_PA_RISC = 26; private static final int STATE_ARCH_SPARC = 27; private static final int STATE_REPOSITORIES = 28; private static final String PI_PDEBUILD = "org.eclipse.pde.build"; //$NON-NLS-1$ private final static int EXCEPTION_PRODUCT_FORMAT = 23; private final static int EXCEPTION_PRODUCT_FILE = 24; private int state = STATE_START; private int outerState = STATE_START; private String platformKeyPrefix = null; private SAXParser parser; private String launcherName = null; // private boolean useIco = false; private final Map<String, Collection<String>> icons = new HashMap<String, Collection<String>>(6); private String configPath = null; private final Map<String, String> platformSpecificConfigPaths = new HashMap<String, String>(); private String configPlatform = null; private String platformConfigPath = null; private String id = null; private String uid = null; private ProductContentType productContentType = null; protected List<FeatureEntry> plugins = new ArrayList<FeatureEntry>(); protected List<FeatureEntry> fragments = new ArrayList<FeatureEntry>(); private final List<FeatureEntry> features = new ArrayList<FeatureEntry>(); private final List<FeatureEntry> rootFeatures = new ArrayList<FeatureEntry>(); private String splashLocation = null; private String productName = null; private String application = null; private String version = null; private Properties launcherArgs = new Properties(); private final File location; private List<BundleInfo> bundleInfos; private Map<String, String> properties; private HashMap<String, HashMap<String, String>> filteredProperties; private boolean includeLaunchers = true; private String licenseURL; private String licenseText = null; private String currentOS; private final List<IRepositoryReference> repositories = new ArrayList<IRepositoryReference>(); private static String normalize(String text) { if (text == null || text.trim().length() == 0) return ""; //$NON-NLS-1$ StringBuffer result = new StringBuffer(text.length()); boolean haveSpace = false; for (int i = 0; i < text.length(); i++) { char c = text.charAt(i); if (Character.isWhitespace(c)) { if (haveSpace) continue; haveSpace = true; result.append(" "); //$NON-NLS-1$ } else { haveSpace = false; result.append(c); } } return result.toString(); } public ProductFile(String location, String os) throws CoreException { super(); this.currentOS = os; this.location = new File(location); try { parserFactory.setNamespaceAware(true); parser = parserFactory.newSAXParser(); InputStream in = new BufferedInputStream(new FileInputStream(location)); try { parser.parse(new InputSource(in), this); } finally { try { in.close(); } catch (IOException e) { // ignore exception on close (as it was done by Utils.close() before) } } } catch (ParserConfigurationException e) { throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e)); } catch (SAXException e) { throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e)); } catch (FileNotFoundException e) { throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FILE, NLS.bind(Messages.exception_missingElement, location), null)); } catch (IOException e) { throw new CoreException(new Status(IStatus.ERROR, PI_PDEBUILD, EXCEPTION_PRODUCT_FORMAT, NLS.bind(Messages.exception_productParse, location), e)); } } /** * Constructs a product file parser. */ public ProductFile(String location) throws Exception { super(); this.location = new File(location); parserFactory.setNamespaceAware(true); parser = parserFactory.newSAXParser(); InputStream in = new BufferedInputStream(new FileInputStream(location)); try { parser.parse(new InputSource(in), this); } finally { in.close(); } parser = null; } /** * Gets the name of the launcher specified in the .product file. */ public String getLauncherName() { return launcherName; } /** * Gets the location of the .product file. */ public File getLocation() { return location; } /** * Returns the properties found in .product file. Properties * are located in the <configurations> block of the file */ public Map<String, String> getConfigurationProperties() { return getConfigurationProperties(null, null); } /** * Returns the properties found in .product file that are valid * for the specified platform os and architecture. If there is no * platform os and/or architecture specified, return only the properties * that are not filtered by the unspecified os and/or arch. * Properties are located in the <configurations> block of the file */ public Map<String, String> getConfigurationProperties(String os, String arch) { // add all generic properties Map<String, String> result = properties != null ? properties : new HashMap<String, String>(); // add any properties filtered on os and/or arch if (filteredProperties != null) { String[] filteredKeys = new String[3]; // ".arch", "os.", "os.arch" if (os == null) { // only arch is specified. Provide properties defined for // all os and a specific architecture if (arch != null && arch.length() > 0) { filteredKeys[0] = "." + arch; //$NON-NLS-1$ } } else { if (arch == null) { // only os is specified. Provide properties defined for // specific os and all architectures. filteredKeys[1] = os + "."; //$NON-NLS-1$ } else { // os and arch specified. Provide properties defined for // the os, for the arch, and for both filteredKeys[0] = "." + arch; //$NON-NLS-1$ filteredKeys[1] = os + "."; //$NON-NLS-1$ filteredKeys[2] = os + "." + arch; //$NON-NLS-1$ } } for (int i = 0; i < filteredKeys.length; i++) { if (filteredKeys[i] != null) { // copy all mappings that are filtered for this os and/or arch HashMap<String, String> innerMap = filteredProperties.get(filteredKeys[i]); if (innerMap != null) { result.putAll(innerMap); } } } } if (application != null && !result.containsKey(PROPERTY_ECLIPSE_APPLICATION)) result.put(PROPERTY_ECLIPSE_APPLICATION, application); if (id != null && !result.containsKey(PROPERTY_ECLIPSE_PRODUCT)) result.put(PROPERTY_ECLIPSE_PRODUCT, id); return result; } /** * Returns a List<VersionedName> for each bundle that makes up this product. * @param includeFragments Indicates whether or not fragments should * be included in the list */ public List<IVersionedId> getBundles(boolean includeFragments) { List<IVersionedId> result = new LinkedList<IVersionedId>(); for (FeatureEntry plugin : plugins) { result.add(new VersionedId(plugin.getId(), plugin.getVersion())); } if (includeFragments) { for (FeatureEntry fragment : fragments) { result.add(new VersionedId(fragment.getId(), fragment.getVersion())); } } return result; } public boolean hasBundles(boolean includeFragments) { // implement directly; don't call the potentially overridden getBundles return !plugins.isEmpty() || (includeFragments && !fragments.isEmpty()); } private List<FeatureEntry> getBundleEntries(boolean includeFragments) { List<FeatureEntry> result = new LinkedList<FeatureEntry>(); result.addAll(plugins); if (includeFragments) result.addAll(fragments); return result; } /** * Returns a List<BundleInfo> for each bundle that has custom configuration data * in the product file. * @return A List<BundleInfo> */ public List<BundleInfo> getBundleInfos() { return bundleInfos != null ? bundleInfos : Collections.<BundleInfo> emptyList(); } /** * Returns a list<VersionedName> of fragments that constitute this product. */ public List<IVersionedId> getFragments() { List<IVersionedId> result = new LinkedList<IVersionedId>(); for (FeatureEntry fragment : fragments) { result.add(new VersionedId(fragment.getId(), fragment.getVersion())); } return result; } /** * Returns a List<VersionedName> of features that constitute this product. */ public List<IVersionedId> getFeatures() { return getFeatures(INCLUDED_FEATURES); } public boolean hasFeatures() { // implement directly; don't call the potentially overridden getFeatures return !features.isEmpty(); } public List<IVersionedId> getFeatures(int options) { List<IVersionedId> result = new LinkedList<IVersionedId>(); if ((options & INCLUDED_FEATURES) != 0) { for (FeatureEntry feature : features) { result.add(new VersionedId(feature.getId(), feature.getVersion())); } } if ((options & ROOT_FEATURES) != 0) { for (FeatureEntry feature : rootFeatures) { result.add(new VersionedId(feature.getId(), feature.getVersion())); } } return result; } public List<FeatureEntry> getProductEntries() { if (useFeatures()) { return features; } return getBundleEntries(true); } public boolean containsPlugin(String plugin) { List<IVersionedId> bundles = getBundles(true); for (IVersionedId versionedId : bundles) { if (versionedId.getId().equals(plugin)) { return true; } } return false; } public String[] getIcons() { return getIcons(currentOS); } public String[] getIcons(String os) { Collection<String> result = icons.get(os); if (result == null) return new String[0]; return result.toArray(new String[result.size()]); } public String getConfigIniPath(String os) { String specific = platformSpecificConfigPaths.get(os); return specific == null ? configPath : specific; } public String getConfigIniPath() { return configPath; } public boolean haveCustomConfig() { return configPath != null || platformSpecificConfigPaths.size() > 0; } /** * Returns the ID for this product. */ public String getId() { if (uid != null) return uid; return id; } public String getProductId() { return id; } /** * Returns the location (the bundle) that defines the splash screen */ public String getSplashLocation() { return splashLocation; } /** * Returns the product name. */ public String getProductName() { return productName; } /** * Returns the application identifier for this product. */ public String getApplication() { return application; } /** * Returns true if this product is built using feature, * false otherwise. */ public boolean useFeatures() { return productContentType == ProductContentType.FEATURES; } /** * Returns the version of the product */ public String getVersion() { return (version == null || version.length() == 0) ? "0.0.0" : version; //$NON-NLS-1$ } public boolean includeLaunchers() { return includeLaunchers; } public Map<String, BundleInfo> getConfigurationInfo() { Map<String, BundleInfo> result = new HashMap<String, BundleInfo>(); for (BundleInfo info : getBundleInfos()) { result.put(info.getSymbolicName(), info); } return result; } public Properties getConfigProperties() { Properties props = new Properties(); for (Entry<String, String> property : getConfigurationProperties().entrySet()) { props.setProperty(property.getKey(), property.getValue()); } return props; } /** * Returns the VM arguments for a specific platform. * If the empty string is used for the OS, this returns * the default VM arguments */ public String getVMArguments(String os) { return getVMArguments(os, null); } /** * Returns the VM arguments for a specific platform and architecture * combination. If the empty string is used for the architecture, this * returns the default arguments for the platform. If the empty string is * used for the OS, this returns the default VM arguments. */ public String getVMArguments(String os, String arch) { os = os == null ? "" : os; //$NON-NLS-1$ String key = null; if (os.equals(OS_WIN32)) { key = VM_ARGS_WIN; } else if (os.equals(OS_LINUX)) { key = VM_ARGS_LINUX; } else if (os.equals(OS_MACOSX)) { key = VM_ARGS_MAC; } else if (os.equals(OS_SOLARIS)) { key = VM_ARGS_SOLARIS; } arch = arch == null ? "" : arch; //$NON-NLS-1$ String archKey = null; if (arch.equals(ARCH_X86)) { archKey = EL_ARCH_X86; } else if (arch.equals(ARCH_X86_64)) { archKey = EL_ARCH_X86_64; } else if (arch.equals(ARCH_PPC)) { archKey = EL_ARCH_PPC; } else if (arch.equals(ARCH_IA_64)) { archKey = EL_ARCH_IA_64; } else if (arch.equals(ARCH_IA_64_32)) { archKey = EL_ARCH_IA_64_32; } else if (arch.equals(ARCH_PA_RISC)) { archKey = EL_ARCH_PA_RISC; } else if (arch.equals(ARCH_SPARC)) { archKey = EL_ARCH_SPARC; } String platformArchKey = null; String defaults = launcherArgs.getProperty(VM_ARGS); // architecture arguments independent of platform should be part // of the defaults. if (archKey != null) { String archOnAllPlatforms = launcherArgs.getProperty(VM_ARGS + "." + archKey); //$NON-NLS-1$ if (archOnAllPlatforms != null && archOnAllPlatforms.length() > 0) { defaults = defaults + " " + archOnAllPlatforms; //$NON-NLS-1$ } } String platform = null, platformAndArch = null, args = null; if (key != null) { // a platform with no arch specified platform = launcherArgs.getProperty(key); // platform + arch if (archKey != null) { platformArchKey = key + "." + archKey; //$NON-NLS-1$ platformAndArch = launcherArgs.getProperty(platformArchKey); } } if (defaults != null) { if (platform != null) args = platformAndArch != null ? defaults + " " + platform + " " + platformAndArch : defaults + " " + platform; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ else args = defaults; } else { if (platform != null) args = platformAndArch != null ? platform + " " + platformAndArch : platform; //$NON-NLS-1$ else args = platformAndArch != null ? platformAndArch : ""; //$NON-NLS-1$ } return normalize(args); } /** * Returns the program arguments for a specific platform. * If the empty string is used for the OS, this returns * the default program arguments */ public String getProgramArguments(String os) { return getProgramArguments(os, null); } /** * Returns the program arguments for a specific platform. * If the empty string is used for the OS, this returns * the default program arguments */ public String getProgramArguments(String os, String arch) { os = os == null ? "" : os; //$NON-NLS-1$ String key = null; if (os.equals(OS_WIN32)) { key = PROGRAM_ARGS_WIN; } else if (os.equals(OS_LINUX)) { key = PROGRAM_ARGS_LINUX; } else if (os.equals(OS_MACOSX)) { key = PROGRAM_ARGS_MAC; } else if (os.equals(OS_SOLARIS)) { key = PROGRAM_ARGS_SOLARIS; } arch = arch == null ? "" : arch; //$NON-NLS-1$ String archKey = null; if (arch.equals(ARCH_X86)) { archKey = EL_ARCH_X86; } else if (arch.equals(ARCH_X86_64)) { archKey = EL_ARCH_X86_64; } else if (arch.equals(ARCH_PPC)) { archKey = EL_ARCH_PPC; } else if (arch.equals(ARCH_IA_64)) { archKey = EL_ARCH_IA_64; } else if (arch.equals(ARCH_IA_64_32)) { archKey = EL_ARCH_IA_64_32; } else if (arch.equals(ARCH_PA_RISC)) { archKey = EL_ARCH_PA_RISC; } else if (arch.equals(ARCH_SPARC)) { archKey = EL_ARCH_SPARC; } String platformArchKey = null; String defaults = launcherArgs.getProperty(PROGRAM_ARGS); // architecture arguments independent of platform should be part // of the defaults. if (archKey != null) { String archOnAllPlatforms = launcherArgs.getProperty(PROGRAM_ARGS + "." + archKey); //$NON-NLS-1$ if (archOnAllPlatforms != null && archOnAllPlatforms.length() > 0) { defaults = defaults + " " + archOnAllPlatforms; //$NON-NLS-1$ } } String platform = null, platformAndArch = null, args = null; if (key != null) { // a platform with no arch specified platform = launcherArgs.getProperty(key); // platform + arch if (archKey != null) { platformArchKey = key + "." + archKey; //$NON-NLS-1$ platformAndArch = launcherArgs.getProperty(platformArchKey); } } if (defaults != null) { if (platform != null) args = platformAndArch != null ? defaults + " " + platform + " " + platformAndArch : defaults + " " + platform; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ else args = defaults; } else { if (platform != null) args = platformAndArch != null ? platform + " " + platformAndArch : platform; //$NON-NLS-1$ else args = platformAndArch != null ? platformAndArch : ""; //$NON-NLS-1$ } return normalize(args); } public String getLicenseText() { return licenseText; } public String getLicenseURL() { return licenseURL; } public List<IRepositoryReference> getRepositoryEntries() { return repositories; } @Override public void startElement(String uri, String localName, String qName, Attributes attributes) { switch (state) { case STATE_START : if (EL_PRODUCT.equals(localName)) { processProduct(attributes); state = STATE_PRODUCT; } break; case STATE_PRODUCT : if (EL_CONFIG_INI.equals(localName)) { processConfigIni(attributes); state = STATE_CONFIG_INI; } else if (EL_LAUNCHER.equals(localName)) { processLauncher(attributes); state = STATE_LAUNCHER; } else if (EL_PLUGINS.equals(localName)) { state = STATE_PLUGINS; } else if (EL_FEATURES.equals(localName)) { state = STATE_FEATURES; } else if (EL_LAUNCHER_ARGS.equals(localName)) { state = STATE_LAUNCHER_ARGS; } else if (EL_SPLASH.equals(localName)) { splashLocation = attributes.getValue(ATTRIBUTE_LOCATION); } else if (EL_CONFIGURATIONS.equals(localName)) { state = STATE_CONFIGURATIONS; } else if (EL_LICENSE.equals(localName)) { state = STATE_LICENSE; } else if (EL_REPOSITORIES.equals(localName)) { state = STATE_REPOSITORIES; } break; case STATE_CONFIG_INI : processConfigIniPlatform(localName, true); break; case STATE_LAUNCHER : if (OS_SOLARIS.equals(localName)) { processSolaris(attributes); } else if ("win".equals(localName)) { //$NON-NLS-1$ processWin(attributes); } else if (OS_LINUX.equals(localName)) { processLinux(attributes); } else if (OS_MACOSX.equals(localName)) { processMac(attributes); } if ("ico".equals(localName)) { //$NON-NLS-1$ processIco(attributes); } else if ("bmp".equals(localName)) { //$NON-NLS-1$ processBmp(attributes); } break; case STATE_LAUNCHER_ARGS : if (PROGRAM_ARGS.equals(localName)) { state = STATE_PROGRAM_ARGS; } else if (PROGRAM_ARGS_LINUX.equals(localName)) { state = STATE_PROGRAM_ARGS_LINUX; } else if (PROGRAM_ARGS_MAC.equals(localName)) { state = STATE_PROGRAM_ARGS_MAC; } else if (PROGRAM_ARGS_SOLARIS.equals(localName)) { state = STATE_PROGRAM_ARGS_SOLARIS; } else if (PROGRAM_ARGS_WIN.equals(localName)) { state = STATE_PROGRAM_ARGS_WIN; } else if (VM_ARGS.equals(localName)) { state = STATE_VM_ARGS; } else if (VM_ARGS_LINUX.equals(localName)) { state = STATE_VM_ARGS_LINUX; } else if (VM_ARGS_MAC.equals(localName)) { state = STATE_VM_ARGS_MAC; } else if (VM_ARGS_SOLARIS.equals(localName)) { state = STATE_VM_ARGS_SOLARIS; } else if (VM_ARGS_WIN.equals(localName)) { state = STATE_VM_ARGS_WIN; } break; // For all argument states. Set a platform key prefix representing // the outer state (platform) of the launcher arguments and then // set the state of the inner state (architecture). case STATE_PROGRAM_ARGS : platformKeyPrefix = PROGRAM_ARGS; setArchState(localName); break; case STATE_PROGRAM_ARGS_LINUX : platformKeyPrefix = PROGRAM_ARGS_LINUX; setArchState(localName); break; case STATE_PROGRAM_ARGS_MAC : platformKeyPrefix = PROGRAM_ARGS_MAC; setArchState(localName); break; case STATE_PROGRAM_ARGS_SOLARIS : platformKeyPrefix = PROGRAM_ARGS_SOLARIS; setArchState(localName); break; case STATE_PROGRAM_ARGS_WIN : platformKeyPrefix = PROGRAM_ARGS_WIN; setArchState(localName); break; case STATE_VM_ARGS : platformKeyPrefix = VM_ARGS; setArchState(localName); break; case STATE_VM_ARGS_LINUX : platformKeyPrefix = VM_ARGS_LINUX; setArchState(localName); break; case STATE_VM_ARGS_MAC : platformKeyPrefix = VM_ARGS_MAC; setArchState(localName); break; case STATE_VM_ARGS_SOLARIS : platformKeyPrefix = VM_ARGS_SOLARIS; setArchState(localName); break; case STATE_VM_ARGS_WIN : platformKeyPrefix = VM_ARGS_WIN; setArchState(localName); break; case STATE_PLUGINS : if (EL_PLUGIN.equals(localName)) { processPlugin(attributes); } break; case STATE_REPOSITORIES : if (EL_REPOSITORY.equals(localName)) { processRepositoryInformation(attributes); } break; case STATE_LICENSE : if (EL_URL.equals(localName)) { state = STATE_LICENSE_URL; } else if (EL_TEXT.equals(localName)) { licenseText = ""; //$NON-NLS-1$ state = STATE_LICENSE_TEXT; } break; case STATE_FEATURES : if (EL_FEATURE.equals(localName)) { processFeature(attributes); } break; case STATE_CONFIGURATIONS : if (EL_PLUGIN.equals(localName)) { processPluginConfiguration(attributes); } else if (EL_PROPERTY.equals(localName)) { processPropertyConfiguration(attributes); } break; } } private void setArchState(String archName) { outerState = state; if (EL_ARCH_X86.equals(archName)) { state = STATE_ARCH_X86; } else if (EL_ARCH_X86_64.equals(archName)) { state = STATE_ARCH_X86_64; } else if (EL_ARCH_PPC.equals(archName)) { state = STATE_ARCH_PPC; } else if (EL_ARCH_IA_64.equals(archName)) { state = STATE_ARCH_IA_64; } else if (EL_ARCH_IA_64_32.equals(archName)) { state = STATE_ARCH_IA_64_32; } else if (EL_ARCH_PA_RISC.equals(archName)) { state = STATE_ARCH_PA_RISC; } else if (EL_ARCH_SPARC.equals(archName)) { state = STATE_ARCH_SPARC; } } /** * Processes the property tag in the .product file. These tags contain * a Name and Value pair. For each tag (with a non-null name), a property * is created. */ private void processPropertyConfiguration(Attributes attributes) { String name = attributes.getValue(ATTRIBUTE_NAME); String value = attributes.getValue(ATTRIBUTE_VALUE); String os = attributes.getValue(ATTRIBUTE_OS); if (os == null) os = ""; //$NON-NLS-1$ String arch = attributes.getValue(ATTRIBUTE_ARCH); if (arch == null) arch = ""; //$NON-NLS-1$ String propOSArchKey = os + "." + arch; //$NON-NLS-1$ if (name == null) return; if (value == null) value = ""; //$NON-NLS-1$ if (propOSArchKey.length() <= 1) { // this is a generic property for all platforms and arch if (properties == null) properties = new HashMap<String, String>(); properties.put(name, value); } else { // store the property in the filtered map, keyed by "os.arch" if (filteredProperties == null) filteredProperties = new HashMap<String, HashMap<String, String>>(); HashMap<String, String> filteredMap = filteredProperties.get(propOSArchKey); if (filteredMap == null) { filteredMap = new HashMap<String, String>(); filteredProperties.put(propOSArchKey, filteredMap); } filteredMap.put(name, value); } } private void processPluginConfiguration(Attributes attributes) { BundleInfo info = new BundleInfo(); info.setSymbolicName(attributes.getValue(ATTRIBUTE_ID)); info.setVersion(attributes.getValue(ATTRIBUTE_VERSION)); String value = attributes.getValue(ATTRIBUTE_START_LEVEL); if (value != null) { int startLevel = Integer.parseInt(value); if (startLevel > 0) info.setStartLevel(startLevel); } value = attributes.getValue(ATTRIBUTE_AUTO_START); if (value != null) info.setMarkedAsStarted(Boolean.parseBoolean(value)); if (bundleInfos == null) bundleInfos = new ArrayList<BundleInfo>(); bundleInfos.add(info); } private void processRepositoryInformation(Attributes attributes) { try { URI uri = URIUtil.fromString(attributes.getValue(ATTRIBUTE_LOCATION)); boolean enabled = Boolean.parseBoolean(attributes.getValue(ATTRIBUTE_ENABLED)); // First add a metadata repository repositories.add(new RepositoryReference(uri, null, IRepository.TYPE_METADATA, enabled ? IRepository.ENABLED : IRepository.NONE)); // Now a colocated artifact repository repositories.add(new RepositoryReference(uri, null, IRepository.TYPE_ARTIFACT, enabled ? IRepository.ENABLED : IRepository.NONE)); } catch (URISyntaxException e) { // ignore malformed URI's. These should have already been caught by the UI } } @Override public void endElement(String uri, String localName, String qName) { switch (state) { case STATE_PLUGINS : if (EL_PLUGINS.equals(localName)) state = STATE_PRODUCT; break; case STATE_FEATURES : if (EL_FEATURES.equals(localName)) state = STATE_PRODUCT; break; case STATE_LAUNCHER_ARGS : if (EL_LAUNCHER_ARGS.equals(localName)) state = STATE_PRODUCT; break; case STATE_LAUNCHER : if (EL_LAUNCHER.equals(localName)) state = STATE_PRODUCT; break; case STATE_CONFIGURATIONS : if (EL_CONFIGURATIONS.equals(localName)) state = STATE_PRODUCT; break; case STATE_LICENSE : if (EL_LICENSE.equals(localName)) state = STATE_PRODUCT; break; case STATE_PROGRAM_ARGS : case STATE_PROGRAM_ARGS_LINUX : case STATE_PROGRAM_ARGS_MAC : case STATE_PROGRAM_ARGS_SOLARIS : case STATE_PROGRAM_ARGS_WIN : case STATE_VM_ARGS : case STATE_VM_ARGS_LINUX : case STATE_VM_ARGS_MAC : case STATE_VM_ARGS_SOLARIS : case STATE_VM_ARGS_WIN : state = STATE_LAUNCHER_ARGS; break; case STATE_LICENSE_URL : case STATE_LICENSE_TEXT : state = STATE_LICENSE; break; case STATE_ARCH_X86 : case STATE_ARCH_X86_64 : case STATE_ARCH_PPC : case STATE_ARCH_IA_64 : case STATE_ARCH_IA_64_32 : case STATE_ARCH_PA_RISC : case STATE_ARCH_SPARC : state = outerState; break; case STATE_CONFIG_INI : if (EL_CONFIG_INI.equals(localName)) state = STATE_PRODUCT; else processConfigIniPlatform(localName, false); break; case STATE_REPOSITORIES : if (EL_REPOSITORIES.equals(localName)) state = STATE_PRODUCT; break; } } @Override public void characters(char[] ch, int start, int length) { switch (state) { case STATE_PROGRAM_ARGS : addLaunchArgumentToMap(PROGRAM_ARGS, String.valueOf(ch, start, length)); break; case STATE_PROGRAM_ARGS_LINUX : addLaunchArgumentToMap(PROGRAM_ARGS_LINUX, String.valueOf(ch, start, length)); break; case STATE_PROGRAM_ARGS_MAC : addLaunchArgumentToMap(PROGRAM_ARGS_MAC, String.valueOf(ch, start, length)); break; case STATE_PROGRAM_ARGS_SOLARIS : addLaunchArgumentToMap(PROGRAM_ARGS_SOLARIS, String.valueOf(ch, start, length)); break; case STATE_PROGRAM_ARGS_WIN : addLaunchArgumentToMap(PROGRAM_ARGS_WIN, String.valueOf(ch, start, length)); break; case STATE_VM_ARGS : addLaunchArgumentToMap(VM_ARGS, String.valueOf(ch, start, length)); break; case STATE_VM_ARGS_LINUX : addLaunchArgumentToMap(VM_ARGS_LINUX, String.valueOf(ch, start, length)); break; case STATE_VM_ARGS_MAC : addLaunchArgumentToMap(VM_ARGS_MAC, String.valueOf(ch, start, length)); break; case STATE_VM_ARGS_SOLARIS : addLaunchArgumentToMap(VM_ARGS_SOLARIS, String.valueOf(ch, start, length)); break; case STATE_VM_ARGS_WIN : addLaunchArgumentToMap(VM_ARGS_WIN, String.valueOf(ch, start, length)); break; case STATE_ARCH_X86 : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_X86, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_X86_64 : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_X86_64, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_PPC : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_PPC, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_IA_64 : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_IA_64, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_IA_64_32 : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_IA_64_32, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_PA_RISC : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_PA_RISC, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_ARCH_SPARC : addLaunchArgumentToMap(platformKeyPrefix + "." + EL_ARCH_SPARC, String.valueOf(ch, start, length)); //$NON-NLS-1$ break; case STATE_CONFIG_INI : if (platformConfigPath != null) platformConfigPath += String.valueOf(ch, start, length); break; case STATE_LICENSE_URL : licenseURL = String.valueOf(ch, start, length); break; case STATE_LICENSE_TEXT : if (licenseText != null) licenseText += String.valueOf(ch, start, length); break; } } private void addLaunchArgumentToMap(String key, String value) { if (launcherArgs == null) launcherArgs = new Properties(); String oldValue = launcherArgs.getProperty(key); if (oldValue != null) launcherArgs.setProperty(key, oldValue + value); else launcherArgs.setProperty(key, value); } protected void processPlugin(Attributes attributes) { String fragment = attributes.getValue(ATTRIBUTE_FRAGMENT); String pluginId = attributes.getValue(ATTRIBUTE_ID); String pluginVersion = attributes.getValue(ATTRIBUTE_VERSION); FeatureEntry entry = new FeatureEntry(pluginId, pluginVersion != null ? pluginVersion : GENERIC_VERSION_NUMBER, true); entry.setFragment(Boolean.parseBoolean(fragment)); if (fragment != null && Boolean.parseBoolean(fragment)) { fragments.add(entry); } else { plugins.add(entry); } } private void processFeature(Attributes attributes) { String featureId = attributes.getValue(ATTRIBUTE_ID); String featureVersion = attributes.getValue(ATTRIBUTE_VERSION); FeatureInstallMode installMode = FeatureInstallMode.parse(attributes.getValue(ATTRIBUTE_FEATURE_INSTALL_MODE)); FeatureEntry featureEntry = new FeatureEntry(featureId, featureVersion != null ? featureVersion : GENERIC_VERSION_NUMBER, false); switch (installMode) { case ROOT : rootFeatures.add(featureEntry); break; default : features.add(featureEntry); } } private void processProduct(Attributes attributes) { id = attributes.getValue(ATTRIBUTE_ID); uid = attributes.getValue(ATTRIBUTE_UID); productName = attributes.getValue(ATTRIBUTE_NAME); application = attributes.getValue(ATTRIBUTE_APPLICATION); if (attributes.getIndex(ATTRIBUTE_INCLUDE_LAUNCHERS) >= 0) includeLaunchers = Boolean.valueOf(attributes.getValue(ATTRIBUTE_INCLUDE_LAUNCHERS)); String contentTypeString = attributes.getValue(ATTRIBUTE_CONTENT_TYPE); if (contentTypeString != null) productContentType = ProductContentType.toProductContentType(contentTypeString); if (productContentType == null) { // useFeatures attribute is taken into account only if the contentType attribute is missing String use = attributes.getValue("useFeatures"); //$NON-NLS-1$ // for backward compatibility with the old behavior if (use != null && Boolean.parseBoolean(use)) productContentType = ProductContentType.FEATURES; else productContentType = ProductContentType.BUNDLES; } version = attributes.getValue(ATTRIBUTE_VERSION); } private void processConfigIni(Attributes attributes) { String path = null; if ("custom".equals(attributes.getValue("use"))) { //$NON-NLS-1$//$NON-NLS-2$ path = attributes.getValue(ATTRIBUTE_PATH); } String os = attributes.getValue("os"); //$NON-NLS-1$ if (os != null && os.length() > 0) { // TODO should we allow a platform-specific default to over-ride a custom generic path? if (path != null) platformSpecificConfigPaths.put(os, path); } else if (path != null) { configPath = path; } } private void processConfigIniPlatform(String key, boolean begin) { if (begin) { configPlatform = key; platformConfigPath = ""; //$NON-NLS-1$ } else if (configPlatform.equals(key) && platformConfigPath.length() > 0) { platformSpecificConfigPaths.put(key, platformConfigPath); platformConfigPath = null; } } private void processLauncher(Attributes attributes) { launcherName = attributes.getValue(ATTRIBUTE_NAME); } private void addIcon(String os, String value) { if (value == null) return; File iconFile = new File(value); if (!iconFile.isFile()) { //workspace Location instanceLocation = ServiceHelper.getService(Activator.getContext(), Location.class, Location.INSTANCE_FILTER); if (instanceLocation != null && instanceLocation.getURL() != null) { File workspace = URLUtil.toFile(instanceLocation.getURL()); if (workspace != null) iconFile = new File(workspace, value); } } if (!iconFile.isFile()) iconFile = new File(location.getParentFile(), value); Collection<String> list = icons.get(os); if (list == null) { list = new ArrayList<String>(6); icons.put(os, list); } list.add(iconFile.getAbsolutePath()); } private void processSolaris(Attributes attributes) { addIcon(OS_SOLARIS, attributes.getValue(SOLARIS_LARGE)); addIcon(OS_SOLARIS, attributes.getValue(SOLARIS_MEDIUM)); addIcon(OS_SOLARIS, attributes.getValue(SOLARIS_SMALL)); addIcon(OS_SOLARIS, attributes.getValue(SOLARIS_TINY)); } private void processWin(Attributes attributes) { // useIco = Boolean.parseBoolean(attributes.getValue(P_USE_ICO)); } private void processIco(Attributes attributes) { addIcon(OS_WIN32, attributes.getValue(ATTRIBUTE_PATH)); } private void processBmp(Attributes attributes) { addIcon(OS_WIN32, attributes.getValue(WIN32_16_HIGH)); addIcon(OS_WIN32, attributes.getValue(WIN32_16_LOW)); addIcon(OS_WIN32, attributes.getValue(WIN32_24_LOW)); addIcon(OS_WIN32, attributes.getValue(WIN32_32_HIGH)); addIcon(OS_WIN32, attributes.getValue(WIN32_32_LOW)); addIcon(OS_WIN32, attributes.getValue(WIN32_48_HIGH)); addIcon(OS_WIN32, attributes.getValue(WIN32_48_LOW)); addIcon(OS_WIN32, attributes.getValue(WIN32_256_HIGH)); } private void processLinux(Attributes attributes) { addIcon(OS_LINUX, attributes.getValue(ATTRIBUTE_ICON)); } private void processMac(Attributes attributes) { addIcon(OS_MACOSX, attributes.getValue(ATTRIBUTE_ICON)); } public ProductContentType getProductContentType() { return productContentType; } }