diff options
Diffstat (limited to 'bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginParser.java')
-rw-r--r-- | bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginParser.java | 708 |
1 files changed, 708 insertions, 0 deletions
diff --git a/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginParser.java b/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginParser.java new file mode 100644 index 000000000..e6cb4d3a5 --- /dev/null +++ b/bundles/org.eclipse.osgi.compatibility.plugins/src/org/eclipse/osgi/compatibility/plugins/PluginParser.java @@ -0,0 +1,708 @@ +/******************************************************************************* + * Copyright (c) 2000, 2013 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.osgi.compatibility.plugins; + +import java.io.InputStream; +import java.util.*; +import javax.xml.parsers.SAXParserFactory; +import org.eclipse.osgi.container.Module; +import org.eclipse.osgi.framework.log.FrameworkLogEntry; +import org.eclipse.osgi.internal.framework.EquinoxConfiguration; +import org.eclipse.osgi.internal.framework.EquinoxContainer; +import org.eclipse.osgi.util.NLS; +import org.osgi.framework.*; +import org.osgi.util.tracker.ServiceTracker; +import org.xml.sax.*; +import org.xml.sax.helpers.DefaultHandler; + +/** + * Internal class. + */ +public class PluginParser extends DefaultHandler implements IModel { + private static ServiceTracker<SAXParserFactory, SAXParserFactory> xmlTracker = null; + + private final EquinoxConfiguration configuration; + private PluginInfo manifestInfo = new PluginInfo(); + Version target; // The targeted platform for the given manifest + static final Version TARGET21 = new Version(2, 1, 0); + + public class PluginInfo implements IPluginInfo { + String schemaVersion; + String pluginId; + String version; + String vendor; + + // an ordered list of library path names. + List<String> libraryPaths; + // TODO Should get rid of the libraries map and just have a + // list of library export statements instead. Library paths must + // preserve order. + Map<String, List<String>> libraries; //represent the libraries and their export statement + ArrayList<PluginParser.Prerequisite> requires; + private boolean requiresExpanded = false; //indicates if the requires have been processed. + boolean compatibilityFound = false; //set to true is the requirement list contain compatilibity + String pluginClass; + String masterPluginId; + String masterVersion; + String masterMatch; + private Set<String> filters; + String pluginName; + boolean singleton; + boolean fragment; + private final static String TARGET21_STRING = "2.1"; //$NON-NLS-1$ + boolean hasExtensionExtensionPoints = false; + + public boolean isFragment() { + return fragment; + } + + public String toString() { + return "plugin-id: " + pluginId + " version: " + version + " libraries: " + libraries + " class:" + pluginClass + " master: " + masterPluginId + " master-version: " + masterVersion + " requires: " + requires + " singleton: " + singleton; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ //$NON-NLS-5$ //$NON-NLS-6$ //$NON-NLS-7$ //$NON-NLS-8$ + } + + public Map<String, List<String>> getLibraries() { + if (libraries == null) + return new HashMap<String, List<String>>(0); + return libraries; + } + + public ArrayList<Prerequisite> getRequires() { + if (!TARGET21.equals(target) && schemaVersion == null && !requiresExpanded) { + requiresExpanded = true; + if (requires == null) { + requires = new ArrayList<Prerequisite>(1); + requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); + requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); + } else { + //Add elements on the requirement list of ui and help. + for (int i = 0; i < requires.size(); i++) { + Prerequisite analyzed = requires.get(i); + if ("org.eclipse.ui".equals(analyzed.getName())) { //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.ui.workbench.texteditor", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.jface.text", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.ui.editors", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.ui.views", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.ui.ide", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + } else if ("org.eclipse.help".equals(analyzed.getName())) { //$NON-NLS-1$ + requires.add(i + 1, new Prerequisite("org.eclipse.help.base", null, true, analyzed.isExported(), null)); //$NON-NLS-1$ + } else if (PluginConverterImpl.PI_RUNTIME.equals(analyzed.getName()) && !compatibilityFound) { + requires.add(i + 1, new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, analyzed.isExported(), null)); + } + } + if (!requires.contains(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null))) { + requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY, null, false, false, null)); + } + //Remove any prereq on runtime and add a prereq on runtime 2.1 + //This is used to recognize the version for which the given plugin was initially targeted. + Prerequisite runtimePrereq = new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null); + requires.remove(runtimePrereq); + requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, TARGET21_STRING, false, false, IModel.PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL)); + } + } + if (requires == null) + return requires = new ArrayList<Prerequisite>(0); + + return requires; + } + + public String getMasterId() { + return masterPluginId; + } + + public String getMasterVersion() { + return masterVersion; + } + + public String getMasterMatch() { + return masterMatch; + } + + public String getPluginClass() { + return pluginClass; + } + + public String getUniqueId() { + return pluginId; + } + + public String getVersion() { + return version; + } + + public Set<String> getPackageFilters() { + return filters; + } + + public String[] getLibrariesName() { + if (libraryPaths == null) + return new String[0]; + return libraryPaths.toArray(new String[libraryPaths.size()]); + } + + public String getPluginName() { + return pluginName; + } + + public String getProviderName() { + return vendor; + } + + public boolean isSingleton() { + return singleton; + } + + public boolean hasExtensionExtensionPoints() { + return hasExtensionExtensionPoints; + } + + public String getRoot() { + return isFragment() ? FRAGMENT : PLUGIN; + } + + /* + * Provides some basic form of validation. Since plugin/fragment is the only mandatory + * attribute, it is the only one we cara about here. + */ + public String validateForm() { + if (this.pluginId == null) + return NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_ID, getRoot()}); + if (this.pluginName == null) + return NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_NAME, getRoot()}); + if (this.version == null) + return NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), PLUGIN_VERSION, getRoot()}); + if (isFragment() && this.masterPluginId == null) + return NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), FRAGMENT_PLUGIN_ID, getRoot()}); + if (isFragment() && this.masterVersion == null) + return NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_MISSING_ATTRIBUTE, new String[] {getRoot(), FRAGMENT_PLUGIN_VERSION, getRoot()}); + return null; + } + } + + // Current State Information + Stack<Integer> stateStack = new Stack<Integer>(); + + // Current object stack (used to hold the current object we are populating in this plugin info + Stack<Object> objectStack = new Stack<Object>(); + Locator locator = null; + + // Valid States + private static final int IGNORED_ELEMENT_STATE = 0; + private static final int INITIAL_STATE = 1; + private static final int PLUGIN_STATE = 2; + private static final int PLUGIN_RUNTIME_STATE = 3; + private static final int PLUGIN_REQUIRES_STATE = 4; + private static final int PLUGIN_EXTENSION_POINT_STATE = 5; + private static final int PLUGIN_EXTENSION_STATE = 6; + private static final int RUNTIME_LIBRARY_STATE = 7; + private static final int LIBRARY_EXPORT_STATE = 8; + private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9; + private static final int FRAGMENT_STATE = 11; + + public PluginParser(EquinoxConfiguration configuration, Version target) { + super(); + this.configuration = configuration; + this.target = target; + } + + /** + * Receive a Locator object for document events. + * + * <p> + * By default, do nothing. Application writers may override this method in + * a subclass if they wish to store the locator for use with other document + * events. + * </p> + * + * @param locator A locator for all SAX document events. + * @see org.xml.sax.ContentHandler#setDocumentLocator(org.xml.sax.Locator) + * @see org.xml.sax.Locator + */ + public void setDocumentLocator(Locator locator) { + this.locator = locator; + } + + public void endDocument() { + // nothing + } + + public void endElement(String uri, String elementName, String qName) { + switch (stateStack.peek().intValue()) { + case IGNORED_ELEMENT_STATE : + stateStack.pop(); + break; + case INITIAL_STATE : + // shouldn't get here + // internalError(Policy.bind("parse.internalStack", elementName)); //$NON-NLS-1$ + break; + case PLUGIN_STATE : + case FRAGMENT_STATE : + break; + case PLUGIN_RUNTIME_STATE : + if (elementName.equals(RUNTIME)) { + stateStack.pop(); + } + break; + case PLUGIN_REQUIRES_STATE : + if (elementName.equals(PLUGIN_REQUIRES)) { + stateStack.pop(); + objectStack.pop(); + } + break; + case PLUGIN_EXTENSION_POINT_STATE : + if (elementName.equals(EXTENSION_POINT)) { + stateStack.pop(); + } + break; + case PLUGIN_EXTENSION_STATE : + if (elementName.equals(EXTENSION)) { + stateStack.pop(); + } + break; + case RUNTIME_LIBRARY_STATE : + if (elementName.equals(LIBRARY)) { + String curLibrary = (String) objectStack.pop(); + if (!curLibrary.trim().equals("")) { //$NON-NLS-1$ + @SuppressWarnings("unchecked") + List<String> exports = (List<String>) objectStack.pop(); + if (manifestInfo.libraries == null) { + manifestInfo.libraries = new HashMap<String, List<String>>(3); + manifestInfo.libraryPaths = new ArrayList<String>(3); + } + manifestInfo.libraries.put(curLibrary, exports); + manifestInfo.libraryPaths.add(curLibrary.replace('\\', '/')); + } + stateStack.pop(); + } + break; + case LIBRARY_EXPORT_STATE : + if (elementName.equals(LIBRARY_EXPORT)) { + stateStack.pop(); + } + break; + case PLUGIN_REQUIRES_IMPORT_STATE : + if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { + stateStack.pop(); + } + break; + } + } + + public void error(SAXParseException ex) { + logStatus(ex); + } + + public void fatalError(SAXParseException ex) throws SAXException { + logStatus(ex); + throw ex; + } + + public void handleExtensionPointState(String elementName, Attributes attributes) { + // nothing to do for extension-points' children + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + manifestInfo.hasExtensionExtensionPoints = true; + } + + public void handleExtensionState(String elementName, Attributes attributes) { + // nothing to do for extensions' children + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + manifestInfo.hasExtensionExtensionPoints = true; + } + + public void handleInitialState(String elementName, Attributes attributes) { + if (elementName.equals(PLUGIN)) { + stateStack.push(new Integer(PLUGIN_STATE)); + parsePluginAttributes(attributes); + } else if (elementName.equals(FRAGMENT)) { + manifestInfo.fragment = true; + stateStack.push(new Integer(FRAGMENT_STATE)); + parseFragmentAttributes(attributes); + } else { + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + internalError(elementName); + } + } + + public void handleLibraryExportState(String elementName, Attributes attributes) { + // All elements ignored. + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + } + + public void handleLibraryState(String elementName, Attributes attributes) { + if (elementName.equals(LIBRARY_EXPORT)) { + // Change State + stateStack.push(new Integer(LIBRARY_EXPORT_STATE)); + // The top element on the stack much be a library element + String currentLib = (String) objectStack.peek(); + if (attributes == null) + return; + String maskValue = attributes.getValue("", LIBRARY_EXPORT_MASK); //$NON-NLS-1$ + // pop off the library - already in currentLib + objectStack.pop(); + @SuppressWarnings("unchecked") + List<String> exportMask = (List<String>) objectStack.peek(); + // push library back on + objectStack.push(currentLib); + //Split the export upfront + if (maskValue != null) { + StringTokenizer tok = new StringTokenizer(maskValue, ","); //$NON-NLS-1$ + while (tok.hasMoreTokens()) { + String value = tok.nextToken(); + if (!exportMask.contains(maskValue)) + exportMask.add(value.trim()); + } + } + return; + } + if (elementName.equals(LIBRARY_PACKAGES)) { + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + return; + } + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + internalError(elementName); + return; + } + + public void handlePluginState(String elementName, Attributes attributes) { + if (elementName.equals(RUNTIME)) { + // We should only have one Runtime element in a plugin or fragment + Object whatIsIt = objectStack.peek(); + if ((whatIsIt instanceof PluginInfo) && ((PluginInfo) objectStack.peek()).libraries != null) { + // This is at least the 2nd Runtime element we have hit. Ignore it. + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + return; + } + stateStack.push(new Integer(PLUGIN_RUNTIME_STATE)); + // Push a new vector to hold all the library entries objectStack.push(new Vector()); + return; + } + if (elementName.equals(PLUGIN_REQUIRES)) { + stateStack.push(new Integer(PLUGIN_REQUIRES_STATE)); + // Push a new vector to hold all the prerequisites + objectStack.push(new ArrayList<String>()); + parseRequiresAttributes(attributes); + return; + } + if (elementName.equals(EXTENSION_POINT)) { + // mark the plugin as singleton and ignore all elements under extension (if there are any) + manifestInfo.singleton = true; + stateStack.push(new Integer(PLUGIN_EXTENSION_POINT_STATE)); + return; + } + if (elementName.equals(EXTENSION)) { + // mark the plugin as singleton and ignore all elements under extension (if there are any) + manifestInfo.singleton = true; + stateStack.push(new Integer(PLUGIN_EXTENSION_STATE)); + return; + } + // If we get to this point, the element name is one we don't currently accept. + // Set the state to indicate that this element will be ignored + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + internalError(elementName); + } + + public void handleRequiresImportState(String elementName, Attributes attributes) { + // All elements ignored. + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + } + + public void handleRequiresState(String elementName, Attributes attributes) { + if (elementName.equals(PLUGIN_REQUIRES_IMPORT)) { + parsePluginRequiresImport(attributes); + return; + } + // If we get to this point, the element name is one we don't currently accept. + // Set the state to indicate that this element will be ignored + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + internalError(elementName); + } + + public void handleRuntimeState(String elementName, Attributes attributes) { + if (elementName.equals(LIBRARY)) { + // Change State + stateStack.push(new Integer(RUNTIME_LIBRARY_STATE)); + // Process library attributes + parseLibraryAttributes(attributes); + return; + } + // If we get to this point, the element name is one we don't currently accept. + // Set the state to indicate that this element will be ignored + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + internalError(elementName); + } + + private void logStatus(SAXParseException ex) { + String name = ex.getSystemId(); + if (name == null) + name = ""; //$NON-NLS-1$ + else + name = name.substring(1 + name.lastIndexOf("/")); //$NON-NLS-1$ + String msg; + if (name.equals("")) //$NON-NLS-1$ + msg = NLS.bind(PluginConverterMsg.parse_error, ex.getMessage()); + else + msg = NLS.bind(PluginConverterMsg.parse_errorNameLineColumn, new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()}); + + configuration.getHookRegistry().getContainer().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, msg, null); + } + + synchronized public PluginInfo parsePlugin(InputStream in) throws Exception { + Module systemModule = configuration.getHookRegistry().getContainer().getStorage().getModuleContainer().getModule(0); + Bundle systemBundle = systemModule.getBundle(); + BundleContext systemContext = systemBundle.getBundleContext(); + SAXParserFactory factory = acquireXMLParsing(systemContext); + if (factory == null) { + configuration.getHookRegistry().getContainer().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, PluginConverterMsg.ECLIPSE_CONVERTER_NO_SAX_FACTORY, null); + return null; + } + + factory.setNamespaceAware(true); + factory.setNamespaceAware(true); + try { + factory.setFeature("http://xml.org/sax/features/string-interning", true); //$NON-NLS-1$ + } catch (SAXException se) { + // ignore; we can still operate without string-interning + } + factory.setValidating(false); + factory.newSAXParser().parse(in, this); + return manifestInfo; + } + + public static SAXParserFactory acquireXMLParsing(BundleContext context) { + if (xmlTracker == null) { + xmlTracker = new ServiceTracker<SAXParserFactory, SAXParserFactory>(context, "javax.xml.parsers.SAXParserFactory", null); //$NON-NLS-1$ + xmlTracker.open(); + } + SAXParserFactory result = xmlTracker.getService(); + if (result != null) + return result; + // backup to using jaxp to create a new instance + return SAXParserFactory.newInstance(); + } + + public static void releaseXMLParsing() { + if (xmlTracker != null) + xmlTracker.close(); + } + + public void parseFragmentAttributes(Attributes attributes) { + // process attributes + objectStack.push(manifestInfo); + int len = attributes.getLength(); + for (int i = 0; i < len; i++) { + String attrName = attributes.getLocalName(i); + String attrValue = attributes.getValue(i).trim(); + if (attrName.equals(FRAGMENT_ID)) + manifestInfo.pluginId = attrValue; + else if (attrName.equals(FRAGMENT_NAME)) + manifestInfo.pluginName = attrValue; + else if (attrName.equals(FRAGMENT_VERSION)) + manifestInfo.version = attrValue; + else if (attrName.equals(FRAGMENT_PROVIDER)) + manifestInfo.vendor = attrValue; + else if (attrName.equals(FRAGMENT_PLUGIN_ID)) + manifestInfo.masterPluginId = attrValue; + else if (attrName.equals(FRAGMENT_PLUGIN_VERSION)) + manifestInfo.masterVersion = attrValue; + else if (attrName.equals(FRAGMENT_PLUGIN_MATCH)) + manifestInfo.masterMatch = attrValue; + } + } + + public void parseLibraryAttributes(Attributes attributes) { + // Push a vector to hold the export mask + objectStack.push(new ArrayList<String>()); + String current = attributes.getValue("", LIBRARY_NAME); //$NON-NLS-1$ + objectStack.push(current); + } + + public void parsePluginAttributes(Attributes attributes) { + // process attributes + objectStack.push(manifestInfo); + int len = attributes.getLength(); + for (int i = 0; i < len; i++) { + String attrName = attributes.getLocalName(i); + String attrValue = attributes.getValue(i).trim(); + if (attrName.equals(PLUGIN_ID)) + manifestInfo.pluginId = attrValue; + else if (attrName.equals(PLUGIN_NAME)) + manifestInfo.pluginName = attrValue; + else if (attrName.equals(PLUGIN_VERSION)) + manifestInfo.version = attrValue; + else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER))) + manifestInfo.vendor = attrValue; + else if (attrName.equals(PLUGIN_CLASS)) + manifestInfo.pluginClass = attrValue; + } + } + + public class Prerequisite { + String name; + String version; + boolean optional; + boolean export; + String match; + + public boolean isExported() { + return export; + } + + public String getMatch() { + return match; + } + + public String getName() { + return name; + } + + public boolean isOptional() { + return optional; + } + + public String getVersion() { + return version; + } + + public Prerequisite(String preqName, String prereqVersion, boolean isOtional, boolean isExported, String prereqMatch) { + name = preqName; + version = prereqVersion; + optional = isOtional; + export = isExported; + match = prereqMatch; + } + + public String toString() { + return name; + } + + public boolean equals(Object prereq) { + if (!(prereq instanceof Prerequisite)) + return false; + return name.equals(((Prerequisite) prereq).name); + } + + public int hashCode() { + return name.hashCode(); + } + } + + public void parsePluginRequiresImport(Attributes attributes) { + if (manifestInfo.requires == null) { + manifestInfo.requires = new ArrayList<Prerequisite>(); + // to avoid cycles + // if (!manifestInfo.pluginId.equals(PluginConverterImpl.PI_RUNTIME)) //$NON-NLS-1$ + // manifestInfo.requires.add(new Prerequisite(PluginConverterImpl.PI_RUNTIME, null, false, false, null)); //$NON-NLS-1$ + } + // process attributes + String plugin = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN); //$NON-NLS-1$ + if (plugin == null) + return; + if (plugin.equals(PluginConverterImpl.PI_BOOT)) + return; + if (plugin.equals(PluginConverterImpl.PI_RUNTIME_COMPATIBILITY)) + manifestInfo.compatibilityFound = true; + String version = attributes.getValue("", PLUGIN_REQUIRES_PLUGIN_VERSION); //$NON-NLS-1$ + String optional = attributes.getValue("", PLUGIN_REQUIRES_OPTIONAL); //$NON-NLS-1$ + String export = attributes.getValue("", PLUGIN_REQUIRES_EXPORT); //$NON-NLS-1$ + String match = attributes.getValue("", PLUGIN_REQUIRES_MATCH); //$NON-NLS-1$ + manifestInfo.requires.add(new Prerequisite(plugin, version, "true".equalsIgnoreCase(optional) ? true : false, "true".equalsIgnoreCase(export) ? true : false, match)); //$NON-NLS-1$ //$NON-NLS-2$ + } + + public void parseRequiresAttributes(Attributes attributes) { + //Nothing to do. + } + + static String replace(String s, String from, String to) { + String str = s; + int fromLen = from.length(); + int toLen = to.length(); + int ix = str.indexOf(from); + while (ix != -1) { + str = str.substring(0, ix) + to + str.substring(ix + fromLen); + ix = str.indexOf(from, ix + toLen); + } + return str; + } + + public void startDocument() { + stateStack.push(new Integer(INITIAL_STATE)); + } + + public void startElement(String uri, String elementName, String qName, Attributes attributes) { + switch (stateStack.peek().intValue()) { + case INITIAL_STATE : + handleInitialState(elementName, attributes); + break; + case FRAGMENT_STATE : + case PLUGIN_STATE : + handlePluginState(elementName, attributes); + break; + case PLUGIN_RUNTIME_STATE : + handleRuntimeState(elementName, attributes); + break; + case PLUGIN_REQUIRES_STATE : + handleRequiresState(elementName, attributes); + break; + case PLUGIN_EXTENSION_POINT_STATE : + handleExtensionPointState(elementName, attributes); + break; + case PLUGIN_EXTENSION_STATE : + handleExtensionState(elementName, attributes); + break; + case RUNTIME_LIBRARY_STATE : + handleLibraryState(elementName, attributes); + break; + case LIBRARY_EXPORT_STATE : + handleLibraryExportState(elementName, attributes); + break; + case PLUGIN_REQUIRES_IMPORT_STATE : + handleRequiresImportState(elementName, attributes); + break; + default : + stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); + } + } + + public void warning(SAXParseException ex) { + logStatus(ex); + } + + private void internalError(String elementName) { + String message = NLS.bind(PluginConverterMsg.ECLIPSE_CONVERTER_PARSE_UNKNOWNTOP_ELEMENT, elementName); + configuration.getHookRegistry().getContainer().getLogServices().log(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, (manifestInfo.pluginId == null ? message : "Plug-in : " + manifestInfo.pluginId + ", " + message), null); //$NON-NLS-1$//$NON-NLS-2$ + } + + /** + * @throws SAXException + */ + public void processingInstruction(String instructionTarget, String data) throws SAXException { + // Since 3.0, a processing instruction of the form <?eclipse version="3.0"?> at + // the start of the manifest file is used to indicate the plug-in manifest + // schema version in effect. Pre-3.0 (i.e., 2.1) plug-in manifest files do not + // have one of these, and this is how we can distinguish the manifest of a + // pre-3.0 plug-in from a post-3.0 one (for compatibility tranformations). + if (instructionTarget.equalsIgnoreCase("eclipse")) { //$NON-NLS-1$ + // just the presence of this processing instruction indicates that this + // plug-in is at least 3.0 + manifestInfo.schemaVersion = "3.0"; //$NON-NLS-1$ + StringTokenizer tokenizer = new StringTokenizer(data, "=\""); //$NON-NLS-1$ + while (tokenizer.hasMoreTokens()) { + String token = tokenizer.nextToken(); + if (token.equalsIgnoreCase("version")) { //$NON-NLS-1$ + if (!tokenizer.hasMoreTokens()) { + break; + } + manifestInfo.schemaVersion = tokenizer.nextToken(); + break; + } + } + } + } +} |