From 67862511f9227d3b800cf90605a47bd3ff91889d Mon Sep 17 00:00:00 2001 From: Pascal Rapicault Date: Mon, 16 Jan 2006 22:41:54 +0000 Subject: Bug 123133 - Add APIs to remove extensions and extension points from the registry --- .../registry/BufferedRandomInputStream.java | 4 +- .../internal/registry/ConfigurationElement.java | 10 +- .../registry/ConfigurationElementHandle.java | 6 +- .../core/internal/registry/Contribution.java | 73 +++++-- .../eclipse/core/internal/registry/Extension.java | 10 +- .../core/internal/registry/ExtensionHandle.java | 6 +- .../core/internal/registry/ExtensionPoint.java | 10 +- .../internal/registry/ExtensionPointHandle.java | 6 +- .../core/internal/registry/ExtensionRegistry.java | 215 ++++++++++++++------- .../core/internal/registry/ExtensionsParser.java | 6 +- .../internal/registry/HashtableOfStringAndInt.java | 4 +- .../core/internal/registry/RegistryObject.java | 22 +-- .../internal/registry/RegistryObjectFactory.java | 28 +-- .../internal/registry/RegistryObjectManager.java | 15 +- .../core/internal/registry/TableReader.java | 10 +- .../core/internal/registry/TableWriter.java | 61 ++---- .../registry/osgi/EclipseBundleListener.java | 4 +- .../spi/ConfigurationElementAttribute.java | 72 +++++++ .../spi/ConfigurationElementDescription.java | 131 +++++++++++++ .../registry/spi/ExtensionDescription.java | 110 ----------- .../internal/registry/spi/ExtensionProperty.java | 58 ------ .../equinox/registry/IExtensionRegistry.java | 89 ++++++--- .../equinox/registry/spi/RegistryStrategy.java | 2 +- 23 files changed, 558 insertions(+), 394 deletions(-) create mode 100644 bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementAttribute.java create mode 100644 bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementDescription.java delete mode 100644 bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionDescription.java delete mode 100644 bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionProperty.java diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/BufferedRandomInputStream.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/BufferedRandomInputStream.java index 08c23a6f2..a19c8619f 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/BufferedRandomInputStream.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/BufferedRandomInputStream.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2005 IBM Corporation and others. + * Copyright (c) 2005, 2006 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 @@ -29,7 +29,7 @@ public class BufferedRandomInputStream extends InputStream { public BufferedRandomInputStream(File file, int bufferSize) throws IOException { filePath = file.getCanonicalPath(); - inputFile = new RandomAccessFile(file, "r"); + inputFile = new RandomAccessFile(file, "r"); //$NON-NLS-1$ buffer = new byte[bufferSize]; resetBuffer(); } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElement.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElement.java index a6ef999dc..2da3d0a45 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElement.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElement.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -42,12 +42,12 @@ public class ConfigurationElement extends RegistryObject { //This happens when the configuration is obtained from a delta containing removed extension. private String contributorId; - protected ConfigurationElement(ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected ConfigurationElement(ExtensionRegistry registry, boolean persist) { + super(registry, persist); } - protected ConfigurationElement(int self, String contributorId, String name, String[] propertiesAndValue, int[] children, int extraDataOffset, int parent, byte parentType, ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected ConfigurationElement(int self, String contributorId, String name, String[] propertiesAndValue, int[] children, int extraDataOffset, int parent, byte parentType, ExtensionRegistry registry, boolean persist) { + super(registry, persist); setObjectId(self); this.contributorId = contributorId; diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElementHandle.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElementHandle.java index c26e12174..38320f1c6 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElementHandle.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ConfigurationElementHandle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -28,8 +28,8 @@ public class ConfigurationElementHandle extends Handle implements IConfiguration return (ConfigurationElement) objectManager.getObject(getId(), RegistryObjectManager.CONFIGURATION_ELEMENT); } - public boolean isDynamic() { - return getConfigurationElement().isDynamic(); + protected boolean shouldPersist() { + return getConfigurationElement().shouldPersist(); } public String getAttribute(String propertyName) { diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Contribution.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Contribution.java index cc375ea16..7dfdf3210 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Contribution.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Contribution.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -11,6 +11,7 @@ package org.eclipse.core.internal.registry; import org.eclipse.core.runtime.Assert; +import org.eclipse.core.runtime.InvalidRegistryObjectException; // This object is used to keep track on a contributor basis of the extension and extension points being contributed. // It is mainly used on removal so we can quickly find objects to remove. @@ -29,7 +30,7 @@ public class Contribution implements KeyedElement { private String namespaceOwnerId = null; // indicates if this contribution needs to be saved in the registry cache - protected boolean isDynamic; + protected boolean persist; // This array stores the identifiers of both the extension points and the extensions. // The array has always a minimum size of 2. @@ -40,24 +41,24 @@ public class Contribution implements KeyedElement { static final public byte EXTENSION_POINT = 0; static final public byte EXTENSION = 1; - protected Contribution(String contributorId, ExtensionRegistry registry, boolean dynamic) { + protected Contribution(String contributorId, ExtensionRegistry registry, boolean persist) { this.contributorId = contributorId; this.registry = registry; - this.isDynamic = dynamic; + this.persist = persist; } void mergeContribution(Contribution addContribution) { Assert.isTrue(contributorId.equals(addContribution.contributorId)); Assert.isTrue(registry == addContribution.registry); - // isDynamic? + // persist? // Old New Result - // F F F - // F T F - // T F F => the only situation where isDynamic status needs to be adjusted - // T T T - if (isDynamic() && !addContribution.isDynamic()) - isDynamic = false; + // F F F + // F T T => needs to be adjusted + // T F T + // T T T + if (shouldPersist() != addContribution.shouldPersist()) + persist = true; int[] existing = getRawChildren(); int[] addition = addContribution.getRawChildren(); @@ -130,7 +131,53 @@ public class Contribution implements KeyedElement { return contributorId.equals(((Contribution) other).contributorId); } - public boolean isDynamic() { - return isDynamic; + public boolean shouldPersist() { + return persist; + } + + public void unlinkChild(int id) { + // find index of the child being unlinked: + int index = -1; + for (int i = 2; i < children.length; i++) { + if (children[i] == id) { + index = i; + break; + } + } + if (index == -1) + throw new InvalidRegistryObjectException(); + + // copy all array except one element at index + int[] result = new int[children.length - 1]; + System.arraycopy(children, 0, result, 0, index); + System.arraycopy(children, index + 1, result, index, children.length - index - 1); + + // fix sizes + if (index < children[EXTENSION_POINT] + 2) + result[EXTENSION_POINT]--; + else + result[EXTENSION]--; + + children = result; + } + + /** + * Contribution is empty if it has no children. + */ + public boolean isEmpty() { + return (children[EXTENSION_POINT] == 0 || children[EXTENSION] == 0); + } + + /** + * Find if this contribution has a children with ID = id. + * @param id possible ID of the child + * @return true: contribution has this child + */ + public boolean hasChild(int id) { + for (int i = 2; i < children.length; i++) { + if (children[i] == id) + return true; + } + return false; } } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Extension.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Extension.java index a8da6dfab..e7e385af4 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Extension.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/Extension.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -30,12 +30,12 @@ public class Extension extends RegistryObject { private static final byte XPT_NAME = 1; // The fully qualified name of the extension point to which this extension is attached to private static final int EXTRA_SIZE = 2; - protected Extension(ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected Extension(ExtensionRegistry registry, boolean persist) { + super(registry, persist); } - protected Extension(int self, String simpleId, String namespace, int[] children, int extraData, ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected Extension(int self, String simpleId, String namespace, int[] children, int extraData, ExtensionRegistry registry, boolean persist) { + super(registry, persist); setObjectId(self); this.simpleId = simpleId; diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionHandle.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionHandle.java index 7f0ee9c0d..403a8842d 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionHandle.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionHandle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -28,8 +28,8 @@ public class ExtensionHandle extends Handle implements IExtension { return (Extension) objectManager.getObject(getId(), RegistryObjectManager.EXTENSION); } - public boolean isDynamic() { - return getExtension().isDynamic(); + protected boolean shouldPersist() { + return getExtension().shouldPersist(); } public String getNamespace() { diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPoint.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPoint.java index 6f9b583f0..c883e0189 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPoint.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPoint.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2004 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -31,12 +31,12 @@ public class ExtensionPoint extends RegistryObject { private static final byte CONTRIBUTOR_ID = 4; //The namespace owner contributing the extension point private static final int EXTRA_SIZE = 5; - protected ExtensionPoint(ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected ExtensionPoint(ExtensionRegistry registry, boolean persist) { + super(registry, persist); } - protected ExtensionPoint(int self, int[] children, int dataOffset, ExtensionRegistry registry, boolean isDynamic) { - super(registry, isDynamic); + protected ExtensionPoint(int self, int[] children, int dataOffset, ExtensionRegistry registry, boolean persist) { + super(registry, persist); setObjectId(self); setRawChildren(children); diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPointHandle.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPointHandle.java index 41606927c..d3b8496d4 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPointHandle.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionPointHandle.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -33,8 +33,8 @@ public class ExtensionPointHandle extends Handle implements IExtensionPoint { return getExtensionPoint().getNamespace(); } - public boolean isDynamic() { - return getExtensionPoint().isDynamic(); + protected boolean shouldPersist() { + return getExtensionPoint().shouldPersist(); } public IExtension getExtension(String extensionId) { diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionRegistry.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionRegistry.java index 14d7bbe86..3fda664b9 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionRegistry.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionRegistry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2005 IBM Corporation and others. + * Copyright (c) 2000, 2006 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 @@ -14,8 +14,8 @@ import java.io.*; import java.lang.reflect.Array; import java.util.*; import javax.xml.parsers.ParserConfigurationException; -import org.eclipse.core.internal.registry.spi.ExtensionDescription; -import org.eclipse.core.internal.registry.spi.ExtensionProperty; +import org.eclipse.core.internal.registry.spi.ConfigurationElementDescription; +import org.eclipse.core.internal.registry.spi.ConfigurationElementAttribute; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.adaptor.FileManager; import org.eclipse.equinox.registry.*; @@ -68,7 +68,7 @@ public class ExtensionRegistry implements IExtensionRegistry { protected TableReader theTableReader = new TableReader(this); private Object masterToken; // use to get full control of the registry; objects created as "static" - private Object userToken; // use to add dynamic contributions + private Object userToken; // use to modify non-persisted registry elements ///////////////////////////////////////////////////////////////////////////////////////// // Registry strategies @@ -108,7 +108,7 @@ public class ExtensionRegistry implements IExtensionRegistry { * interested on changes in the given plug-in. *

*/ - public void add(Contribution element) { + private void add(Contribution element) { access.enterWrite(); try { basicAdd(element, true); @@ -118,17 +118,6 @@ public class ExtensionRegistry implements IExtensionRegistry { } } - public void add(Contribution[] elements) { - access.enterWrite(); - try { - for (int i = 0; i < elements.length; i++) - basicAdd(elements[i], true); - fireRegistryChangeEvent(); - } finally { - access.exitWrite(); - } - } - /* Utility method to help with array concatenations */ static Object concatArrays(Object a, Object b) { Object[] result = (Object[]) Array.newInstance(a.getClass().getComponentType(), Array.getLength(a) + Array.getLength(b)); @@ -902,29 +891,36 @@ public class ExtensionRegistry implements IExtensionRegistry { } } - ////////////////////////////////////////////////////////////////////////////////////// - // Modifiable portion - - public boolean addContribution(InputStream is, String contributorId, String contributionName, ResourceBundle b, Object key) { - // check access - if (!strategy.isModifiable() && masterToken != key && userToken != key) - throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.addXMLContribution() method. Check if proper access token is supplied."); //$NON-NLS-1$ - // determine contribution nature - boolean isDynamic; + /** + * Access check for add/remove operations: + * a) for modifiable registry key is not required (null is fine) + * b) for non-modifiable registry master key allows all operations + * c) for non-modifiable registry user key allows modifications of non-persisted elements + * + * @param key key to the registry supplied by the user + * @param persist true if operation affects persisted elements + * @return true is the key grants read/write access to the registry + */ + private boolean checkReadWriteAccess(Object key, boolean persist) { + if (strategy.isModifiable()) + return true; if (masterToken == key) - isDynamic = false; - else if (userToken == key) - isDynamic = true; - else - isDynamic = false; // default: for modifiable registry contributions are static + return true; + if (userToken == key && !persist) + return true; + return false; + } + public boolean addContribution(InputStream is, String contributorId, boolean persist, String contributionName, ResourceBundle b, Object key) { + if (!checkReadWriteAccess(key, persist)) + throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.addXMLContribution() method. Check if proper access token is supplied."); //$NON-NLS-1$ if (contributionName == null) contributionName = ""; //$NON-NLS-1$ String ownerName = getNamespace(contributorId); String message = NLS.bind(RegistryMessages.parse_problems, ownerName); MultiStatus problems = new MultiStatus(RegistryMessages.OWNER_NAME, ExtensionsParser.PARSE_PROBLEM, message, null); ExtensionsParser parser = new ExtensionsParser(problems, this); - Contribution contribution = getElementFactory().createContribution(contributorId, isDynamic); + Contribution contribution = getElementFactory().createContribution(contributorId, persist); try { parser.parseManifest(strategy.getXMLParser(), new InputSource(is), contributionName, getObjectManager(), contribution, b); @@ -948,10 +944,7 @@ public class ExtensionRegistry implements IExtensionRegistry { // nothing to do } } - - // Do not synchronize on registry here because the registry handles - // the synchronization for us in registry.add - add(contribution); + add(contribution); // the add() method does synchronization return true; } @@ -961,35 +954,51 @@ public class ExtensionRegistry implements IExtensionRegistry { } /** - * Creates an extension point. + * Adds an extension point to the extension registry. + *

+ * If the registry is not modifiable, this method is an access controlled method. + * Proper token should be passed as an argument for non-modifiable registries. + *

+ * @see org.eclipse.equinox.registry.spi.RegistryStrategy#isModifiable() * - * @param contributorId - Id of the supplier of this extension point - * @param extensionPointId - Id of the extension point. If non-qualified names is supplied, - * it will be converted internally into a fully qualified name. - * @param extensionPointLabel- display string for the extension point - * @param schemaLocation - points to the location of the XML schema file + * @param identifier Id of the extension point. If non-qualified names is supplied, + * it will be converted internally into a fully qualified name + * @param contributorId ID of the supplier of this contribution + * @param persist indicates if contribution should be stored in the registry cache. If false, + * contribution is not persisted in the registry cache and is lost on Eclipse restart + * @param label display string for the extension point + * @param schemaReference reference to the extension point schema. The schema reference + * is a URL path relative to the plug-in installation URL. May be null + * @param token the key used to check permissions. Two registry keys are set in the registry + * constructor {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: + * master token and a user token. Master token allows all operations; user token + * allows non-persisted registry elements to be modified. + * @throws IllegalArgumentException if incorrect token is passed in */ - public void createExtensionPoint(String contributorId, String extensionPointId, String extensionPointLabel, String schemaLocation) { - + public void addExtensionPoint(String identifier, String contributorId, boolean persist, String label, String schemaReference, Object token) throws IllegalArgumentException { + if (!checkReadWriteAccess(token, persist)) + throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); //$NON-NLS-1$ // Extension point Id might not be null - if (extensionPointId == null) { - String message = NLS.bind(RegistryMessages.create_failedExtensionPoint, extensionPointLabel); + if (identifier == null) { + String message = NLS.bind(RegistryMessages.create_failedExtensionPoint, label); log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, message, null)); } + if (schemaReference == null) + schemaReference = ""; //$NON-NLS-1$ // prepare namespace information String namespaceName = getNamespace(contributorId); String namespaceOwnerId = getNamespaceOwnerId(contributorId); // addition wraps in a contribution - Contribution contribution = getElementFactory().createContribution(contributorId, true); + Contribution contribution = getElementFactory().createContribution(contributorId, persist); - ExtensionPoint currentExtPoint = getElementFactory().createExtensionPoint(true); - String uniqueId = namespaceName + '.' + extensionPointId; + ExtensionPoint currentExtPoint = getElementFactory().createExtensionPoint(persist); + String uniqueId = namespaceName + '.' + identifier; currentExtPoint.setUniqueIdentifier(uniqueId); - String labelNLS = translate(extensionPointLabel, null); + String labelNLS = translate(label, null); currentExtPoint.setLabel(labelNLS); - currentExtPoint.setSchema(schemaLocation); + currentExtPoint.setSchema(schemaReference); getObjectManager().addExtensionPoint(currentExtPoint, true); @@ -1009,29 +1018,42 @@ public class ExtensionRegistry implements IExtensionRegistry { } /** - * Creates an extension. - * - * @see ExtensionDescription + * Adds an extension to the extension registry. + *

+ * If the registry is not modifiable, this method is an access controlled method. + * Proper token should be passed as an argument for non-modifiable registries. + *

+ * @see org.eclipse.equinox.registry.spi.RegistryStrategy#isModifiable() + * @see org.eclipse.core.internal.registry.spi.ConfigurationElementDescription * - * @param contributorId - Id of the supplier of this extension - * @param extensionId - Id of the extension. If non-qualified name is supplied, + * @param identifier Id of the extension. If non-qualified name is supplied, * it will be converted internally into a fully qualified name - * @param extensionLabel - display string for this extension - * @param extensionPointId - Id of the point being extended. If non-qualified + * @param contributorId ID of the supplier of this contribution + * @param persist indicates if contribution should be stored in the registry cache. If false, + * contribution is not persisted in the registry cache and is lost on Eclipse restart + * @param label display string for this extension + * @param extensionPointId Id of the point being extended. If non-qualified * name is supplied, it is assumed to have the same contributorId as this extension - * @param description - contents of the extension + * @param configurationElements contents of the extension + * @param token the key used to check permissions. Two registry keys are set in the registry + * constructor {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: + * master token and a user token. Master token allows all operations; user token + * allows non-persisted registry elements to be modified. + * @throws IllegalArgumentException if incorrect token is passed in */ - public void createExtension(String contributorId, String extensionId, String extensionLabel, String extensionPointId, ExtensionDescription description) { + public void addExtension(String identifier, String contributorId, boolean persist, String label, String extensionPointId, ConfigurationElementDescription configurationElements, Object token) throws IllegalArgumentException { + if (!checkReadWriteAccess(token, persist)) + throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.addExtensionPoint() method. Check if proper access token is supplied."); //$NON-NLS-1$ // prepare namespace information String namespaceName = getNamespace(contributorId); String namespaceOwnerId = getNamespaceOwnerId(contributorId); // addition wraps in a contribution - Contribution contribution = getElementFactory().createContribution(contributorId, true); + Contribution contribution = getElementFactory().createContribution(contributorId, persist); - Extension currentExtension = getElementFactory().createExtension(true); - currentExtension.setSimpleIdentifier(extensionId); - String extensionLabelNLS = translate(extensionLabel, null); + Extension currentExtension = getElementFactory().createExtension(persist); + currentExtension.setSimpleIdentifier(identifier); + String extensionLabelNLS = translate(label, null); currentExtension.setLabel(extensionLabelNLS); String targetExtensionPointId; @@ -1043,7 +1065,7 @@ public class ExtensionRegistry implements IExtensionRegistry { getObjectManager().add(currentExtension, true); - createExtensionData(namespaceOwnerId, description, currentExtension); + createExtensionData(namespaceOwnerId, configurationElements, currentExtension, persist); currentExtension.setNamespaceName(namespaceName); @@ -1058,15 +1080,15 @@ public class ExtensionRegistry implements IExtensionRegistry { } // Fill in the actual content of this extension - private void createExtensionData(String namespaceOwnerId, ExtensionDescription description, RegistryObject parent) { - ConfigurationElement currentConfigurationElement = getElementFactory().createConfigurationElement(true); + private void createExtensionData(String namespaceOwnerId, ConfigurationElementDescription description, RegistryObject parent, boolean persist) { + ConfigurationElement currentConfigurationElement = getElementFactory().createConfigurationElement(persist); currentConfigurationElement.setNamespaceOwnerId(namespaceOwnerId); - currentConfigurationElement.setName(description.getElementName()); + currentConfigurationElement.setName(description.getName()); - if (description.hasProperties()) { - ExtensionProperty[] descriptionProperties = description.getProperties(); - int len = descriptionProperties.length; + ConfigurationElementAttribute[] descriptionProperties = description.getAttributes(); + if (descriptionProperties != null && descriptionProperties.length != 0) { + int len = descriptionProperties.length; String[] properties = new String[len * 2]; for (int i = 0; i < len; i++) { properties[i * 2] = descriptionProperties[i].getName(); @@ -1083,10 +1105,10 @@ public class ExtensionRegistry implements IExtensionRegistry { getObjectManager().add(currentConfigurationElement, true); // process children - ExtensionDescription[] children = description.getChildren(); + ConfigurationElementDescription[] children = description.getChildren(); if (children != null) { for (int i = 0; i < children.length; i++) { - createExtensionData(namespaceOwnerId, children[i], currentConfigurationElement); + createExtensionData(namespaceOwnerId, children[i], currentConfigurationElement, persist); } } @@ -1102,6 +1124,55 @@ public class ExtensionRegistry implements IExtensionRegistry { currentConfigurationElement.setParentType(parent instanceof ConfigurationElement ? RegistryObjectManager.CONFIGURATION_ELEMENT : RegistryObjectManager.EXTENSION); } + public boolean removeExtension(IExtension extension, Object token) throws IllegalArgumentException { + if (!(extension instanceof ExtensionHandle)) + return false; + return removeObject(((ExtensionHandle) extension).getObject(), false, token); + } + + public boolean removeExtensionPoint(IExtensionPoint extensionPoint, Object token) throws IllegalArgumentException { + if (!(extensionPoint instanceof ExtensionPointHandle)) + return false; + return removeObject(((ExtensionPointHandle) extensionPoint).getObject(), true, token); + } + + private boolean removeObject(RegistryObject registryObject, boolean isExtensionPoint, Object token) { + if (!checkReadWriteAccess(token, registryObject.shouldPersist())) + throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.removeExtension() method. Check if proper access token is supplied."); //$NON-NLS-1$ + int id = registryObject.getObjectId(); + + access.enterWrite(); + try { + String namespace; + if (isExtensionPoint) + namespace = removeExtensionPoint(id); + else + namespace = removeExtension(id); + + Map removed = new HashMap(1); + removed.put(new Integer(id), registryObject); + registryObjects.removeObjects(removed); + registryObjects.addNavigableObjects(removed); + getDelta(namespace).setObjectManager(registryObjects.createDelegatingObjectManager(removed)); + + String[] possibleContributors = strategy.getNamespaceContributors(namespace); + for (int i = 0; i < possibleContributors.length; i++) { + Contribution contribution = registryObjects.getContribution(possibleContributors[i]); + if (contribution.hasChild(id)) { + contribution.unlinkChild(id); + if (contribution.isEmpty()) + registryObjects.removeContribution(possibleContributors[i]); + break; + } + } + + fireRegistryChangeEvent(); + } finally { + access.exitWrite(); + } + return true; + } + public void setCompatibilityStrategy(ICompatibilityStrategy strategy) { compatibilityStrategy = strategy; } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionsParser.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionsParser.java index 81061c88d..5d540d2f1 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionsParser.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/ExtensionsParser.java @@ -278,7 +278,7 @@ public class ExtensionsParser extends DefaultHandler { configurationElementValue = null; // create a new Configuration Element and push it onto the object stack - ConfigurationElement currentConfigurationElement = registry.getElementFactory().createConfigurationElement(namespace.isDynamic()); + ConfigurationElement currentConfigurationElement = registry.getElementFactory().createConfigurationElement(namespace.shouldPersist()); currentConfigurationElement.setNamespaceOwnerId(namespace.getNamespaceOwnerId()); objectStack.push(currentConfigurationElement); currentConfigurationElement.setName(elementName); @@ -387,7 +387,7 @@ public class ExtensionsParser extends DefaultHandler { } private void parseExtensionAttributes(Attributes attributes) { - Extension currentExtension = registry.getElementFactory().createExtension(namespace.isDynamic()); + Extension currentExtension = registry.getElementFactory().createExtension(namespace.shouldPersist()); objectStack.push(currentExtension); // Process Attributes @@ -446,7 +446,7 @@ public class ExtensionsParser extends DefaultHandler { } private void parseExtensionPointAttributes(Attributes attributes) { - ExtensionPoint currentExtPoint = registry.getElementFactory().createExtensionPoint(namespace.isDynamic()); + ExtensionPoint currentExtPoint = registry.getElementFactory().createExtensionPoint(namespace.shouldPersist()); // Process Attributes int len = (attributes != null) ? attributes.getLength() : 0; diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/HashtableOfStringAndInt.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/HashtableOfStringAndInt.java index 711ce1157..78ff58cce 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/HashtableOfStringAndInt.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/HashtableOfStringAndInt.java @@ -166,11 +166,11 @@ public final class HashtableOfStringAndInt implements Cloneable { /** * Filtered save: outputs only elements with values not in the excluded list. */ - public void save(DataOutputStream out, TableWriter writer) throws IOException { + public void save(DataOutputStream out, RegistryObjectManager objectManager) throws IOException { HashtableOfStringAndInt filteredHashtable = new HashtableOfStringAndInt((int) (elementSize * GROWTH_FACTOR)); String currentKey; for (int i = keyTable.length; --i >= 0;) - if ((currentKey = keyTable[i]) != null && writer.shouldCache(valueTable[i])) + if ((currentKey = keyTable[i]) != null && objectManager.shouldPersist(valueTable[i])) filteredHashtable.put(currentKey, valueTable[i]); filteredHashtable.save(out); } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObject.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObject.java index f3fa8e865..65fac9299 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObject.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObject.java @@ -20,24 +20,24 @@ public abstract class RegistryObject implements KeyedElement { //The children of the element protected int[] children = RegistryObjectManager.EMPTY_INT_ARRAY; - // The field combines offset, dynamic flag, and no offset flag + // The field combines offset, persistence flag, and no offset flag private int extraDataOffset = EMPTY_MASK; // it is assumed that int has 32 bits (bits #0 to #31); // bits #0 - #29 are the offset (limited to about 1Gb) - // bit #30 - registry object is dynamic if set + // bit #30 - persistance flag // bit #31 - registry object has no extra data offset // the bit#31 is a sign bit; bit#30 is the highest mantissa bit static final int EMPTY_MASK = 0x80000000; // only taking bit #31 - static final int DYNAMIC_MASK = 0x40000000; // only taking bit #30 + static final int PERSIST_MASK = 0x40000000; // only taking bit #30 static final int OFFSET_MASK = 0x3FFFFFFF; // all bits but #30, #31 //The registry that owns this object protected ExtensionRegistry registry; - protected RegistryObject(ExtensionRegistry registry, boolean isDynamic) { + protected RegistryObject(ExtensionRegistry registry, boolean persist) { this.registry = registry; - setDynamic(isDynamic); + setPersist(persist); } void setRawChildren(int[] values) { @@ -70,15 +70,15 @@ public abstract class RegistryObject implements KeyedElement { return objectId == ((RegistryObject) other).objectId; } - protected boolean isDynamic() { - return (extraDataOffset & DYNAMIC_MASK) == DYNAMIC_MASK; + protected boolean shouldPersist() { + return (extraDataOffset & PERSIST_MASK) == PERSIST_MASK; } - private void setDynamic(boolean dynamic) { - if (dynamic) - extraDataOffset |= DYNAMIC_MASK; + private void setPersist(boolean persist) { + if (persist) + extraDataOffset |= PERSIST_MASK; else - extraDataOffset &= ~DYNAMIC_MASK; + extraDataOffset &= ~PERSIST_MASK; } protected boolean noExtraData() { diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectFactory.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectFactory.java index 603bb50a5..3b078b294 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectFactory.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectFactory.java @@ -24,37 +24,37 @@ public class RegistryObjectFactory { //////////////////////////////////////////////////////////////////////////// // Contribution - public Contribution createContribution(String contributorId, boolean isDynamic) { - return new Contribution(contributorId, registry, isDynamic); + public Contribution createContribution(String contributorId, boolean persist) { + return new Contribution(contributorId, registry, persist); } //////////////////////////////////////////////////////////////////////////// // Extension point - public ExtensionPoint createExtensionPoint(boolean isDynamic) { - return new ExtensionPoint(registry, isDynamic); + public ExtensionPoint createExtensionPoint(boolean persist) { + return new ExtensionPoint(registry, persist); } - public ExtensionPoint createExtensionPoint(int self, int[] children, int dataOffset, boolean isDynamic) { - return new ExtensionPoint(self, children, dataOffset, registry, isDynamic); + public ExtensionPoint createExtensionPoint(int self, int[] children, int dataOffset, boolean persist) { + return new ExtensionPoint(self, children, dataOffset, registry, persist); } //////////////////////////////////////////////////////////////////////////// // Extension - public Extension createExtension(boolean isDynamic) { - return new Extension(registry, isDynamic); + public Extension createExtension(boolean persist) { + return new Extension(registry, persist); } - public Extension createExtension(int self, String simpleId, String namespace, int[] children, int extraData, boolean isDynamic) { - return new Extension(self, simpleId, namespace, children, extraData, registry, isDynamic); + public Extension createExtension(int self, String simpleId, String namespace, int[] children, int extraData, boolean persist) { + return new Extension(self, simpleId, namespace, children, extraData, registry, persist); } //////////////////////////////////////////////////////////////////////////// // Configuration element - public ConfigurationElement createConfigurationElement(boolean isDynamic) { - return new ConfigurationElement(registry, isDynamic); + public ConfigurationElement createConfigurationElement(boolean persist) { + return new ConfigurationElement(registry, persist); } - public ConfigurationElement createConfigurationElement(int self, String contributorId, String name, String[] propertiesAndValue, int[] children, int extraDataOffset, int parent, byte parentType, boolean isDynamic) { - return new ConfigurationElement(self, contributorId, name, propertiesAndValue, children, extraDataOffset, parent, parentType, registry, isDynamic); + public ConfigurationElement createConfigurationElement(int self, String contributorId, String name, String[] propertiesAndValue, int[] children, int extraDataOffset, int parent, byte parentType, boolean persist) { + return new ConfigurationElement(self, contributorId, name, propertiesAndValue, children, extraDataOffset, parent, parentType, registry, persist); } } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectManager.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectManager.java index dc4f7f6d1..d92943196 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectManager.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/RegistryObjectManager.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -216,11 +216,11 @@ public class RegistryObjectManager implements IObjectManager { // of this method would have to retrieved the object from disk and check // its "dynamic" status. The problem is that id alone is not enough to get the object // from the disk; object type is needed as well. - public boolean isDynamic(int id) { + public boolean shouldPersist(int id) { Object result = cache.get(id); if (result != null) - return ((RegistryObject) result).isDynamic(); - return false; + return ((RegistryObject) result).shouldPersist(); + return true; } public synchronized RegistryObject[] getObjects(int[] values, byte type) { @@ -582,4 +582,11 @@ public class RegistryObjectManager implements IObjectManager { public ExtensionRegistry getRegistry() { return registry; } + + synchronized Contribution getContribution(String id) { + KeyedElement tmp = newContributions.getByKey(id); + if (tmp == null) + tmp = getFormerContributions().getByKey(id); + return (Contribution) tmp; + } } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableReader.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableReader.java index b3e3ee96f..3a83fc4a4 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableReader.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableReader.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -162,7 +162,7 @@ public class TableReader { int[] children = readArray(is); if (actualContributorId == null) actualContributorId = contributorId; - return getObjectFactory().createConfigurationElement(self, actualContributorId, name, propertiesAndValue, children, misc, parentId, parentType, false); + return getObjectFactory().createConfigurationElement(self, actualContributorId, name, propertiesAndValue, children, misc, parentId, parentType, true); } public Object loadThirdLevelConfigurationElements(int offset, RegistryObjectManager objectManager) { @@ -232,7 +232,7 @@ public class TableReader { String namespace = readStringOrNull(mainInput); int[] children = readArray(mainInput); int extraData = mainInput.readInt(); - return getObjectFactory().createExtension(self, simpleId, namespace, children, extraData, false); + return getObjectFactory().createExtension(self, simpleId, namespace, children, extraData, true); } public ExtensionPoint loadExtensionPointTree(int offset, RegistryObjectManager objects) { @@ -282,7 +282,7 @@ public class TableReader { int self = mainInput.readInt(); int[] children = readArray(mainInput); int extraData = mainInput.readInt(); - return getObjectFactory().createExtensionPoint(self, children, extraData, false); + return getObjectFactory().createExtensionPoint(self, children, extraData, true); } private int[] readArray(DataInputStream in) throws IOException { @@ -364,7 +364,7 @@ public class TableReader { KeyedHashSet result = new KeyedHashSet(size); for (int i = 0; i < size; i++) { String contributorId = readStringOrNull(namespaceInput); - Contribution n = getObjectFactory().createContribution(contributorId, false); + Contribution n = getObjectFactory().createContribution(contributorId, true); n.setRawChildren(readArray(namespaceInput)); result.add(n); } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableWriter.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableWriter.java index 3c6cdc972..9f8b71c87 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableWriter.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/TableWriter.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2004, 2005 IBM Corporation and others. + * Copyright (c) 2004, 2006 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 @@ -149,27 +149,27 @@ public class TableWriter { // get count of contributions that will be cached int cacheSize = 0; for (int i = 0; i < newElements.length; i++) { - if (shouldCache((Contribution) newElements[i])) + if (((Contribution) newElements[i]).shouldPersist()) cacheSize++; } for (int i = 0; i < formerElements.length; i++) { - if (shouldCache((Contribution) formerElements[i])) + if (((Contribution) formerElements[i]).shouldPersist()) cacheSize++; } outputNamespace.writeInt(cacheSize); for (int i = 0; i < newElements.length; i++) { Contribution element = (Contribution) newElements[i]; - if (shouldCache(element)) { + if (element.shouldPersist()) { writeStringOrNull(element.getContributorId(), outputNamespace); - saveArray(element.getRawChildren(), outputNamespace); + saveArray(filter(element.getRawChildren()), outputNamespace); } } for (int i = 0; i < formerElements.length; i++) { Contribution element = (Contribution) formerElements[i]; - if (shouldCache(element)) { + if (element.shouldPersist()) { writeStringOrNull(element.getContributorId(), outputNamespace); - saveArray(element.getRawChildren(), outputNamespace); + saveArray(filter(element.getRawChildren()), outputNamespace); } } outputNamespace.flush(); @@ -183,7 +183,7 @@ public class TableWriter { writeCacheHeader(outputTable, registryTimeStamp); outputTable.writeInt(objectManager.getNextId()); offsets.save(outputTable); - objectManager.getExtensionPoints().save(outputTable, this); // uses writer to filter contents + objectManager.getExtensionPoints().save(outputTable, objectManager); // uses writer to filter contents outputTable.flush(); fosTable.getFD().sync(); outputTable.close(); @@ -214,7 +214,7 @@ public class TableWriter { } private void saveExtensionPoint(ExtensionPointHandle xpt) throws IOException { - if (!shouldCache(xpt)) + if (!xpt.shouldPersist()) return; //save the file position offsets.put(xpt.getId(), mainOutput.size()); @@ -228,7 +228,7 @@ public class TableWriter { } private void saveExtension(ExtensionHandle ext, DataOutputStream outputStream) throws IOException { - if (!shouldCache(ext)) + if (!ext.shouldPersist()) return; offsets.put(ext.getId(), outputStream.size()); outputStream.writeInt(ext.getId()); @@ -248,7 +248,7 @@ public class TableWriter { //Save Configuration elements depth first private void saveConfigurationElement(ConfigurationElementHandle element, DataOutputStream outputStream, DataOutputStream extraOutputStream, int depth) throws IOException { - if (!shouldCache(element)) + if (!element.shouldPersist()) return; DataOutputStream currentOutput = outputStream; if (depth > 2) @@ -285,7 +285,7 @@ public class TableWriter { int countCElements = 0; boolean[] save = new boolean[ces.length]; for (int j = 0; j < ces.length; j++) { - if (shouldCache((ConfigurationElementHandle) ces[j])) { + if (((ConfigurationElementHandle) ces[j]).shouldPersist()) { save[j] = true; countCElements++; } else @@ -353,42 +353,12 @@ public class TableWriter { registry.log(status); } - private boolean shouldCache(ExtensionPointHandle extensionPoint) { - if (extensionPoint.isDynamic()) - return saveDynamic(); - return true; - } - - private boolean shouldCache(ExtensionHandle extension) { - if (extension.isDynamic()) - return saveDynamic(); - return true; - } - - private boolean shouldCache(ConfigurationElementHandle configElement) { - if (configElement.isDynamic()) - return saveDynamic(); - return true; - } - - private boolean shouldCache(Contribution contribution) { - if (contribution.isDynamic()) - return saveDynamic(); - return true; - } - - public boolean shouldCache(int registryObjectId) { - if (objectManager.isDynamic(registryObjectId)) - return saveDynamic(); - return true; - } - // Filters out registry objects that should not be cached private int[] filter(int[] input) { boolean[] save = new boolean[input.length]; int resultSize = 0; for (int i = 0; i < input.length; i++) { - if (shouldCache(input[i])) { + if (objectManager.shouldPersist(input[i])) { save[i] = true; resultSize++; } else @@ -404,9 +374,4 @@ public class TableWriter { } return result; } - - // Regulates if we are saving dynamic registry objects - public boolean saveDynamic() { - return false; - } } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/osgi/EclipseBundleListener.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/osgi/EclipseBundleListener.java index 7bb22e6b4..12a70d357 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/osgi/EclipseBundleListener.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/osgi/EclipseBundleListener.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2005 IBM Corporation and others. + * Copyright (c) 2003, 2006 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 @@ -136,7 +136,7 @@ public class EclipseBundleListener implements SynchronousBundleListener { //Ignore the exception } - registry.addContribution(is, contributorId, manifestName, b, token); + registry.addContribution(is, contributorId, true, manifestName, b, token); // bug 70941 // need to ensure we can find resource bundles from fragments diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementAttribute.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementAttribute.java new file mode 100644 index 000000000..03ddd53c5 --- /dev/null +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementAttribute.java @@ -0,0 +1,72 @@ +/******************************************************************************* + * Copyright (c) 2005, 2006 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.core.internal.registry.spi; + +import org.eclipse.equinox.registry.IConfigurationElement; + +/** + * Describes properties of configuration elements to be added to the registry. + * Properties are represented as pairs of strings: {attribute name; attribute value}. + *

+ * It is expected that both attribute name and attribute value are not null. + *

+ *

+ * This class can be instantited. + *

+ *

+ * This class is not intended to be subclassed. + *

+ * @see ConfigurationElementDescription + * @see IConfigurationElement + */ +public final class ConfigurationElementAttribute { + + /** + * Attribute name. + * @see IConfigurationElement#getAttributeNames() + */ + private String name; + + /** + * Attribute value. + * @see IConfigurationElement#getAttributeAsIs(String) + */ + private String value; + + /** + * Constructor. + * + * @param name attribute name + * @param value attribute value + */ + public ConfigurationElementAttribute(String name, String value) { + this.name = name; + this.value = value; + } + + /** + * Returns attribute name. + * @return attribute name + * @see IConfigurationElement#getAttributeNames() + */ + public String getName() { + return name; + } + + /** + * Returns value of the attribute. + * @return attribute value + * @see IConfigurationElement#getAttributeAsIs(String) + */ + public String getValue() { + return value; + } +} diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementDescription.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementDescription.java new file mode 100644 index 000000000..c5118cee4 --- /dev/null +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ConfigurationElementDescription.java @@ -0,0 +1,131 @@ +/******************************************************************************* + * Copyright (c) 2005, 2006 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.core.internal.registry.spi; + +import org.eclipse.equinox.registry.IConfigurationElement; + +/** + * Describes configuration elements (content of an extension) to be added to + * the extension registry. Configuration element can contain attributes or + * a String value. Configuration element can contain other configuration + * elements (children). + *

+ * It is expected that configuration element's name is not null. Attributes and + * children of the extension description might be null; value might be null as well. + *

+ *

+ * This class can be instantiated. + *

+ *

+ * This class is not intended to be subclassed. + *

+ * @see ConfigurationElementAttribute + */ +public final class ConfigurationElementDescription { + + /** + * Name of the configuration element. + * @see IConfigurationElement#getName() + */ + private String name; + + /** + * Attributes of the configuration element. + * @see IConfigurationElement#getAttribute(String) + */ + private ConfigurationElementAttribute[] attributes; + + /** + * String value to be stored in this configuration element. + * @see IConfigurationElement#getValue() + */ + private String value; + + /** + * Children of the configuration element. + * @see IConfigurationElement#getChildren() + */ + private ConfigurationElementDescription[] children; + + /** + * Constructor. + * + * @param name - name of the configuration element + * @param attributes - attributes of the configuration element. Might be null. + * @param value - string value to be stored. Might be null. + * @param children - children of the configuration element. Might be null. + * @see IConfigurationElement#getName() + * @see IConfigurationElement#getChildren() + * @see IConfigurationElement#getAttribute(String) + * @see IConfigurationElement#getValue() + */ + public ConfigurationElementDescription(String name, ConfigurationElementAttribute[] attributes, String value, ConfigurationElementDescription[] children) { + this.name = name; + this.attributes = attributes; + this.value = value; + this.children = children; + } + + /** + * Constructor. + * + * @param name - name of the configuration element + * @param attribute - attribute of the configuration element. Might be null. + * @param value - string value to be stored. Might be null. + * @param children - children of the configuration element. Might be null. + * @see IConfigurationElement#getName() + * @see IConfigurationElement#getChildren() + * @see IConfigurationElement#getAttribute(String) + * @see IConfigurationElement#getValue() + */ + public ConfigurationElementDescription(String name, ConfigurationElementAttribute attribute, String value, ConfigurationElementDescription[] children) { + this.name = name; + this.attributes = new ConfigurationElementAttribute[] {attribute}; + this.value = value; + this.children = children; + } + + /** + * Returns children of the configuration element. + * @return - children of the extension + * @see IConfigurationElement#getChildren() + */ + public ConfigurationElementDescription[] getChildren() { + return children; + } + + /** + * Returns name of the configuration element. + * @return - extension name + * @see IConfigurationElement#getName() + */ + public String getName() { + return name; + } + + /** + * Returns attributes of the configuration element. + * @return - attributes of the extension description + * @see IConfigurationElement#getAttribute(String) + */ + public ConfigurationElementAttribute[] getAttributes() { + return attributes; + } + + /** + * Returns string value stored in the configuration element. + * @return - String value to be stored in the element + * @see IConfigurationElement#getValue() + */ + public String getValue() { + return value; + } +} diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionDescription.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionDescription.java deleted file mode 100644 index c5b3f75ac..000000000 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionDescription.java +++ /dev/null @@ -1,110 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005 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.core.internal.registry.spi; - -/** - * Describes an extension to be added to the extension registry. - * - * It is expected that extension name is not null. Properties and children of - * the extension description might be null; value might be null as well. - * - * This class is not intended to be subclassed. - * - * @since org.eclipse.equinox.registry 1.0 - */ -public final class ExtensionDescription { - - /** - * Name of the extension. - */ - private String elementName; - - /** - * Properties of the extension element. - * @see ExtensionProperty - */ - private ExtensionProperty[] properties; - - /** - * String value to be stored in this configuration element. - */ - private String value; - - /** - * Children of the extension element. - */ - private ExtensionDescription[] children; - - /** - * Constructor. - * @param name - name of the extension - * @param properties - properties of the extension - * @param value - string value to be stored - * @param children - children of the extension element - */ - public ExtensionDescription(String name, ExtensionProperty[] properties, String value, ExtensionDescription[] children) { - this.elementName = name; - this.properties = properties; - this.value = value; - this.children = children; - } - - /** - * Constructor. - * @param name - name of the extension - * @param property - property of the extension - * @param value - string value to be stored - * @param children - children of the extension element - */ - public ExtensionDescription(String name, ExtensionProperty property, String value, ExtensionDescription[] children) { - this.elementName = name; - this.properties = new ExtensionProperty[] {property}; - this.value = value; - this.children = children; - } - - /** - * @return - children of the extension - */ - public ExtensionDescription[] getChildren() { - return children; - } - - /** - * @return - extension name - */ - public String getElementName() { - return elementName; - } - - /** - * @return - properties of the extension description - */ - public ExtensionProperty[] getProperties() { - return properties; - } - - /** - * @return true - extension description has some properties associated with it; false - no properties - * are associated with the extension description - */ - public boolean hasProperties() { - return (properties != null) ? properties.length != 0 : false; - } - - /** - * @return - String value to be stored in the element - */ - public String getValue() { - return value; - } - -} diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionProperty.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionProperty.java deleted file mode 100644 index 818d5e48a..000000000 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/core/internal/registry/spi/ExtensionProperty.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2005 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.core.internal.registry.spi; - -/** - * Describes properties of an extension. Properties are pairs of strings: - * {property name; property value}. - * - * It is expected that both property name and property value are not null. - * - * This class is not intended to be subclassed. - * - * @since org.eclipse.equinox.registry 1.0 - */ -public final class ExtensionProperty { - - /** - * Property name. - */ - private String name; - - /** - * Property value - */ - private String value; - - /** - * Constructor. - * @param name - property name - * @param value - property value - */ - public ExtensionProperty(String name, String value) { - this.name = name; - this.value = value; - } - - /** - * @return - property name - */ - public String getName() { - return name; - } - - /** - * @return - property value - */ - public String getValue() { - return value; - } -} diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/IExtensionRegistry.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/IExtensionRegistry.java index b4185cb37..bb6705de1 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/IExtensionRegistry.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/IExtensionRegistry.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2003, 2005 IBM Corporation and others. + * Copyright (c) 2003, 2006 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 @@ -51,7 +51,6 @@ import java.util.ResourceBundle; *

* This interface is not intended to be implemented by clients. *

- * @since 3.0 */ public interface IExtensionRegistry { /** @@ -232,7 +231,6 @@ public interface IExtensionRegistry { * empty array if there are no known extensions/extension points in this registry. * * @return all namespaces known to this registry - * @since 3.0 */ //TODO This needs to be clarified. public String[] getNamespaces(); @@ -249,36 +247,77 @@ public interface IExtensionRegistry { public void removeRegistryChangeListener(EventListener listener); /** - * Adds to the extension registry an extension point(s), extension(s), or - * a combination of those described by the XML file. - * - * If registry is no modifiable, this method is an access controlled method. - * Proper token is required for non-modifiable registries. - * - * @see org.eclipse.equinox.registry.spi.RegistryStrategy#isModifiable() - * - * @param is - stream open on the XML file. The XML file can contain an extension + * Adds to this extension registry an extension point(s), extension(s), or + * a combination of those described by the XML file. The information in + * the XML file should be supplied in the same format as the plugin.xml; in fact, + * Plug-in Manifest editor can be used to prepare the XML file. The top token + * of the contribution (normally, "plugin" or "fragment" in the Plug-in Manifest + * editor) is ignored by this method. + *

+ * This method is an access controlled method. Proper token (master token or user token) should + * be passed as an argument. + *

+ * @param is stream open on the XML file. The XML file can contain an extension * poin(s) or/and extension(s) described in the format similar to plugin.xml - * @param contributorId - ID of the supplier of this contribution - * @param name - optional name of the contribution. Used for error reporting; might be null - * @param translationBundle - optional resource bundle used for translations; might be null - * @param token - the key used to check permissions. The registry had two keys specified in its - * creation {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: - * master token and a user token. Use the user token to specify that contribution has dynamic - * nature. If registry is created with a registry strategy that specified isModifiable() as "true", - * null can be passed instead of a token. + * @param contributorId ID of the supplier of this contribution + * @param persist indicates if contribution should be stored in the registry cache. If false, + * contribution is not persisted in the registry cache and is lost on Eclipse restart + * @param name optional name of the contribution. Used for error reporting; might be null + * @param translationBundle optional resource bundle used for translations; might be null + * @param token the key used to check permissions. Two registry keys are set in the registry + * constructor {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: + * master token and a user token. Master token allows all operations; user token + * allows non-persisted registry elements to be modified. * @return - true: the contribution was successfully processed; false - error in * the processing of the contribution + * @throws IllegalArgumentException if incorrect token is passed + */ + public boolean addContribution(InputStream is, String contributorId, boolean persist, String name, ResourceBundle translationBundle, Object token) throws IllegalArgumentException; + + /** + * Removes extension. + * + * @param extension extension to be removed + * @param token the key used to check permissions. Two registry keys are set in the registry + * constructor {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: + * master token and a user token. Master token allows all operations; user token only + * allows non-persisted registry elements to be modified. + *

+ * This method is an access controlled method. Proper token (master token or user token) should + * be passed as an argument. + *

+ * @return true if the extension was successfully removed + * @throws IllegalArgumentException if incorrect token is passed + */ + public boolean removeExtension(IExtension extension, Object token) throws IllegalArgumentException; + + /** + * Removes extension point. + * + * @param extensionPoint extension point to be removed + * @param token the key used to check permissions. Two registry keys are set in the registry + * constructor {@link RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object)}: + * master token and a user token. Master token allows all operations; user token only + * allows non-persisted registry elements to be modified. + *

+ * This method is an access controlled method. Proper token (master token or user token) should + * be passed as an argument. + *

+ * @return true if the extension point was successfully removed + * @throws IllegalArgumentException if incorrect token is passed */ - public boolean addContribution(InputStream is, String contributorId, String name, ResourceBundle translationBundle, Object token); + public boolean removeExtensionPoint(IExtensionPoint extensionPoint, Object token) throws IllegalArgumentException; /** - * Call this method to properly stop the registry. It stops registry event processing + * Call this method to properly stop the registry. The method stops registry event processing * and writes out cache information to be used in the next run. This is an access controlled * method; master token is required. - * + *

+ * This method is an access controlled method. Master token should be passed as an argument. + *

* @see RegistryFactory#createRegistry(org.eclipse.equinox.registry.spi.RegistryStrategy, Object, Object) - * @param token - master token for the registry + * @param token master token for the registry + * @throws IllegalArgumentException if incorrect token is passed */ - public void stop(Object token); + public void stop(Object token) throws IllegalArgumentException; } diff --git a/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/spi/RegistryStrategy.java b/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/spi/RegistryStrategy.java index b5009d799..00091e63f 100644 --- a/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/spi/RegistryStrategy.java +++ b/bundles/org.eclipse.equinox.registry/src/org/eclipse/equinox/registry/spi/RegistryStrategy.java @@ -279,7 +279,7 @@ public class RegistryStrategy { } /** - * Specifies if lazy cahe loading is used. If cache startegy is not supplied, + * Specifies if lazy cache loading is used. If cache startegy is not supplied, * lazy cache loading is used. * * This basic implementation specifies that lazy cache loading is going to be used. -- cgit v1.2.3