blob: ea4f0c125fede2b3444e217cd17b655fad4e3ff5 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 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
*******************************************************************************/
package org.eclipse.equinox.internal.p2.publisher.features;
import java.io.*;
import java.util.*;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.eclipse.equinox.internal.p2.publisher.IProductDescriptor;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.helpers.DefaultHandler;
/**
*
* @since 3.1
*/
public class ProductFile extends DefaultHandler implements IProductDescriptor {
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 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$
private static final String PRODUCT = "product"; //$NON-NLS-1$
private static final String CONFIG_INI = "configIni"; //$NON-NLS-1$
private static final String LAUNCHER = "launcher"; //$NON-NLS-1$
private static final String LAUNCHER_ARGS = "launcherArgs"; //$NON-NLS-1$
private static final String PLUGINS = "plugins"; //$NON-NLS-1$
private static final String FEATURES = "features"; //$NON-NLS-1$
private static final String SPLASH = "splash"; //$NON-NLS-1$
// private static final String P_USE_ICO = "useIco"; //$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 int state = STATE_START;
private SAXParser parser;
private String launcherName = null;
private Map icons = new HashMap(6);
private String configPath = null;
private String id = null;
private boolean useFeatures = false;
private List plugins = null;
private List fragments = null;
private List features = null;
private String splashLocation = null;
private String productName = null;
private String application = null;
private String version = null;
private Properties launcherArgs = new Properties();
private final Map platformSpecificConfigPaths = new HashMap();
private File location;
private static String normalize(String text) {
if (text == null || text.trim().length() == 0)
return ""; //$NON-NLS-1$
text = text.replaceAll("\\r|\\n|\\f|\\t", " "); //$NON-NLS-1$ //$NON-NLS-2$
return text.replaceAll("\\s+", " "); //$NON-NLS-1$ //$NON-NLS-2$
}
/**
* Constructs a feature parser.
*/
public ProductFile(String location) throws Exception {
super();
this.location = new File(location);
// try {
parserFactory.setNamespaceAware(true);
parser = parserFactory.newSAXParser();
InputStream in = new BufferedInputStream(new FileInputStream(location));
parser.parse(new InputSource(in), this);
parser = null;
// } 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));
// }
}
public String getLauncherName() {
return launcherName;
}
public File getLocation() {
return location;
}
public List getBundles(boolean includeFragments) {
List p = plugins != null ? plugins : Collections.EMPTY_LIST;
if (!includeFragments)
return p;
List f = fragments != null ? fragments : Collections.EMPTY_LIST;
int size = p.size() + f.size();
if (size == 0)
return Collections.EMPTY_LIST;
List both = new ArrayList(size);
both.addAll(p);
both.addAll(f);
return both;
}
public List getFragments() {
if (fragments == null)
return Collections.EMPTY_LIST;
return fragments;
}
public List getFeatures() {
if (features == null)
return Collections.EMPTY_LIST;
return features;
}
public boolean containsPlugin(String plugin) {
return (plugins != null && plugins.contains(plugin)) || (fragments != null && fragments.contains(plugin));
}
/**
* Parses the specified url and constructs a feature
*/
public String[] getIcons(String os) {
Collection result = (Collection) icons.get(os);
if (result == null)
return new String[0];
return (String[]) result.toArray(new String[result.size()]);
}
public String getConfigIniPath(String os) {
String specific = (String) platformSpecificConfigPaths.get(os);
return specific == null ? configPath : specific;
}
public String getConfigIniPath() {
return configPath;
}
public String getId() {
return id;
}
public String getSplashLocation() {
return splashLocation;
}
public String getProductName() {
return productName;
}
public String getApplication() {
return application;
}
public boolean useFeatures() {
return useFeatures;
}
public String getVersion() {
return (version == null) ? "0.0.0" : version; //$NON-NLS-1$
}
public String getVMArguments(String os) {
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;
}
String prefix = launcherArgs.getProperty(VM_ARGS);
String platform = null, args = null;
if (key != null)
platform = launcherArgs.getProperty(key);
if (prefix != null)
args = platform != null ? prefix + " " + platform : prefix; //$NON-NLS-1$
else
args = platform != null ? platform : ""; //$NON-NLS-1$
return normalize(args);
}
public String getProgramArguments(String os) {
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;
}
String prefix = launcherArgs.getProperty(PROGRAM_ARGS);
String platform = null, args = null;
if (key != null)
platform = launcherArgs.getProperty(key);
if (prefix != null)
args = platform != null ? prefix + " " + platform : prefix; //$NON-NLS-1$
else
args = platform != null ? platform : ""; //$NON-NLS-1$
return normalize(args);
}
public void startElement(String uri, String localName, String qName, Attributes attributes) {
switch (state) {
case STATE_START :
if (PRODUCT.equals(localName)) {
processProduct(attributes);
state = STATE_PRODUCT;
}
break;
case STATE_PRODUCT :
if (CONFIG_INI.equals(localName)) {
processConfigIni(attributes);
} else if (LAUNCHER.equals(localName)) {
processLauncher(attributes);
state = STATE_LAUNCHER;
} else if (PLUGINS.equals(localName)) {
state = STATE_PLUGINS;
} else if (FEATURES.equals(localName)) {
state = STATE_FEATURES;
} else if (LAUNCHER_ARGS.equals(localName)) {
state = STATE_LAUNCHER_ARGS;
} else if (SPLASH.equals(localName)) {
splashLocation = attributes.getValue("location"); //$NON-NLS-1$
}
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;
case STATE_PLUGINS :
if ("plugin".equals(localName)) { //$NON-NLS-1$
processPlugin(attributes);
}
break;
case STATE_FEATURES :
if ("feature".equals(localName)) { //$NON-NLS-1$
processFeature(attributes);
}
break;
}
}
public void endElement(String uri, String localName, String qName) {
switch (state) {
case STATE_PLUGINS :
if (PLUGINS.equals(localName))
state = STATE_PRODUCT;
break;
case STATE_FEATURES :
if (FEATURES.equals(localName))
state = STATE_PRODUCT;
break;
case STATE_LAUNCHER_ARGS :
if (LAUNCHER_ARGS.equals(localName))
state = STATE_PRODUCT;
break;
case STATE_LAUNCHER :
if (LAUNCHER.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;
}
}
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;
}
}
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);
}
private void processPlugin(Attributes attributes) {
String fragment = attributes.getValue("fragment"); //$NON-NLS-1$
if (fragment != null && new Boolean(fragment).booleanValue()) {
if (fragments == null)
fragments = new ArrayList();
fragments.add(attributes.getValue("id")); //$NON-NLS-1$
} else {
if (plugins == null)
plugins = new ArrayList();
plugins.add(attributes.getValue("id")); //$NON-NLS-1$
}
}
private void processFeature(Attributes attributes) {
if (features == null)
features = new ArrayList();
features.add(attributes.getValue("id")); //$NON-NLS-1$
}
private void processProduct(Attributes attributes) {
id = attributes.getValue("id"); //$NON-NLS-1$
productName = attributes.getValue("name"); //$NON-NLS-1$
application = attributes.getValue("application"); //$NON-NLS-1$
String use = attributes.getValue("useFeatures"); //$NON-NLS-1$
if (use != null)
useFeatures = Boolean.valueOf(use).booleanValue();
version = attributes.getValue("version"); //$NON-NLS-1$
}
private void processConfigIni(Attributes attributes) {
String path = null;
if ("custom".equals(attributes.getValue("use"))) { //$NON-NLS-1$//$NON-NLS-2$
path = attributes.getValue("path"); //$NON-NLS-1$
}
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 {
configPath = path;
}
}
private void processLauncher(Attributes attributes) {
launcherName = attributes.getValue("name"); //$NON-NLS-1$
}
private void addIcon(String os, String value) {
if (value == null)
return;
Collection list = (Collection) icons.get(os);
if (list == null) {
list = new ArrayList(6);
icons.put(os, list);
}
if (!new File(value).isAbsolute())
value = new File(location.getParentFile(), value).getAbsolutePath();
list.add(value);
}
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.valueOf(attributes.getValue(P_USE_ICO)).booleanValue();
}
private void processIco(Attributes attributes) {
addIcon(OS_WIN32, attributes.getValue("path")); //$NON-NLS-1$
}
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));
}
private void processLinux(Attributes attributes) {
addIcon(OS_LINUX, attributes.getValue("icon")); //$NON-NLS-1$
}
private void processMac(Attributes attributes) {
addIcon(OS_MACOSX, attributes.getValue("icon")); //$NON-NLS-1$
}
}