blob: d5297eb8ff97e2806d34b73025ea4ade26cafd64 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2007, 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
*******************************************************************************/
package org.eclipse.equinox.internal.p2.update;
import java.io.*;
import java.net.*;
import java.util.ArrayList;
import java.util.StringTokenizer;
import javax.xml.parsers.*;
import org.eclipse.core.runtime.URIUtil;
import org.eclipse.equinox.internal.p2.core.helpers.SecureXMLUtil;
import org.eclipse.equinox.p2.core.ProvisionException;
import org.eclipse.osgi.util.NLS;
import org.w3c.dom.*;
import org.xml.sax.SAXException;
/**
* Parser for platform.xml files.
*
* @since 1.0
*/
public class ConfigurationParser implements ConfigurationConstants {
static final String PLATFORM_BASE = "platform:/base/"; //$NON-NLS-1$
private URL osgiInstallArea;
/*
* Parse the given file handle which points to a platform.xml file and a configuration object.
* Returns null if the file doesn't exist.
*/
static Configuration parse(File file, URL osgiInstallArea) throws ProvisionException {
return new ConfigurationParser(osgiInstallArea).internalParse(file);
}
private ConfigurationParser(URL osgiInstallArea) {
this.osgiInstallArea = osgiInstallArea;
}
/*
* Create a feature object based on the given DOM node.
* Return the new feature.
*/
private Feature createFeature(Node node, Site site) {
Feature result = new Feature(site);
String id = getAttribute(node, ATTRIBUTE_ID);
if (id != null)
result.setId(id);
String url = getAttribute(node, ATTRIBUTE_URL);
if (url != null)
result.setUrl(url);
String version = getAttribute(node, ATTRIBUTE_VERSION);
if (version != null)
result.setVersion(version);
String pluginIdentifier = getAttribute(node, ATTRIBUTE_PLUGIN_IDENTIFIER);
if (pluginIdentifier != null)
result.setPluginIdentifier(pluginIdentifier);
String pluginVersion = getAttribute(node, ATTRIBUTE_PLUGIN_VERSION);
// plug-in version is the same as the feature version if it is missing
if (pluginVersion == null)
pluginVersion = version;
if (pluginVersion != null)
result.setPluginVersion(pluginVersion);
String application = getAttribute(node, ATTRIBUTE_APPLICATION);
if (application != null)
result.setApplication(application);
// get primary flag
String flag = getAttribute(node, ATTRIBUTE_PRIMARY);
if (flag != null && Boolean.parseBoolean(flag))
result.setPrimary(true);
// get install locations
String locations = getAttribute(node, ATTRIBUTE_ROOT);
if (locations != null) {
StringTokenizer tokenizer = new StringTokenizer(locations, ","); //$NON-NLS-1$
ArrayList<URL> rootList = new ArrayList<URL>();
while (tokenizer.hasMoreTokens()) {
try {
URL rootEntry = new URL(tokenizer.nextToken().trim());
rootList.add(rootEntry);
} catch (MalformedURLException e) {
// skip bad entries ...
}
}
URL[] roots = rootList.toArray(new URL[rootList.size()]);
result.setRoots(roots);
}
return result;
}
/*
* Create the features from the given DOM node.
*/
private void createFeatures(Node node, Site site) {
NodeList children = node.getChildNodes();
int size = children.getLength();
for (int i = 0; i < size; i++) {
Node child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE)
continue;
if (!ELEMENT_FEATURE.equalsIgnoreCase(child.getNodeName()))
continue;
Feature feature = createFeature(child, site);
if (feature != null)
site.addFeature(feature);
}
}
/*
* Create a site based on the given DOM node.
*/
private Site createSite(Node node) {
Site result = new Site();
String policy = getAttribute(node, ATTRIBUTE_POLICY);
if (policy != null)
result.setPolicy(policy);
String enabled = getAttribute(node, ATTRIBUTE_ENABLED);
if (enabled != null)
result.setEnabled(Boolean.parseBoolean(enabled));
String updateable = getAttribute(node, ATTRIBUTE_UPDATEABLE);
if (updateable != null)
result.setUpdateable(Boolean.parseBoolean(updateable));
String url = getAttribute(node, ATTRIBUTE_URL);
if (url != null) {
try {
// do this to ensure the location is an encoded URI
URI uri = URIUtil.fromString(url);
URI osgiURI = osgiInstallArea != null ? URIUtil.toURI(osgiInstallArea) : null;
result.setUrl(getLocation(uri, osgiURI).toString());
} catch (URISyntaxException e) {
result.setUrl(url);
}
}
String linkFile = getAttribute(node, ATTRIBUTE_LINKFILE);
if (linkFile != null)
result.setLinkFile(linkFile);
String list = getAttribute(node, ATTRIBUTE_LIST);
if (list != null)
for (StringTokenizer tokenizer = new StringTokenizer(list, ","); tokenizer.hasMoreTokens();) //$NON-NLS-1$
result.addPlugin(tokenizer.nextToken());
createFeatures(node, result);
return result;
}
/*
* Convert the given url string to an absolute url. If the string is
* platform:/base/ then return a string which represents the osgi
* install area.
*/
private URI getLocation(URI location, URI osgiArea) {
if (osgiArea == null)
return location;
if (PLATFORM_BASE.equals(location.toString()))
return osgiArea;
return URIUtil.makeAbsolute(location, osgiArea);
}
/*
* Return the attribute with the given name, or null if it does
* not exist.
*/
private String getAttribute(Node node, String name) {
NamedNodeMap attributes = node.getAttributes();
Node temp = attributes.getNamedItem(name);
return temp == null ? null : temp.getNodeValue();
}
/*
* Load the given file into a DOM document.
*/
private Document load(InputStream input) throws ParserConfigurationException, IOException, SAXException {
// load the feature xml
DocumentBuilderFactory factory = SecureXMLUtil.newSecureDocumentBuilderFactory();
DocumentBuilder builder = factory.newDocumentBuilder();
input = new BufferedInputStream(input);
try {
return builder.parse(input);
} finally {
if (input != null)
try {
input.close();
} catch (IOException e) {
// ignore
}
}
}
/*
* Parse the given file handle which points to a platform.xml file and a configuration object.
* Returns null if the file doesn't exist.
*/
private Configuration internalParse(File file) throws ProvisionException {
if (!file.exists()) {
// remove from cache since it doesn't exist anymore on disk
ConfigurationCache.put(file, null);
return null;
}
// have we read this before?
Configuration result = ConfigurationCache.get(file);
if (result != null)
return result;
try {
InputStream input = new BufferedInputStream(new FileInputStream(file));
Document document = load(input);
result = process(document);
// save for future use
ConfigurationCache.put(file, result);
return result;
} catch (IOException e) {
throw new ProvisionException(NLS.bind(Messages.error_reading_config, file), e);
} catch (ParserConfigurationException e) {
throw new ProvisionException(Messages.error_parsing_config, e);
} catch (SAXException e) {
throw new ProvisionException(Messages.error_parsing_config, e);
}
}
/*
* Process the given DOM document and create the appropriate
* site objects.
*/
private Configuration process(Document document) {
Node node = getConfigElement(document);
if (node == null)
return null;
Configuration configuration = createConfiguration(node);
NodeList children = node.getChildNodes();
int size = children.getLength();
for (int i = 0; i < size; i++) {
Node child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE)
continue;
if (!ELEMENT_SITE.equalsIgnoreCase(child.getNodeName()))
continue;
Site site = createSite(child);
if (site != null)
configuration.add(site);
}
return configuration;
}
private Configuration createConfiguration(Node node) {
Configuration result = new Configuration();
String value = getAttribute(node, ATTRIBUTE_DATE);
if (value != null)
result.setDate(value);
value = getAttribute(node, ATTRIBUTE_TRANSIENT);
if (value != null)
result.setTransient(Boolean.parseBoolean(value));
value = getAttribute(node, ATTRIBUTE_SHARED_UR);
if (value != null)
result.setSharedUR(value);
value = getAttribute(node, ATTRIBUTE_VERSION);
if (value != null)
result.setVersion(value);
return result;
}
private Node getConfigElement(Document doc) {
NodeList children = doc.getChildNodes();
int size = children.getLength();
for (int i = 0; i < size; i++) {
Node child = children.item(i);
if (child.getNodeType() != Node.ELEMENT_NODE)
continue;
if (ELEMENT_CONFIG.equalsIgnoreCase(child.getNodeName()))
return child;
}
return null;
}
}