| /******************************************************************************* |
| * Copyright (c) 2000, 2004 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Common Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/cpl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.core.internal.model; |
| |
| import java.util.*; |
| import javax.xml.parsers.SAXParserFactory; |
| import org.eclipse.core.internal.runtime.InternalPlatform; |
| import org.eclipse.core.internal.runtime.Policy; |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.core.runtime.model.*; |
| import org.osgi.framework.ServiceReference; |
| import org.xml.sax.*; |
| import org.xml.sax.helpers.DefaultHandler; |
| |
| public class PluginParser extends DefaultHandler implements IModel { |
| |
| // concrete object factory |
| Factory factory; |
| |
| // File name for this plugin or fragment |
| // This to help with error reporting |
| String locationName = null; |
| |
| // Current State Information |
| Stack stateStack = new Stack(); |
| |
| // Current object stack (used to hold the current object we are |
| // populating in this plugin descriptor |
| Stack objectStack = new Stack(); |
| |
| 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 LIBRARY_PACKAGES_STATE = 12; |
| private static final int PLUGIN_REQUIRES_IMPORT_STATE = 9; |
| private static final int CONFIGURATION_ELEMENT_STATE = 10; |
| private static final int FRAGMENT_STATE = 11; |
| |
| // Keep a group of vectors as a temporary scratch space. These |
| // vectors will be used to populate arrays in the plugin descriptor |
| // once processing of the XML file is complete. |
| private static final int EXTENSION_POINT_INDEX = 0; |
| private static final int EXTENSION_INDEX = 1; |
| private static final int LAST_INDEX = 1; |
| private Vector scratchVectors[] = new Vector[LAST_INDEX + 1]; |
| |
| private ServiceReference parserReference; |
| |
| public PluginParser(Factory factory) { |
| super(); |
| this.factory = factory; |
| } |
| |
| /** |
| * 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 |
| * @see org.xml.sax.Locator |
| */ |
| public void setDocumentLocator(Locator locator) { |
| this.locator = locator; |
| } |
| |
| public void characters(char[] ch, int start, int length) { |
| int state = ((Integer) stateStack.peek()).intValue(); |
| if (state != CONFIGURATION_ELEMENT_STATE) |
| return; |
| if (state == CONFIGURATION_ELEMENT_STATE) { |
| // Accept character data within an element, is when it is |
| // part of a configuration element (i.e. an element within an EXTENSION element |
| ConfigurationElementModel currentConfigElement = (ConfigurationElementModel) objectStack.peek(); |
| String value = new String(ch, start, length); |
| String oldValue = currentConfigElement.getValueAsIs(); |
| if (oldValue == null) { |
| if (value.trim().length() != 0) |
| currentConfigElement.setValue(value); |
| } else { |
| currentConfigElement.setValue(oldValue + value); |
| } |
| } |
| } |
| |
| public void endDocument() { |
| } |
| |
| public void endElement(String uri, String elementName, String qName) { |
| switch (((Integer) 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 : |
| if (elementName.equals(PLUGIN) || elementName.equals(FRAGMENT)) { |
| stateStack.pop(); |
| PluginModel root = (PluginModel) objectStack.peek(); |
| |
| // Put the extension points into this plugin |
| Vector extPointVector = scratchVectors[EXTENSION_POINT_INDEX]; |
| if (extPointVector.size() > 0) { |
| root.setDeclaredExtensionPoints((ExtensionPointModel[]) extPointVector.toArray(new ExtensionPointModel[extPointVector.size()])); |
| scratchVectors[EXTENSION_POINT_INDEX].removeAllElements(); |
| } |
| |
| // Put the extensions into this plugin too |
| Vector extVector = scratchVectors[EXTENSION_INDEX]; |
| if (extVector.size() > 0) { |
| root.setDeclaredExtensions((ExtensionModel[]) extVector.toArray(new ExtensionModel[extVector.size()])); |
| scratchVectors[EXTENSION_INDEX].removeAllElements(); |
| } |
| } |
| break; |
| case PLUGIN_RUNTIME_STATE : |
| if (elementName.equals(RUNTIME)) { |
| stateStack.pop(); |
| // take the vector of library entries and put them into the plugin |
| // descriptor |
| Vector libVector = (Vector) objectStack.pop(); |
| if (libVector.size() > 0) { |
| PluginModel model = (PluginModel) objectStack.peek(); |
| model.setRuntime((LibraryModel[]) libVector.toArray(new LibraryModel[libVector.size()])); |
| } |
| } |
| break; |
| case PLUGIN_REQUIRES_STATE : |
| if (elementName.equals(PLUGIN_REQUIRES)) { |
| stateStack.pop(); |
| // take the vector of prerequisites and put them into the plugin |
| // descriptor |
| Vector importVector = (Vector) objectStack.pop(); |
| if (importVector.size() > 0) { |
| PluginModel parentDescriptor = (PluginModel) objectStack.peek(); |
| parentDescriptor.setRequires((PluginPrerequisiteModel[]) importVector.toArray(new PluginPrerequisiteModel[importVector.size()])); |
| } |
| } |
| break; |
| case PLUGIN_EXTENSION_POINT_STATE : |
| if (elementName.equals(EXTENSION_POINT)) { |
| stateStack.pop(); |
| } |
| break; |
| case PLUGIN_EXTENSION_STATE : |
| if (elementName.equals(EXTENSION)) { |
| stateStack.pop(); |
| // Finish up extension object |
| ExtensionModel currentExtension = (ExtensionModel) objectStack.pop(); |
| PluginModel parent = (PluginModel) objectStack.peek(); |
| currentExtension.setParent(parent); |
| scratchVectors[EXTENSION_INDEX].addElement(currentExtension); |
| } |
| break; |
| case RUNTIME_LIBRARY_STATE : |
| if (elementName.equals(LIBRARY)) { |
| LibraryModel curLibrary = (LibraryModel) objectStack.pop(); |
| // Clean up the exports for this library entry |
| Vector exportsVector = (Vector) objectStack.pop(); |
| if (exportsVector.size() > 0) { |
| curLibrary.setExports((String[]) exportsVector.toArray(new String[exportsVector.size()])); |
| } |
| |
| // Add this library element to the vector "runtime" on the stack |
| Vector libraryVector = (Vector) objectStack.peek(); |
| libraryVector.addElement(curLibrary); |
| 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; |
| case CONFIGURATION_ELEMENT_STATE : |
| // We don't care what the element name was |
| stateStack.pop(); |
| // Now finish up the configuration element object |
| ConfigurationElementModel currentConfigElement = (ConfigurationElementModel) objectStack.pop(); |
| |
| String value = currentConfigElement.getValueAsIs(); |
| if (value != null) { |
| currentConfigElement.setValue(value.trim()); |
| } |
| |
| Object parent = objectStack.peek(); |
| currentConfigElement.setParent(parent); |
| if (((Integer) stateStack.peek()).intValue() == PLUGIN_EXTENSION_STATE) { |
| // Want to add this configuration element to the subelements of an extension |
| ConfigurationElementModel[] oldValues = (ConfigurationElementModel[]) ((ExtensionModel) parent).getSubElements(); |
| int size = (oldValues == null) ? 0 : oldValues.length; |
| ConfigurationElementModel[] newValues = new ConfigurationElementModel[size + 1]; |
| for (int i = 0; i < size; i++) { |
| newValues[i] = oldValues[i]; |
| } |
| newValues[size] = currentConfigElement; |
| ((ExtensionModel) parent).setSubElements(newValues); |
| } else { |
| ConfigurationElementModel[] oldValues = (ConfigurationElementModel[]) ((ConfigurationElementModel) parent).getSubElements(); |
| int size = (oldValues == null) ? 0 : oldValues.length; |
| ConfigurationElementModel[] newValues = new ConfigurationElementModel[size + 1]; |
| for (int i = 0; i < size; i++) { |
| newValues[i] = oldValues[i]; |
| } |
| newValues[size] = currentConfigElement; |
| ((ConfigurationElementModel) parent).setSubElements(newValues); |
| } |
| 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) { |
| |
| // We ignore all elements under extension points (if there are any) |
| stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); |
| internalError(Policy.bind("parse.unknownElement", EXTENSION_POINT, elementName)); //$NON-NLS-1$ |
| } |
| |
| public void handleExtensionState(String elementName, Attributes attributes) { |
| |
| // You need to change the state here even though we will be executing the same |
| // code for ExtensionState and ConfigurationElementState. We ignore the name |
| // of the element for ConfigurationElements. When we are wrapping up, we will |
| // want to add each configuration element object to the subElements vector of |
| // its parent configuration element object. However, the first configuration |
| // element object we created (the last one we pop off the stack) will need to |
| // be added to a vector in the extension object called _configuration. |
| stateStack.push(new Integer(CONFIGURATION_ELEMENT_STATE)); |
| |
| // create a new Configuration Element and push it onto the object stack |
| ConfigurationElementModel currentConfigurationElement = factory.createConfigurationElement(); |
| objectStack.push(currentConfigurationElement); |
| currentConfigurationElement.setName(elementName); |
| |
| // Processing the attributes of a configuration element involves creating |
| // a new configuration property for each attribute and populating the configuration |
| // property with the name/value pair of the attribute. Note there will be one |
| // configuration property for each attribute |
| parseConfigurationElementAttributes(attributes); |
| } |
| |
| public void handleInitialState(String elementName, Attributes attributes) { |
| if (elementName.equals(PLUGIN)) { |
| stateStack.push(new Integer(PLUGIN_STATE)); |
| parsePluginAttributes(attributes); |
| } else if (elementName.equals(FRAGMENT)) { |
| stateStack.push(new Integer(FRAGMENT_STATE)); |
| parseFragmentAttributes(attributes); |
| } else { |
| stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); |
| internalError(Policy.bind("parse.unknownTopElement", elementName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void handleLibraryExportState(String elementName, Attributes attributes) { |
| |
| // All elements ignored. |
| stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); |
| internalError(Policy.bind("parse.unknownElement", LIBRARY_EXPORT, elementName)); //$NON-NLS-1$ |
| } |
| |
| 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 |
| LibraryModel currentLib = (LibraryModel) objectStack.peek(); |
| |
| if (attributes == null) |
| return; |
| |
| String maskValue = null; |
| |
| // Process Attributes |
| 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(LIBRARY_EXPORT_MASK)) |
| maskValue = attrValue; |
| else |
| internalError(Policy.bind("parse.unknownAttribute", LIBRARY, attrName)); //$NON-NLS-1$ |
| } |
| |
| // set up mask tables |
| // pop off the library - already in currentLib |
| objectStack.pop(); |
| Vector exportMask = (Vector) objectStack.peek(); |
| // push library back on |
| objectStack.push(currentLib); |
| if ((maskValue != null) && (!exportMask.contains(maskValue))) |
| exportMask.addElement(maskValue); |
| return; |
| } |
| |
| if (elementName.equals(LIBRARY_PACKAGES)) { |
| LibraryModel currentLib = (LibraryModel) objectStack.peek(); |
| if (attributes == null) |
| return; |
| for (int i = 0; i < attributes.getLength(); i++) { |
| if (LIBRARY_PACKAGES_PREFIXES.equals(attributes.getLocalName(i))) { |
| String line = attributes.getValue(i); |
| String[] prefixes = getArrayFromList(line); |
| currentLib.setPackagePrefixes(prefixes); |
| } |
| } |
| return; |
| } |
| |
| // Any other element is invalid |
| stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); |
| internalError(Policy.bind("parse.unknownElement", LIBRARY, elementName)); //$NON-NLS-1$ |
| return; |
| } |
| |
| /** |
| * convert a list of comma-separated tokens into an array |
| */ |
| protected static String[] getArrayFromList(String line) { |
| if (line == null || line.trim().length() == 0) |
| return null; |
| Vector list = new Vector(); |
| StringTokenizer tokens = new StringTokenizer(line, ","); //$NON-NLS-1$ |
| while (tokens.hasMoreTokens()) { |
| String token = tokens.nextToken().trim(); |
| if (token.length() != 0) |
| list.addElement(token); |
| } |
| return list.isEmpty() ? null : (String[]) list.toArray(new String[0]); |
| } |
| |
| 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 PluginDescriptorModel) && (((PluginDescriptorModel) objectStack.peek()).getRuntime() != null)) || ((whatIsIt instanceof PluginFragmentModel) && (((PluginFragmentModel) objectStack.peek()).getRuntime() != null))) { |
| // This is at least the 2nd Runtime element we have |
| // hit. Ignore it and give an error. |
| 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 Vector()); |
| parseRequiresAttributes(attributes); |
| return; |
| } |
| if (elementName.equals(EXTENSION_POINT)) { |
| stateStack.push(new Integer(PLUGIN_EXTENSION_POINT_STATE)); |
| parseExtensionPointAttributes(attributes); |
| return; |
| } |
| if (elementName.equals(EXTENSION)) { |
| stateStack.push(new Integer(PLUGIN_EXTENSION_STATE)); |
| parseExtensionAttributes(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(Policy.bind("parse.unknownElement", PLUGIN + " / " + FRAGMENT, elementName)); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| |
| public void handleRequiresImportState(String elementName, Attributes attributes) { |
| |
| // All elements ignored. |
| stateStack.push(new Integer(IGNORED_ELEMENT_STATE)); |
| internalError(Policy.bind("parse.unknownElement", PLUGIN_REQUIRES_IMPORT, elementName)); //$NON-NLS-1$ |
| } |
| |
| 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(Policy.bind("parse.unknownElement", PLUGIN_REQUIRES, elementName)); //$NON-NLS-1$ |
| } |
| |
| 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(Policy.bind("parse.unknownElement", RUNTIME, elementName)); //$NON-NLS-1$ |
| } |
| |
| public void ignoreableWhitespace(char[] ch, int start, int length) { |
| } |
| |
| private void logStatus(SAXParseException ex) { |
| String name = ex.getSystemId(); |
| if (name == null) |
| name = locationName; |
| 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 = Policy.bind("parse.error", ex.getMessage()); //$NON-NLS-1$ |
| else |
| msg = Policy.bind("parse.errorNameLineColumn", //$NON-NLS-1$ |
| new String[] {name, Integer.toString(ex.getLineNumber()), Integer.toString(ex.getColumnNumber()), ex.getMessage()}); |
| factory.error(new Status(IStatus.WARNING, Platform.PI_RUNTIME, Platform.PARSE_PROBLEM, msg, ex)); |
| } |
| |
| synchronized public PluginModel parsePlugin(InputSource in) throws Exception { |
| SAXParserFactory factory = acquireXMLParsing(); |
| if (factory == null) |
| return null; // TODO we log an error |
| |
| try { |
| locationName = in.getSystemId(); |
| 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 (PluginModel) objectStack.pop(); |
| } finally { |
| releaseXMLParsing(); |
| } |
| } |
| |
| private SAXParserFactory acquireXMLParsing() { |
| parserReference = InternalPlatform.getDefault().getBundleContext().getServiceReference("javax.xml.parsers.SAXParserFactory"); //$NON-NLS-1$ |
| if (parserReference == null) |
| return null; |
| return (SAXParserFactory) InternalPlatform.getDefault().getBundleContext().getService(parserReference); |
| } |
| |
| private void releaseXMLParsing() { |
| if (parserReference != null) |
| InternalPlatform.getDefault().getBundleContext().ungetService(parserReference); |
| } |
| |
| public void parseConfigurationElementAttributes(Attributes attributes) { |
| |
| ConfigurationElementModel parentConfigurationElement = (ConfigurationElementModel) objectStack.peek(); |
| parentConfigurationElement.setStartLine(locator.getLineNumber()); |
| |
| Vector propVector = null; |
| |
| // process attributes |
| int len = (attributes != null) ? attributes.getLength() : 0; |
| if (len == 0) |
| return; |
| propVector = new Vector(); |
| |
| for (int i = 0; i < len; i++) { |
| String attrName = attributes.getLocalName(i); |
| String attrValue = attributes.getValue(i); |
| |
| ConfigurationPropertyModel currentConfigurationProperty = factory.createConfigurationProperty(); |
| currentConfigurationProperty.setName(attrName); |
| currentConfigurationProperty.setValue(attrValue); |
| propVector.addElement(currentConfigurationProperty); |
| } |
| parentConfigurationElement.setProperties((ConfigurationPropertyModel[]) propVector.toArray(new ConfigurationPropertyModel[propVector.size()])); |
| propVector = null; |
| } |
| |
| public void parseExtensionAttributes(Attributes attributes) { |
| |
| PluginModel parent = (PluginModel) objectStack.peek(); |
| ExtensionModel currentExtension = factory.createExtension(); |
| currentExtension.setStartLine(locator.getLineNumber()); |
| objectStack.push(currentExtension); |
| |
| // Process Attributes |
| int len = (attributes != null) ? attributes.getLength() : 0; |
| for (int i = 0; i < len; i++) { |
| String attrName = attributes.getLocalName(i); |
| String attrValue = attributes.getValue(i).trim(); |
| |
| if (attrName.equals(EXTENSION_NAME)) |
| currentExtension.setName(attrValue); |
| else if (attrName.equals(EXTENSION_ID)) |
| currentExtension.setId(attrValue); |
| else if (attrName.equals(EXTENSION_TARGET)) { |
| // check if point is specified as a simple or qualified name |
| String targetName; |
| if (attrValue.lastIndexOf('.') == -1) { |
| String baseId = parent instanceof PluginDescriptorModel ? parent.getId() : ((PluginFragmentModel) parent).getPlugin(); |
| targetName = baseId + "." + attrValue; //$NON-NLS-1$ |
| } else |
| targetName = attrValue; |
| currentExtension.setExtensionPoint(targetName); |
| } else |
| internalError(Policy.bind("parse.unknownAttribute", EXTENSION, attrName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void parseExtensionPointAttributes(Attributes attributes) { |
| |
| ExtensionPointModel currentExtPoint = factory.createExtensionPoint(); |
| currentExtPoint.setStartLine(locator.getLineNumber()); |
| |
| // Process Attributes |
| int len = (attributes != null) ? attributes.getLength() : 0; |
| for (int i = 0; i < len; i++) { |
| String attrName = attributes.getLocalName(i); |
| String attrValue = attributes.getValue(i).trim(); |
| |
| if (attrName.equals(EXTENSION_POINT_NAME)) |
| currentExtPoint.setName(attrValue); |
| else if (attrName.equals(EXTENSION_POINT_ID)) |
| currentExtPoint.setId(attrValue); |
| else if (attrName.equals(EXTENSION_POINT_SCHEMA)) |
| currentExtPoint.setSchema(attrValue); |
| else |
| internalError(Policy.bind("parse.unknownAttribute", EXTENSION_POINT, attrName)); //$NON-NLS-1$ |
| } |
| // currentExtPoint contains a pointer to the parent plugin descriptor. |
| PluginModel root = (PluginModel) objectStack.peek(); |
| currentExtPoint.setParent(root); |
| |
| // Now populate the the vector just below us on the objectStack with this extension point |
| scratchVectors[EXTENSION_POINT_INDEX].addElement(currentExtPoint); |
| } |
| |
| public void parseFragmentAttributes(Attributes attributes) { |
| PluginFragmentModel current = factory.createPluginFragment(); |
| current.setStartLine(locator.getLineNumber()); |
| objectStack.push(current); |
| |
| // process attributes |
| 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)) |
| current.setId(attrValue); |
| else if (attrName.equals(FRAGMENT_NAME)) |
| current.setName(attrValue); |
| else if (attrName.equals(FRAGMENT_VERSION)) |
| current.setVersion(attrValue); |
| else if (attrName.equals(FRAGMENT_PROVIDER)) |
| current.setProviderName(attrValue); |
| else if (attrName.equals(FRAGMENT_PLUGIN_ID)) |
| current.setPlugin(attrValue); |
| else if (attrName.equals(FRAGMENT_PLUGIN_VERSION)) |
| current.setPluginVersion(attrValue); |
| else if (attrName.equals(FRAGMENT_PLUGIN_MATCH)) { |
| if (FRAGMENT_PLUGIN_MATCH_PERFECT.equals(attrValue)) |
| current.setMatch(PluginFragmentModel.FRAGMENT_MATCH_PERFECT); |
| else if (FRAGMENT_PLUGIN_MATCH_EQUIVALENT.equals(attrValue)) |
| current.setMatch(PluginFragmentModel.FRAGMENT_MATCH_EQUIVALENT); |
| else if (FRAGMENT_PLUGIN_MATCH_COMPATIBLE.equals(attrValue)) |
| current.setMatch(PluginFragmentModel.FRAGMENT_MATCH_COMPATIBLE); |
| else if (FRAGMENT_PLUGIN_MATCH_GREATER_OR_EQUAL.equals(attrValue)) |
| current.setMatch(PluginFragmentModel.FRAGMENT_MATCH_GREATER_OR_EQUAL); |
| else |
| internalError(Policy.bind("parse.validMatch", attrValue)); //$NON-NLS-1$ |
| } else |
| internalError(Policy.bind("parse.unknownAttribute", FRAGMENT, attrName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void parseLibraryAttributes(Attributes attributes) { |
| // Push a vector to hold the export mask |
| objectStack.push(new Vector()); |
| LibraryModel current = factory.createLibrary(); |
| current.setStartLine(locator.getLineNumber()); |
| objectStack.push(current); |
| |
| // Now the objectStack should contain the following: |
| // plugin descriptor or fragment (bottom of the stack) |
| // vector to hold all the library entries |
| // vector to hold the export mask for this library entry |
| // this library entry (top of the stack) |
| |
| // process attributes |
| int len = (attributes != null) ? attributes.getLength() : 0; |
| for (int i = 0; i < len; i++) { |
| String attrName = attributes.getLocalName(i); |
| String attrValue = attributes.getValue(i).trim(); |
| |
| if (attrName.equals(LIBRARY_NAME)) |
| current.setName(attrValue); |
| else if (attrName.equals(LIBRARY_TYPE)) { |
| attrValue = attrValue.toLowerCase(); |
| if (attrValue.equals(LibraryModel.CODE) || attrValue.equals(LibraryModel.RESOURCE)) |
| current.setType(attrValue.toLowerCase()); |
| else |
| internalError(Policy.bind("parse.unknownLibraryType", attrValue, current.getName())); //$NON-NLS-1$ |
| } else |
| internalError(Policy.bind("parse.unknownAttribute", LIBRARY, attrName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void parsePluginAttributes(Attributes attributes) { |
| |
| PluginDescriptorModel current = factory.createPluginDescriptor(); |
| current.setStartLine(locator.getLineNumber()); |
| objectStack.push(current); |
| |
| // process attributes |
| 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)) |
| current.setId(attrValue); |
| else if (attrName.equals(PLUGIN_NAME)) |
| current.setName(attrValue); |
| else if (attrName.equals(PLUGIN_VERSION)) |
| current.setVersion(attrValue); |
| else if (attrName.equals(PLUGIN_VENDOR) || (attrName.equals(PLUGIN_PROVIDER))) |
| current.setProviderName(attrValue); |
| else if (attrName.equals(PLUGIN_CLASS)) |
| current.setPluginClass(attrValue); |
| else |
| internalError(Policy.bind("parse.unknownAttribute", PLUGIN, attrName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void parsePluginRequiresImport(Attributes attributes) { |
| PluginPrerequisiteModel current = factory.createPluginPrerequisite(); |
| current.setStartLine(locator.getLineNumber()); |
| |
| // process attributes |
| int len = (attributes != null) ? attributes.getLength() : 0; |
| for (int i = 0; i < len; i++) { |
| String attrName = attributes.getLocalName(i); |
| String attrValue = attributes.getValue(i).trim(); |
| |
| if (attrName.equals(PLUGIN_REQUIRES_PLUGIN)) |
| current.setPlugin(attrValue); |
| else if (attrName.equals(PLUGIN_REQUIRES_PLUGIN_VERSION)) |
| current.setVersion(attrValue); |
| else if (attrName.equals(PLUGIN_REQUIRES_OPTIONAL)) |
| current.setOptional(TRUE.equalsIgnoreCase(attrValue)); |
| else if (attrName.equals(PLUGIN_REQUIRES_MATCH)) { |
| if (PLUGIN_REQUIRES_MATCH_PERFECT.equals(attrValue)) |
| current.setMatchByte(PluginPrerequisiteModel.PREREQ_MATCH_PERFECT); |
| else if ((PLUGIN_REQUIRES_MATCH_EQUIVALENT.equals(attrValue)) || (PLUGIN_REQUIRES_MATCH_EXACT.equals(attrValue))) |
| current.setMatchByte(PluginPrerequisiteModel.PREREQ_MATCH_EQUIVALENT); |
| else if (PLUGIN_REQUIRES_MATCH_COMPATIBLE.equals(attrValue)) |
| current.setMatchByte(PluginPrerequisiteModel.PREREQ_MATCH_COMPATIBLE); |
| else if (PLUGIN_REQUIRES_MATCH_GREATER_OR_EQUAL.equals(attrValue)) |
| current.setMatchByte(PluginPrerequisiteModel.PREREQ_MATCH_GREATER_OR_EQUAL); |
| else |
| internalError(Policy.bind("parse.validMatch", attrValue)); //$NON-NLS-1$ |
| } else if (attrName.equals(PLUGIN_REQUIRES_EXPORT)) { |
| if (TRUE.equals(attrValue)) |
| current.setExport(true); |
| else if (FALSE.equals(attrValue)) |
| current.setExport(false); |
| else |
| internalError(Policy.bind("parse.validExport", attrValue)); //$NON-NLS-1$ |
| } else |
| internalError(Policy.bind("parse.unknownAttribute", PLUGIN_REQUIRES_IMPORT, attrName)); //$NON-NLS-1$ |
| |
| } |
| // Populate the vector of prerequisites with this new element |
| ((Vector) objectStack.peek()).addElement(current); |
| } |
| |
| public void parseRequiresAttributes(Attributes attributes) { |
| } |
| |
| 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)); |
| for (int i = 0; i <= LAST_INDEX; i++) { |
| scratchVectors[i] = new Vector(); |
| } |
| } |
| |
| public void startElement(String uri, String elementName, String qName, Attributes attributes) { |
| switch (((Integer) stateStack.peek()).intValue()) { |
| case INITIAL_STATE : |
| handleInitialState(elementName, attributes); |
| break; |
| case FRAGMENT_STATE : |
| handlePluginState(elementName, attributes); |
| break; |
| 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 : |
| case CONFIGURATION_ELEMENT_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)); |
| internalError(Policy.bind("parse.unknownTopElement", elementName)); //$NON-NLS-1$ |
| } |
| } |
| |
| public void warning(SAXParseException ex) { |
| logStatus(ex); |
| } |
| |
| private void internalError(String message) { |
| if (locationName != null) |
| factory.error(new Status(IStatus.WARNING, Platform.PI_RUNTIME, Platform.PARSE_PROBLEM, locationName + ": " + message, null)); //$NON-NLS-1$ |
| else |
| factory.error(new Status(IStatus.WARNING, Platform.PI_RUNTIME, Platform.PARSE_PROBLEM, message, null)); |
| } |
| |
| } |