| /******************************************************************************* |
| * 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; |
| } |
| } |