/*******************************************************************************
 * 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.
 */
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.
		 */
		@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.
	 *
	 * @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.
	 * <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.
	 */
	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<>();
		for (int extPoint : element.getExtensionPoints()) {
			String namespace = this.addExtensionPoint(extPoint);
			if (namespace != null)
				affectedNamespaces.add(namespace);
		}
		for (int extension : element.getExtensions()) {
			String namespace = this.addExtension(extension);
			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 (String namespace : affectedNamespaces) {
			getDelta(namespace).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.
	 */
	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 (ExtensionHandle suspect : extensions) {
			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 extension : extensions) {
			ExtensionDelta extensionDelta = new ExtensionDelta();
			extensionDelta.setExtension(extension);
			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.
	 * <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) {
			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<>();
		for (int extension : registryObjects.getExtensionsFrom(contributorId)) {
			String namespace = this.removeExtension(extension);
			if (namespace != null)
				affectedNamespaces.add(namespace);
		}

		// remove extension points
		for (int extPoint : registryObjects.getExtensionPointsFrom(contributorId)) {
			String namespace = this.removeExtensionPoint(extPoint);
			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.
	 * @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() {
		for (String key : new String[] {TableReader.TABLE, TableReader.MAIN, TableReader.EXTRA, TableReader.CONTRIBUTIONS, TableReader.ORPHANS})
			try {
				cacheStorageManager.remove(key);
			} 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.
	 */
	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 (Object info : listenerInfos) {
			final ListenerInfo listenerInfo = (ListenerInfo) info;
			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 (Object delta : scheduledDeltas.values()) {
			((RegistryDelta) delta).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
	 *
	 * @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.
	 * <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.
	 * <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 (ConfigurationElementDescription element : children) {
				createExtensionData(contributorId, element, 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();
		}
	}

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