| /******************************************************************************** |
| * Copyright (c) 2011 Eike Stepper (Berlin, Germany) and others. |
| * |
| * All rights reserved. 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: |
| * Eike Stepper - initial API and implementation |
| ********************************************************************************/ |
| package org.eclipse.emf.ecp.internal.core.util; |
| |
| import java.io.File; |
| import java.util.HashSet; |
| import java.util.Set; |
| |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExtension; |
| import org.eclipse.core.runtime.IExtensionDelta; |
| import org.eclipse.core.runtime.IExtensionPoint; |
| import org.eclipse.core.runtime.IRegistryChangeEvent; |
| import org.eclipse.core.runtime.IRegistryChangeListener; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.emf.ecp.spi.core.util.ECPDisposable; |
| import org.eclipse.emf.ecp.spi.core.util.InternalRegistryElement; |
| import org.eclipse.net4j.util.lifecycle.Lifecycle; |
| import org.osgi.framework.Bundle; |
| |
| /** |
| * @author Eike Stepper |
| * @param <ELEMENT> |
| */ |
| public abstract class ExtensionParser<ELEMENT extends InternalRegistryElement> extends Lifecycle implements |
| IRegistryChangeListener { |
| private final ElementRegistry<ELEMENT, ?> elementRegistry; |
| |
| private final String namespace; |
| |
| private final String name; |
| |
| public ExtensionParser(ElementRegistry<ELEMENT, ?> elementRegistry, String namespace, String name) { |
| this.elementRegistry = elementRegistry; |
| this.namespace = namespace; |
| this.name = name; |
| } |
| |
| public final ElementRegistry<ELEMENT, ?> getElementRegistry() { |
| return elementRegistry; |
| } |
| |
| public final String getNamespace() { |
| return namespace; |
| } |
| |
| public final String getName() { |
| return name; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public void registryChanged(IRegistryChangeEvent event) { |
| final Set<String> remove = new HashSet<String>(); |
| final Set<ELEMENT> add = new HashSet<ELEMENT>(); |
| for (final IExtensionDelta delta : event.getExtensionDeltas(namespace, name)) { |
| final IExtension extension = delta.getExtension(); |
| final int kind = delta.getKind(); |
| switch (kind) { |
| case IExtensionDelta.ADDED: |
| addExtension(extension, add); |
| break; |
| |
| case IExtensionDelta.REMOVED: |
| removeExtension(extension, remove); |
| break; |
| } |
| } |
| |
| final Set<ELEMENT> removedElements = elementRegistry.doChangeElements(remove, add); |
| if (removedElements != null) { |
| for (final ELEMENT removedElement : removedElements) { |
| if (removedElement instanceof ECPDisposable) { |
| final ECPDisposable disposable = removedElement; |
| disposable.dispose(); |
| } |
| } |
| } |
| } |
| |
| @Override |
| protected void doActivate() throws Exception { |
| super.doActivate(); |
| |
| final String extensionPointID = namespace + "." + name; //$NON-NLS-1$ |
| final Set<ELEMENT> add = new HashSet<ELEMENT>(); |
| |
| final IExtensionPoint extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(extensionPointID); |
| for (final IExtension extension : extensionPoint.getExtensions()) { |
| addExtension(extension, add); |
| } |
| |
| elementRegistry.doChangeElements(null, add); |
| Platform.getExtensionRegistry().addRegistryChangeListener(this, namespace); |
| } |
| |
| @Override |
| protected void doDeactivate() throws Exception { |
| Platform.getExtensionRegistry().removeRegistryChangeListener(this); |
| super.doDeactivate(); |
| } |
| |
| protected void addExtension(IExtension extension, Set<ELEMENT> result) { |
| final String name = extension.getUniqueIdentifier(); |
| final IConfigurationElement configurationElement = extension.getConfigurationElements()[0]; |
| |
| final ELEMENT element = createElement(name, configurationElement); |
| element.setLabel(extension.getLabel()); |
| element.setDescription(configurationElement.getAttribute("description")); //$NON-NLS-1$ |
| result.add(element); |
| } |
| |
| protected void removeExtension(IExtension extension, Set<String> result) { |
| final String name = extension.getUniqueIdentifier(); |
| result.add(name); |
| } |
| |
| protected abstract ELEMENT createElement(String name, IConfigurationElement configurationElement); |
| |
| /** |
| * @author Eike Stepper |
| */ |
| public static class ExtensionDescriptor<ELEMENT extends InternalRegistryElement> |
| extends ElementDescriptor<ELEMENT> { |
| private final String type; |
| |
| private final IConfigurationElement configurationElement; |
| |
| public ExtensionDescriptor(ElementRegistry<ELEMENT, ?> registry, String name, String type, |
| IConfigurationElement configurationElement) { |
| super(registry, name); |
| this.type = type; |
| this.configurationElement = configurationElement; |
| |
| try { |
| final String bundleName = configurationElement.getContributor().getName(); |
| final Bundle bundle = Platform.getBundle(bundleName); |
| String location = bundle.getLocation(); |
| |
| if (location.startsWith("initial@")) { //$NON-NLS-1$ |
| location = location.substring("initial@".length()); //$NON-NLS-1$ |
| } |
| |
| final String prefix = "reference:file:"; //$NON-NLS-1$ |
| if (location.startsWith(prefix)) { |
| location = location.substring(prefix.length()); |
| |
| // TODO Trace properly |
| System.out.println(getClass().getSimpleName() + ": " + bundleName + " [" + bundle.getBundleId() //$NON-NLS-1$ //$NON-NLS-2$ |
| + "] --> file:" + new File(location).getCanonicalPath()); //$NON-NLS-1$ |
| } |
| } catch (final Exception ex) { |
| ex.printStackTrace(); |
| } |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String getType() { |
| return type; |
| } |
| |
| public final IConfigurationElement getConfigurationElement() { |
| return configurationElement; |
| } |
| |
| @Override |
| @SuppressWarnings("unchecked") |
| protected ELEMENT resolve() throws Exception { |
| return (ELEMENT) configurationElement.createExecutableExtension(getClassAttributeName()); |
| } |
| |
| protected String getClassAttributeName() { |
| return "class"; //$NON-NLS-1$ |
| } |
| } |
| } |