Copyright (c) 2000, 2018 IBM Corporation and others. This program and the accompanying materials are made available under the terms of the Eclipse Public License 2.0 which accompanies this distribution, and is available at https://www.eclipse.org/legal/epl-2.0/ SPDX-License-Identifier: EPL-2.0 Contributors: IBM Corporation - initial API and implementation Danail Nachev - exception handling for registry listeners (bug 188369)
/******************************************************************************* * Copyright (c) 2000, 2018 IBM Corporation and others. * * This program and the accompanying materials * are made available under the terms of the Eclipse Public License 2.0 * which accompanies this distribution, and is available at * https://www.eclipse.org/legal/epl-2.0/ * * SPDX-License-Identifier: EPL-2.0 * * Contributors: * IBM Corporation - initial API and implementation * Danail Nachev - exception handling for registry listeners (bug 188369) *******************************************************************************/
package org.eclipse.core.internal.registry; import java.io.*; import java.lang.reflect.Array; import java.util.*; import javax.xml.parsers.ParserConfigurationException; import org.eclipse.core.internal.registry.spi.ConfigurationElementAttribute; import org.eclipse.core.internal.registry.spi.ConfigurationElementDescription; import org.eclipse.core.runtime.*; import org.eclipse.core.runtime.spi.*; import org.eclipse.osgi.storagemanager.StorageManager; import org.eclipse.osgi.util.NLS; import org.xml.sax.InputSource; import org.xml.sax.SAXException;
An implementation for the extension registry API.
/** * An implementation for the extension registry API. */
public class ExtensionRegistry implements IExtensionRegistry, IDynamicExtensionRegistry { protected class ListenerInfo { public String filter; public EventListener listener; public ListenerInfo(EventListener listener, String filter) { this.listener = listener; this.filter = filter; }
Used by ListenerList to ensure uniqueness.
/** * Used by ListenerList to ensure uniqueness. */
@Override public boolean equals(Object another) { return another instanceof ListenerInfo && ((ListenerInfo) another).listener == this.listener; } /* (non-Javadoc) * @see java.lang.Object#hashCode() */ @Override public int hashCode() { return listener == null ? 0 : listener.hashCode(); } } // used to enforce concurrent access policy for readers/writers private final ReadWriteMonitor access = new ReadWriteMonitor(); // deltas not broadcasted yet. Deltas are kept organized by the namespace name (objects with the same namespace are grouped together) private transient Map<String, Object> deltas = new HashMap<>(11); //storage manager associated with the registry cache protected StorageManager cacheStorageManager; // all registry change listeners private transient ListenerList<ListenerInfo> listeners = new ListenerList<>(); private RegistryObjectManager registryObjects = null; // Table reader associated with this extension registry protected TableReader theTableReader = new TableReader(this); private final Object masterToken; // use to get full control of the registry; objects created as "static" private final Object userToken; // use to modify non-persisted registry elements protected RegistryStrategy strategy; // overridable portions of the registry functionality private final RegistryTimestamp aggregatedTimestamp = new RegistryTimestamp(); // tracks current contents of the registry // encapsulates processing of new registry deltas private CombinedEventDelta eventDelta = null; // marks a new extended delta. The namespace that normally would not exists is used for this purpose private final static String notNamespace = ""; //$NON-NLS-1$ // does this instance of the extension registry has multiple language support enabled? private final boolean isMultiLanguage; // have we already logged a error on usage of an unsupported multi-language method? private boolean mlErrorLogged = false; public RegistryObjectManager getObjectManager() { return registryObjects; }
Sets new cache file manager. If existing file manager was owned by the registry, closes it.
Params:
  • cacheBase – the base location for the registry cache
  • isCacheReadOnly – whether the file cache is read only
/** * Sets new cache file manager. If existing file manager was owned by the registry, * closes it. * * @param cacheBase the base location for the registry cache * @param isCacheReadOnly whether the file cache is read only */
protected void setFileManager(File cacheBase, boolean isCacheReadOnly) { if (cacheStorageManager != null) cacheStorageManager.close(); // close existing file manager first if (cacheBase != null) { cacheStorageManager = new StorageManager(cacheBase, isCacheReadOnly ? "none" : null, isCacheReadOnly); //$NON-NLS-1$ try { cacheStorageManager.open(!isCacheReadOnly); } catch (IOException e) { // Ignore the exception. The registry will be rebuilt from source. } } }
Adds and resolves all extensions and extension points provided by the plug-in.

A corresponding IRegistryChangeEvent will be broadcast to all listeners interested on changes in the given plug-in.

/** * Adds and resolves all extensions and extension points provided by the * plug-in. * <p> * A corresponding IRegistryChangeEvent will be broadcast to all listeners * interested on changes in the given plug-in. * </p> */
private void add(Contribution element) { access.enterWrite(); try { eventDelta = CombinedEventDelta.recordAddition(); basicAdd(element, true); fireRegistryChangeEvent(); eventDelta = null; } 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)); System.arraycopy(a, 0, result, 0, Array.getLength(a)); System.arraycopy(b, 0, result, Array.getLength(a), Array.getLength(b)); return result; } private String addExtension(int extension) { Extension addedExtension = (Extension) registryObjects.getObject(extension, RegistryObjectManager.EXTENSION); String extensionPointToAddTo = addedExtension.getExtensionPointIdentifier(); ExtensionPoint extPoint = registryObjects.getExtensionPointObject(extensionPointToAddTo); //orphan extension if (extPoint == null) { registryObjects.addOrphan(extensionPointToAddTo, extension); return null; } // otherwise, link them int[] newExtensions; int[] existingExtensions = extPoint.getRawChildren(); newExtensions = new int[existingExtensions.length + 1]; System.arraycopy(existingExtensions, 0, newExtensions, 0, existingExtensions.length); newExtensions[newExtensions.length - 1] = extension; link(extPoint, newExtensions); if (eventDelta != null) eventDelta.rememberExtension(extPoint, extension); return recordChange(extPoint, extension, IExtensionDelta.ADDED); }
Looks for existing orphan extensions to connect to the given extension point. If none is found, there is nothing to do. Otherwise, link them.
/** * Looks for existing orphan extensions to connect to the given extension * point. If none is found, there is nothing to do. Otherwise, link them. */
private String addExtensionPoint(int extPoint) { ExtensionPoint extensionPoint = (ExtensionPoint) registryObjects.getObject(extPoint, RegistryObjectManager.EXTENSION_POINT); if (eventDelta != null) eventDelta.rememberExtensionPoint(extensionPoint); int[] orphans = registryObjects.removeOrphans(extensionPoint.getUniqueIdentifier()); if (orphans == null) return null; link(extensionPoint, orphans); if (eventDelta != null) eventDelta.rememberExtensions(extensionPoint, orphans); return recordChange(extensionPoint, orphans, IExtensionDelta.ADDED); } private Set<String> addExtensionsAndExtensionPoints(Contribution element) { // now add and resolve extensions and extension points Set<String> affectedNamespaces = new HashSet<>(); int[] extPoints = element.getExtensionPoints(); for (int i = 0; i < extPoints.length; i++) { String namespace = this.addExtensionPoint(extPoints[i]); if (namespace != null) affectedNamespaces.add(namespace); } int[] extensions = element.getExtensions(); for (int i = 0; i < extensions.length; i++) { String namespace = this.addExtension(extensions[i]); if (namespace != null) affectedNamespaces.add(namespace); } return affectedNamespaces; } @Override public void addListener(IRegistryEventListener listener) { addListenerInternal(listener, null); } @Override public void addListener(IRegistryEventListener listener, String extensionPointId) { addListenerInternal(listener, extensionPointId); } private void addListenerInternal(EventListener listener, String filter) { synchronized (listeners) { listeners.add(new ListenerInfo(listener, filter)); } } @Override public void addRegistryChangeListener(IRegistryChangeListener listener) { // this is just a convenience API - no need to do any sync'ing here addListenerInternal(listener, null); } @Override public void addRegistryChangeListener(IRegistryChangeListener listener, String filter) { addListenerInternal(listener, filter); } private void basicAdd(Contribution element, boolean link) { registryObjects.addContribution(element); if (!link) return; Set<String> affectedNamespaces = addExtensionsAndExtensionPoints(element); setObjectManagers(affectedNamespaces, registryObjects.createDelegatingObjectManager(registryObjects.getAssociatedObjects(element.getContributorId()))); } private void setObjectManagers(Set<String> affectedNamespaces, IObjectManager manager) { for (Iterator<String> iter = affectedNamespaces.iterator(); iter.hasNext();) { getDelta(iter.next()).setObjectManager(manager); } if (eventDelta != null) eventDelta.setObjectManager(manager); } private void basicRemove(String contributorId) { // ignore anonymous namespaces Set<String> affectedNamespaces = removeExtensionsAndExtensionPoints(contributorId); Map<Integer, RegistryObject> associatedObjects = registryObjects.getAssociatedObjects(contributorId); registryObjects.removeObjects(associatedObjects); registryObjects.addNavigableObjects(associatedObjects); // put the complete set of navigable objects setObjectManagers(affectedNamespaces, registryObjects.createDelegatingObjectManager(associatedObjects)); registryObjects.removeContribution(contributorId); registryObjects.removeContributor(contributorId); } // allow other objects in the registry to use the same lock void enterRead() { access.enterRead(); } // allow other objects in the registry to use the same lock void exitRead() { access.exitRead(); }
Broadcasts (asynchronously) the event to all interested parties.
/** * Broadcasts (asynchronously) the event to all interested parties. */
private void fireRegistryChangeEvent() { // pack new extended delta together with the rest of deltas using invalid namespace deltas.put(notNamespace, eventDelta); // if there is nothing to say, just bail out if (listeners.isEmpty()) { deltas.clear(); return; } // for thread safety, create tmp collections Object[] tmpListeners = listeners.getListeners(); Map<String, Object> tmpDeltas = new HashMap<>(this.deltas); // the deltas have been saved for notification - we can clear them now deltas.clear(); // do the notification asynchronously strategy.scheduleChangeEvent(tmpListeners, tmpDeltas, this); } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String) */ @Override public IConfigurationElement[] getConfigurationElementsFor(String extensionPointId) { // this is just a convenience API - no need to do any sync'ing here int lastdot = extensionPointId.lastIndexOf('.'); if (lastdot == -1) return new IConfigurationElement[0]; return getConfigurationElementsFor(extensionPointId.substring(0, lastdot), extensionPointId.substring(lastdot + 1)); } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String, java.lang.String) */ @Override public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String extensionPointSimpleId) { // this is just a convenience API - no need to do any sync'ing here IExtensionPoint extPoint = this.getExtensionPoint(pluginId, extensionPointSimpleId); if (extPoint == null) return new IConfigurationElement[0]; return extPoint.getConfigurationElements(); } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getConfigurationElementsFor(java.lang.String, java.lang.String, java.lang.String) */ @Override public IConfigurationElement[] getConfigurationElementsFor(String pluginId, String extensionPointName, String extensionId) { // this is just a convenience API - no need to do any sync'ing here IExtension extension = this.getExtension(pluginId, extensionPointName, extensionId); if (extension == null) return new IConfigurationElement[0]; return extension.getConfigurationElements(); } private RegistryDelta getDelta(String namespace) { // is there a delta for the plug-in? RegistryDelta existingDelta = (RegistryDelta) deltas.get(namespace); if (existingDelta != null) return existingDelta; //if not, create one RegistryDelta delta = new RegistryDelta(); deltas.put(namespace, delta); return delta; } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String) */ @Override public IExtension getExtension(String extensionId) { if (extensionId == null) return null; int lastdot = extensionId.lastIndexOf('.'); if (lastdot == -1) return null; String namespace = extensionId.substring(0, lastdot); ExtensionHandle[] extensions; access.enterRead(); try { extensions = registryObjects.getExtensionsFromNamespace(namespace); } finally { access.exitRead(); } for (int i = 0; i < extensions.length; i++) { ExtensionHandle suspect = extensions[i]; if (extensionId.equals(suspect.getUniqueIdentifier())) return suspect; } return null; } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String, java.lang.String) */ @Override public IExtension getExtension(String extensionPointId, String extensionId) { // this is just a convenience API - no need to do any sync'ing here int lastdot = extensionPointId.lastIndexOf('.'); if (lastdot == -1) return null; return getExtension(extensionPointId.substring(0, lastdot), extensionPointId.substring(lastdot + 1), extensionId); } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtension(java.lang.String, java.lang.String, java.lang.String) */ @Override public IExtension getExtension(String pluginId, String extensionPointName, String extensionId) { // this is just a convenience API - no need to do any sync'ing here IExtensionPoint extPoint = getExtensionPoint(pluginId, extensionPointName); if (extPoint != null) return extPoint.getExtension(extensionId); return null; } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoint(java.lang.String) */ @Override public IExtensionPoint getExtensionPoint(String xptUniqueId) { access.enterRead(); try { return registryObjects.getExtensionPointHandle(xptUniqueId); } finally { access.exitRead(); } } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoint(java.lang.String, java.lang.String) */ @Override public IExtensionPoint getExtensionPoint(String elementName, String xpt) { access.enterRead(); try { return registryObjects.getExtensionPointHandle(elementName + '.' + xpt); } finally { access.exitRead(); } } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoints() */ @Override public IExtensionPoint[] getExtensionPoints() { access.enterRead(); try { return registryObjects.getExtensionPointsHandles(); } finally { access.exitRead(); } } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensionPoints(java.lang.String) */ @Override public IExtensionPoint[] getExtensionPoints(String namespaceName) { access.enterRead(); try { return registryObjects.getExtensionPointsFromNamespace(namespaceName); } finally { access.exitRead(); } } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getExtensions(java.lang.String) */ @Override public IExtension[] getExtensions(String namespaceName) { access.enterRead(); try { return registryObjects.getExtensionsFromNamespace(namespaceName); } finally { access.exitRead(); } } @Override public IExtension[] getExtensions(IContributor contributor) { if (!(contributor instanceof RegistryContributor)) throw new IllegalArgumentException(); // should never happen String contributorId = ((RegistryContributor) contributor).getActualId(); access.enterRead(); try { return registryObjects.getExtensionsFromContributor(contributorId); } finally { access.exitRead(); } } @Override public IExtensionPoint[] getExtensionPoints(IContributor contributor) { if (!(contributor instanceof RegistryContributor)) throw new IllegalArgumentException(); // should never happen String contributorId = ((RegistryContributor) contributor).getActualId(); access.enterRead(); try { return registryObjects.getExtensionPointsFromContributor(contributorId); } finally { access.exitRead(); } } /* * (non-Javadoc) * @see org.eclipse.core.runtime.IExtensionRegistry#getNamespaces() */ @Override public String[] getNamespaces() { access.enterRead(); try { KeyedElement[] namespaceElements = registryObjects.getNamespacesIndex().elements(); String[] namespaceNames = new String[namespaceElements.length]; for (int i = 0; i < namespaceElements.length; i++) { namespaceNames[i] = (String) ((RegistryIndexElement) namespaceElements[i]).getKey(); } return namespaceNames; } finally { access.exitRead(); } } @Override public boolean hasContributor(IContributor contributor) { if (!(contributor instanceof RegistryContributor)) throw new IllegalArgumentException(); // should never happen String contributorId = ((RegistryContributor) contributor).getActualId(); return hasContributor(contributorId); } public boolean hasContributor(String contributorId) { access.enterRead(); try { return registryObjects.hasContribution(contributorId); } finally { access.exitRead(); } } private void link(ExtensionPoint extPoint, int[] extensions) { extPoint.setRawChildren(extensions); registryObjects.add(extPoint, true); } /* * Records an extension addition/removal. */ private String recordChange(ExtensionPoint extPoint, int extension, int kind) { // avoid computing deltas when there are no listeners if (listeners.isEmpty()) return null; ExtensionDelta extensionDelta = new ExtensionDelta(); extensionDelta.setExtension(extension); extensionDelta.setExtensionPoint(extPoint.getObjectId()); extensionDelta.setKind(kind); getDelta(extPoint.getNamespace()).addExtensionDelta(extensionDelta); return extPoint.getNamespace(); } /* * Records a set of extension additions/removals. */ private String recordChange(ExtensionPoint extPoint, int[] extensions, int kind) { if (listeners.isEmpty()) return null; String namespace = extPoint.getNamespace(); if (extensions == null || extensions.length == 0) return namespace; RegistryDelta pluginDelta = getDelta(extPoint.getNamespace()); for (int i = 0; i < extensions.length; i++) { ExtensionDelta extensionDelta = new ExtensionDelta(); extensionDelta.setExtension(extensions[i]); extensionDelta.setExtensionPoint(extPoint.getObjectId()); extensionDelta.setKind(kind); pluginDelta.addExtensionDelta(extensionDelta); } return namespace; } public void remove(String removedContributorId, long timestamp) { remove(removedContributorId); if (timestamp != 0) aggregatedTimestamp.remove(timestamp); } @Override public void removeContributor(IContributor contributor, Object key) { if (!(contributor instanceof RegistryContributor)) throw new IllegalArgumentException(); // should never happen if (!checkReadWriteAccess(key, true)) throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.removeContributor() method. Check if proper access token is supplied."); //$NON-NLS-1$ String contributorId = ((RegistryContributor) contributor).getActualId(); remove(contributorId); }
Unresolves and removes all extensions and extension points provided by the plug-in.

A corresponding IRegistryChangeEvent will be broadcast to all listeners interested on changes in the given plug-in.

/** * Unresolves and removes all extensions and extension points provided by * the plug-in. * <p> * A corresponding IRegistryChangeEvent will be broadcast to all listeners * interested on changes in the given plug-in. * </p> */
public void remove(String removedContributorId) { access.enterWrite(); try { eventDelta = CombinedEventDelta.recordRemoval(); basicRemove(removedContributorId); fireRegistryChangeEvent(); eventDelta = null; } finally { access.exitWrite(); } } //Return the affected namespace private String removeExtension(int extensionId) { Extension extension = (Extension) registryObjects.getObject(extensionId, RegistryObjectManager.EXTENSION); registryObjects.removeExtensionFromNamespaceIndex(extensionId, extension.getNamespaceIdentifier()); String xptName = extension.getExtensionPointIdentifier(); ExtensionPoint extPoint = registryObjects.getExtensionPointObject(xptName); if (extPoint == null) { registryObjects.removeOrphan(xptName, extensionId); return null; } // otherwise, unlink the extension from the extension point int[] existingExtensions = extPoint.getRawChildren(); int[] newExtensions = RegistryObjectManager.EMPTY_INT_ARRAY; if (existingExtensions.length > 1) { if (existingExtensions.length == 1) newExtensions = RegistryObjectManager.EMPTY_INT_ARRAY; newExtensions = new int[existingExtensions.length - 1]; for (int i = 0, j = 0; i < existingExtensions.length; i++) if (existingExtensions[i] != extension.getObjectId()) newExtensions[j++] = existingExtensions[i]; } link(extPoint, newExtensions); if (eventDelta != null) eventDelta.rememberExtension(extPoint, extensionId); return recordChange(extPoint, extension.getObjectId(), IExtensionDelta.REMOVED); } private String removeExtensionPoint(int extPoint) { ExtensionPoint extensionPoint = (ExtensionPoint) registryObjects.getObject(extPoint, RegistryObjectManager.EXTENSION_POINT); registryObjects.removeExtensionPointFromNamespaceIndex(extPoint, extensionPoint.getNamespace()); int[] existingExtensions = extensionPoint.getRawChildren(); if (existingExtensions != null && existingExtensions.length != 0) { registryObjects.addOrphans(extensionPoint.getUniqueIdentifier(), existingExtensions); link(extensionPoint, RegistryObjectManager.EMPTY_INT_ARRAY); } if (eventDelta != null) { eventDelta.rememberExtensionPoint(extensionPoint); eventDelta.rememberExtensions(extensionPoint, existingExtensions); } return recordChange(extensionPoint, existingExtensions, IExtensionDelta.REMOVED); } private Set<String> removeExtensionsAndExtensionPoints(String contributorId) { Set<String> affectedNamespaces = new HashSet<>(); int[] extensions = registryObjects.getExtensionsFrom(contributorId); for (int i = 0; i < extensions.length; i++) { String namespace = this.removeExtension(extensions[i]); if (namespace != null) affectedNamespaces.add(namespace); } // remove extension points int[] extPoints = registryObjects.getExtensionPointsFrom(contributorId); for (int i = 0; i < extPoints.length; i++) { String namespace = this.removeExtensionPoint(extPoints[i]); if (namespace != null) affectedNamespaces.add(namespace); } return affectedNamespaces; } @Override public void removeRegistryChangeListener(IRegistryChangeListener listener) { synchronized (listeners) { listeners.remove(new ListenerInfo(listener, null)); } } @Override public void removeListener(IRegistryEventListener listener) { synchronized (listeners) { listeners.remove(new ListenerInfo(listener, null)); } } public ExtensionRegistry(RegistryStrategy registryStrategy, Object masterToken, Object userToken) { isMultiLanguage = "true".equals(RegistryProperties.getProperty(IRegistryConstants.PROP_MULTI_LANGUAGE)); //$NON-NLS-1$ if (registryStrategy != null) strategy = registryStrategy; else strategy = new RegistryStrategy(null, null); this.masterToken = masterToken; this.userToken = userToken; registryObjects = new RegistryObjectManager(this); boolean isRegistryFilledFromCache = false; // indicates if registry was able to use cache to populate it's content if (strategy.cacheUse()) { // Try to read the registry from the cache first. If that fails, create a new registry long start = 0; if (debug()) start = System.currentTimeMillis(); //The cache is made of several files, find the real names of these other files. If all files are found, try to initialize the objectManager if (checkCache()) { try { theTableReader.setTableFile(cacheStorageManager.lookup(TableReader.TABLE, false)); theTableReader.setExtraDataFile(cacheStorageManager.lookup(TableReader.EXTRA, false)); theTableReader.setMainDataFile(cacheStorageManager.lookup(TableReader.MAIN, false)); theTableReader.setContributionsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, false)); theTableReader.setContributorsFile(cacheStorageManager.lookup(TableReader.CONTRIBUTORS, false)); theTableReader.setNamespacesFile(cacheStorageManager.lookup(TableReader.NAMESPACES, false)); theTableReader.setOrphansFile(cacheStorageManager.lookup(TableReader.ORPHANS, false)); long timestamp = strategy.getContributionsTimestamp(); isRegistryFilledFromCache = registryObjects.init(timestamp); if (isRegistryFilledFromCache) aggregatedTimestamp.set(timestamp); } catch (IOException e) { // The registry will be rebuilt from the xml files. Make sure to clear anything filled // from cache so that we won't have partially filled items. isRegistryFilledFromCache = false; clearRegistryCache(); log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.registry_bad_cache, e)); } } if (!isRegistryFilledFromCache) { // set cache storage manager to a first writable location for (int index = 0; index < strategy.getLocationsLength(); index++) { if (!strategy.isCacheReadOnly(index)) { setFileManager(strategy.getStorage(index), false); break; } } } if (debug() && isRegistryFilledFromCache) System.out.println("Reading registry cache: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$ if (debug()) { if (!isRegistryFilledFromCache) System.out.println("Reloading registry from manifest files..."); //$NON-NLS-1$ else System.out.println("Using registry cache..."); //$NON-NLS-1$ } } if (debugEvents()) addRegistryChangeListener(System.out::println); // Do extra start processing if specified in the registry strategy strategy.onStart(this); // preserve for backward compatibility; might be removed later strategy.onStart(this, isRegistryFilledFromCache); }
Stops the registry. Registry has to be stopped to properly close cache and dispose of listeners.
Params:
  • key – - key token for this registry
/** * Stops the registry. Registry has to be stopped to properly * close cache and dispose of listeners. * @param key - key token for this registry */
@Override public void stop(Object key) { // If the registry creator specified a key token, check that the key mathches it // (it is assumed that registry owner keeps the key to prevent unautorized accesss). if (masterToken != null && masterToken != key) { throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.stop() method. Check if proper access token is supplied."); //$NON-NLS-1$ } // Do extra stop processing if specified in the registry strategy strategy.onStop(this); stopChangeEventScheduler(); if (cacheStorageManager == null) return; if (!registryObjects.isDirty() || cacheStorageManager.isReadOnly()) { cacheStorageManager.close(); theTableReader.close(); return; } File tableFile = null; File mainFile = null; File extraFile = null; File contributionsFile = null; File contributorsFile = null; File namespacesFile = null; File orphansFile = null; TableWriter theTableWriter = new TableWriter(this); try { cacheStorageManager.lookup(TableReader.TABLE, true); cacheStorageManager.lookup(TableReader.MAIN, true); cacheStorageManager.lookup(TableReader.EXTRA, true); cacheStorageManager.lookup(TableReader.CONTRIBUTIONS, true); cacheStorageManager.lookup(TableReader.CONTRIBUTORS, true); cacheStorageManager.lookup(TableReader.NAMESPACES, true); cacheStorageManager.lookup(TableReader.ORPHANS, true); tableFile = File.createTempFile(TableReader.TABLE, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ mainFile = File.createTempFile(TableReader.MAIN, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ extraFile = File.createTempFile(TableReader.EXTRA, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ contributionsFile = File.createTempFile(TableReader.CONTRIBUTIONS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ contributorsFile = File.createTempFile(TableReader.CONTRIBUTORS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ namespacesFile = File.createTempFile(TableReader.NAMESPACES, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ orphansFile = File.createTempFile(TableReader.ORPHANS, ".new", cacheStorageManager.getBase()); //$NON-NLS-1$ theTableWriter.setTableFile(tableFile); theTableWriter.setExtraDataFile(extraFile); theTableWriter.setMainDataFile(mainFile); theTableWriter.setContributionsFile(contributionsFile); theTableWriter.setContributorsFile(contributorsFile); theTableWriter.setNamespacesFile(namespacesFile); theTableWriter.setOrphansFile(orphansFile); } catch (IOException e) { cacheStorageManager.close(); return; //Ignore the exception since we can recompute the cache } try { long timestamp; // A bit of backward compatibility: if registry was modified, but timestamp was not, // it means that the new timestamp tracking mechanism was not used. In this case // explicitly obtain timestamps for all contributions. Note that this logic // maintains a problem described in the bug 104267 for contributions that // don't use the timestamp tracking mechanism. if (aggregatedTimestamp.isModifed()) timestamp = aggregatedTimestamp.getContentsTimestamp(); // use timestamp tracking else timestamp = strategy.getContributionsTimestamp(); // use legacy approach if (theTableWriter.saveCache(registryObjects, timestamp)) cacheStorageManager.update(new String[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.CONTRIBUTORS, TableReader.NAMESPACES, TableReader.ORPHANS}, new String[] {tableFile.getName(), mainFile.getName(), extraFile.getName(), contributionsFile.getName(), contributorsFile.getName(), namespacesFile.getName(), orphansFile.getName()}); } catch (IOException e) { //Ignore the exception since we can recompute the cache } theTableReader.close(); cacheStorageManager.close(); } /* * Clear the registry cache files from the file manager so on next start-up we recompute it. */ public void clearRegistryCache() { String[] keys = new String[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.ORPHANS}; for (int i = 0; i < keys.length; i++) try { cacheStorageManager.remove(keys[i]); } catch (IOException e) { log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, IStatus.ERROR, RegistryMessages.meta_registryCacheReadProblems, e)); } aggregatedTimestamp.reset(); } ///////////////////////////////////////////////////////////////////////////////////////////////// // Registry Object Factory // The factory produces contributions, extension points, extensions, and configuration elements // to be stored in the extension registry. protected RegistryObjectFactory theRegistryObjectFactory = null; // Override to provide domain-specific elements to be stored in the extension registry protected void setElementFactory() { if (isMultiLanguage) theRegistryObjectFactory = new RegistryObjectFactoryMulti(this); else theRegistryObjectFactory = new RegistryObjectFactory(this); } // Lazy initialization. public RegistryObjectFactory getElementFactory() { if (theRegistryObjectFactory == null) setElementFactory(); return theRegistryObjectFactory; } TableReader getTableReader() { return theTableReader; } public void log(IStatus status) { strategy.log(status); }
With multi-locale support enabled this method returns the non-translated key so that they can be cached and translated later into desired languages. In the absence of the multi-locale support the key gets translated immediately and only translated values is cached.
/** * With multi-locale support enabled this method returns the non-translated * key so that they can be cached and translated later into desired languages. * In the absence of the multi-locale support the key gets translated immediately * and only translated values is cached. */
public String translate(String key, ResourceBundle resources) { if (isMultiLanguage) return key; return strategy.translate(key, resources); } public boolean debug() { return strategy.debug(); } public boolean debugEvents() { return strategy.debugRegistryEvents(); } public boolean useLazyCacheLoading() { return strategy.cacheLazyLoading(); } public long computeState() { return strategy.getContainerTimestamp(); } // Find the first location that contains a cache table file and set file manager to it. protected boolean checkCache() { for (int index = 0; index < strategy.getLocationsLength(); index++) { File possibleCacheLocation = strategy.getStorage(index); if (possibleCacheLocation == null) break; // bail out on the first null setFileManager(possibleCacheLocation, strategy.isCacheReadOnly(index)); if (cacheStorageManager != null) { // check this new location: File cacheFile = null; try { cacheFile = cacheStorageManager.lookup(TableReader.getTestFileName(), false); } catch (IOException e) { //Ignore the exception. The registry will be rebuilt from the xml files. } if (cacheFile != null && cacheFile.isFile()) return true; // found the appropriate location } } return false; } public Object createExecutableExtension(RegistryContributor defaultContributor, String className, String requestedContributorName) throws CoreException { return strategy.createExecutableExtension(defaultContributor, className, requestedContributorName); } ////////////////////////////////////////////////////////////////////////////////////////// // Registry change events processing public IStatus processChangeEvent(Object[] listenerInfos, final Map<String, ?> scheduledDeltas) { // Separate new event delta from the pack final CombinedEventDelta extendedDelta = (CombinedEventDelta) scheduledDeltas.remove(notNamespace); final MultiStatus result = new MultiStatus(RegistryMessages.OWNER_NAME, IStatus.OK, RegistryMessages.plugin_eventListenerError, null); for (int i = 0; i < listenerInfos.length; i++) { final ListenerInfo listenerInfo = (ListenerInfo) listenerInfos[i]; if ((listenerInfo.listener instanceof IRegistryChangeListener) && scheduledDeltas.size() != 0) { if (listenerInfo.filter == null || scheduledDeltas.containsKey(listenerInfo.filter)) { SafeRunner.run(new ISafeRunnable() { @Override public void run() throws Exception { ((IRegistryChangeListener) listenerInfo.listener).registryChanged(new RegistryChangeEvent(scheduledDeltas, listenerInfo.filter)); } @Override public void handleException(Throwable exception) { result.add(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, RegistryMessages.plugin_eventListenerError, exception)); } }); } } if (listenerInfo.listener instanceof IRegistryEventListener) { IRegistryEventListener extensionListener = (IRegistryEventListener) listenerInfo.listener; IExtension[] extensions = extendedDelta.getExtensions(listenerInfo.filter); IExtensionPoint[] extensionPoints = extendedDelta.getExtensionPoints(listenerInfo.filter); // notification order - on addition: extension points; then extensions if (extendedDelta.isAddition()) { if (extensionPoints != null) extensionListener.added(extensionPoints); if (extensions != null) extensionListener.added(extensions); } else { // on removal: extensions; then extension points if (extensions != null) extensionListener.removed(extensions); if (extensionPoints != null) extensionListener.removed(extensionPoints); } } } for (Iterator<?> iter = scheduledDeltas.values().iterator(); iter.hasNext();) { ((RegistryDelta) iter.next()).getObjectManager().close(); } IObjectManager manager = extendedDelta.getObjectManager(); if (manager != null) manager.close(); return result; } private RegistryEventThread eventThread = null; // registry event loop protected final List<QueueElement> queue = new LinkedList<>(); // stores registry events info // Registry events notifications are done on a separate thread in a sequential manner // (first in - first processed) public void scheduleChangeEvent(Object[] listenerInfos, Map<String, ?> scheduledDeltas) { QueueElement newElement = new QueueElement(listenerInfos, scheduledDeltas); if (eventThread == null) { eventThread = new RegistryEventThread(this); eventThread.start(); } synchronized (queue) { queue.add(newElement); queue.notify(); } } // The pair of values we store in the event queue private class QueueElement { Object[] listenerInfos; Map<String, ?> scheduledDeltas; QueueElement(Object[] infos, Map<String, ?> deltas) { this.scheduledDeltas = deltas; listenerInfos = infos; } } private class RegistryEventThread extends Thread { private final ExtensionRegistry registry; public RegistryEventThread(ExtensionRegistry registry) { super("Extension Registry Event Dispatcher"); //$NON-NLS-1$ setDaemon(true); this.registry = registry; } @Override public void run() { while (true) { QueueElement element; synchronized (queue) { try { while (queue.isEmpty()) queue.wait(); } catch (InterruptedException e) { return; } element = queue.remove(0); } registry.processChangeEvent(element.listenerInfos, element.scheduledDeltas); } } } protected void stopChangeEventScheduler() { if (eventThread != null) { synchronized (queue) { eventThread.interrupt(); eventThread = null; } } }
Access check for add/remove operations: - Master key allows all operations - User key allows modifications of non-persisted elements
Params:
  • key – key to the registry supplied by the user
  • persist – true if operation affects persisted elements
Returns:true is the key grants read/write access to the registry
/** * Access check for add/remove operations: * - Master key allows all operations * - 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 (masterToken == key) return true; if (userToken == key && !persist) return true; return false; } public boolean addContribution(InputStream is, IContributor contributor, boolean persist, String contributionName, ResourceBundle translationBundle, Object key, long timestamp) { boolean result = addContribution(is, contributor, persist, contributionName, translationBundle, key); if (timestamp != 0) aggregatedTimestamp.add(timestamp); return result; } @Override public boolean addContribution(InputStream is, IContributor contributor, boolean persist, String contributionName, ResourceBundle translationBundle, Object key) { if (!checkReadWriteAccess(key, persist)) throw new IllegalArgumentException("Unauthorized access to the ExtensionRegistry.addContribution() method. Check if proper access token is supplied."); //$NON-NLS-1$ if (contributionName == null) contributionName = ""; //$NON-NLS-1$ RegistryContributor internalContributor = (RegistryContributor) contributor; registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present String ownerName = internalContributor.getActualName(); 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(internalContributor.getActualId(), persist); try { parser.parseManifest(strategy.getXMLParser(), new InputSource(is), contributionName, getObjectManager(), contribution, translationBundle); int status = problems.getSeverity(); if (status != IStatus.OK) { log(problems); if (status == IStatus.ERROR || status == IStatus.CANCEL) return false; } } catch (ParserConfigurationException | SAXException | IOException e) { logError(ownerName, contributionName, e); return false; } finally { try { is.close(); } catch (IOException ioe) { // nothing to do } } add(contribution); // the add() method does synchronization return true; } private void logError(String owner, String contributionName, Exception e) { String message = NLS.bind(RegistryMessages.parse_failedParsingManifest, owner + "/" + contributionName); //$NON-NLS-1$ log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, message, e)); }
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.

Params:
  • identifier – Id of the extension point. If non-qualified names is supplied, it will be converted internally into a fully qualified name
  • contributor – the contributor of this extension point
  • 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
  • label – display string for the extension point
  • schemaReference – reference to the extension point schema. The schema reference is a URL path relative to the plug-in installation URL. May be null
  • token – the key used to check permissions. Two registry keys are set in the registry constructor RegistryFactory.createRegistry(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:
Returns:true if successful, false if a problem was encountered
/** * Adds an extension point to the extension registry. * <p> * 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. * </p> * @param identifier Id of the extension point. If non-qualified names is supplied, * it will be converted internally into a fully qualified name * @param contributor the contributor of this extension point * @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.core.runtime.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 <code>true</code> if successful, <code>false</code> if a problem was encountered * @throws IllegalArgumentException if incorrect token is passed in */
public boolean addExtensionPoint(String identifier, IContributor contributor, 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$ RegistryContributor internalContributor = (RegistryContributor) contributor; registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present String contributorId = internalContributor.getActualId(); // Extension point Id might not be null 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$ // addition wraps in a contribution Contribution contribution = getElementFactory().createContribution(contributorId, persist); ExtensionPoint currentExtPoint = getElementFactory().createExtensionPoint(persist); String uniqueId; String namespaceName; int simpleIdStart = identifier.lastIndexOf('.'); if (simpleIdStart == -1) { namespaceName = contribution.getDefaultNamespace(); uniqueId = namespaceName + '.' + identifier; } else { namespaceName = identifier.substring(0, simpleIdStart); uniqueId = identifier; } currentExtPoint.setUniqueIdentifier(uniqueId); currentExtPoint.setNamespace(namespaceName); String labelNLS = translate(label, null); currentExtPoint.setLabel(labelNLS); currentExtPoint.setSchema(schemaReference); if (!getObjectManager().addExtensionPoint(currentExtPoint, true)) { if (debug()) { String msg = NLS.bind(RegistryMessages.parse_duplicateExtensionPoint, uniqueId, contribution.getDefaultNamespace()); log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, msg, null)); } return false; } currentExtPoint.setContributorId(contributorId); // array format: {Number of extension points, Number of extensions, Extension Id} int[] contributionChildren = new int[3]; // Put the extension points into this namespace contributionChildren[Contribution.EXTENSION_POINT] = 1; contributionChildren[Contribution.EXTENSION] = 0; contributionChildren[Contribution.EXTENSION + 1] = currentExtPoint.getObjectId(); contribution.setRawChildren(contributionChildren); add(contribution); return true; }
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.

Params:
  • identifier – Id of the extension. If non-qualified name is supplied, it will be converted internally into a fully qualified name
  • contributor – the contributor of this extension
  • 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
  • label – display string for this extension
  • extensionPointId – Id of the point being extended. If non-qualified name is supplied, it is assumed to have the same contributorId as this extension
  • configurationElements – contents of the extension
  • token – the key used to check permissions. Two registry keys are set in the registry constructor RegistryFactory.createRegistry(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:
See Also:
  • ConfigurationElementDescription
Returns:true if successful, false if a problem was encountered
/** * Adds an extension to the extension registry. * <p> * 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. * </p> * @see org.eclipse.core.internal.registry.spi.ConfigurationElementDescription * * @param identifier Id of the extension. If non-qualified name is supplied, * it will be converted internally into a fully qualified name * @param contributor the contributor of this extension * @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 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.core.runtime.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 <code>true</code> if successful, <code>false</code> if a problem was encountered * @throws IllegalArgumentException if incorrect token is passed in */
public boolean addExtension(String identifier, IContributor contributor, 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 RegistryContributor internalContributor = (RegistryContributor) contributor; registryObjects.addContributor(internalContributor); // only adds a contributor if it is not already present String contributorId = internalContributor.getActualId(); // addition wraps in a contribution Contribution contribution = getElementFactory().createContribution(contributorId, persist); Extension currentExtension = getElementFactory().createExtension(persist); String simpleId; String namespaceName; int simpleIdStart = identifier.lastIndexOf('.'); if (simpleIdStart != -1) { simpleId = identifier.substring(simpleIdStart + 1); namespaceName = identifier.substring(0, simpleIdStart); } else { simpleId = identifier; namespaceName = contribution.getDefaultNamespace(); } currentExtension.setSimpleIdentifier(simpleId); currentExtension.setNamespaceIdentifier(namespaceName); String extensionLabelNLS = translate(label, null); currentExtension.setLabel(extensionLabelNLS); String targetExtensionPointId; if (extensionPointId.indexOf('.') == -1) // No dots -> namespace name added at the start targetExtensionPointId = contribution.getDefaultNamespace() + '.' + extensionPointId; else targetExtensionPointId = extensionPointId; currentExtension.setExtensionPointIdentifier(targetExtensionPointId); // if we have an Id specified, check for duplicates. Only issue warning if duplicate found // as it might still work fine - depending on the access pattern. if (simpleId != null && debug()) { String uniqueId = namespaceName + '.' + simpleId; IExtension existingExtension = getExtension(uniqueId); if (existingExtension != null) { String currentSupplier = contribution.getDefaultNamespace(); String existingSupplier = existingExtension.getContributor().getName(); String msg = NLS.bind(RegistryMessages.parse_duplicateExtension, new String[] {currentSupplier, existingSupplier, uniqueId}); log(new Status(IStatus.WARNING, RegistryMessages.OWNER_NAME, 0, msg, null)); return false; } } getObjectManager().add(currentExtension, true); createExtensionData(contributorId, configurationElements, currentExtension, persist); currentExtension.setContributorId(contributorId); int[] contributionChildren = new int[3]; contributionChildren[Contribution.EXTENSION_POINT] = 0; contributionChildren[Contribution.EXTENSION] = 1; contributionChildren[Contribution.EXTENSION + 1] = currentExtension.getObjectId(); contribution.setRawChildren(contributionChildren); add(contribution); return true; } // Fill in the actual content of this extension private void createExtensionData(String contributorId, ConfigurationElementDescription description, RegistryObject parent, boolean persist) { ConfigurationElement currentConfigurationElement = getElementFactory().createConfigurationElement(persist); currentConfigurationElement.setContributorId(contributorId); currentConfigurationElement.setName(description.getName()); 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(); properties[i * 2 + 1] = translate(descriptionProperties[i].getValue(), null); } currentConfigurationElement.setProperties(properties); } else currentConfigurationElement.setProperties(RegistryObjectManager.EMPTY_STRING_ARRAY); String value = description.getValue(); if (value != null) currentConfigurationElement.setValue(value); getObjectManager().add(currentConfigurationElement, true); // process children ConfigurationElementDescription[] children = description.getChildren(); if (children != null) { for (int i = 0; i < children.length; i++) { createExtensionData(contributorId, children[i], currentConfigurationElement, persist); } } int[] oldValues = parent.getRawChildren(); int size = oldValues.length; int[] newValues = new int[size + 1]; for (int i = 0; i < size; i++) { newValues[i] = oldValues[i]; } newValues[size] = currentConfigurationElement.getObjectId(); parent.setRawChildren(newValues); currentConfigurationElement.setParentId(parent.getObjectId()); currentConfigurationElement.setParentType(parent instanceof ConfigurationElement ? RegistryObjectManager.CONFIGURATION_ELEMENT : RegistryObjectManager.EXTENSION); } @Override public boolean removeExtension(IExtension extension, Object token) throws IllegalArgumentException { if (!(extension instanceof ExtensionHandle)) return false; return removeObject(((ExtensionHandle) extension).getObject(), false, token); } @Override 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 { eventDelta = CombinedEventDelta.recordRemoval(); String namespace; if (isExtensionPoint) namespace = removeExtensionPoint(id); else namespace = removeExtension(id); Map<Integer, RegistryObject> removed = new HashMap<>(1); removed.put(Integer.valueOf(id), registryObject); // There is some asymmetry between extension and extension point removal. Removing extension point makes // extensions "orphans" but does not remove them. As a result, only extensions needs to be processed. if (!isExtensionPoint) registryObjects.addAssociatedObjects(removed, registryObject); registryObjects.removeObjects(removed); registryObjects.addNavigableObjects(removed); IObjectManager manager = registryObjects.createDelegatingObjectManager(removed); getDelta(namespace).setObjectManager(manager); eventDelta.setObjectManager(manager); registryObjects.unlinkChildFromContributions(id); fireRegistryChangeEvent(); eventDelta = null; } finally { access.exitWrite(); } return true; } @Override public IContributor[] getAllContributors() { access.enterRead(); try { return registryObjects.getContributorsSync(); } finally { access.exitRead(); } }
EXPERIMENTAL. This method has been added as part of a work in progress. There is a guarantee neither that this API will work nor that it will remain the same. Please do not use this method without consulting with the Equinox team.
/** * <strong>EXPERIMENTAL</strong>. This method has been added as part of a work in progress. * There is a guarantee neither that this API will work nor that it will remain the same. * Please do not use this method without consulting with the Equinox team. */
public Object getTemporaryUserToken() { return userToken; } @Override public boolean isMultiLanguage() { return isMultiLanguage; } public String[] translate(String[] nonTranslated, IContributor contributor, String locale) { return strategy.translate(nonTranslated, contributor, locale); } public String getLocale() { return strategy.getLocale(); } public void logMultiLangError() { if (mlErrorLogged) // only log this error ones return; log(new Status(IStatus.ERROR, RegistryMessages.OWNER_NAME, 0, RegistryMessages.registry_non_multi_lang, new IllegalArgumentException())); mlErrorLogged = true; } }