/******************************************************************************* * Copyright (c) 2007, 2010 Association for Decentralized Information Management * in Industry THTH ry. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * VTT Technical Research Centre of Finland - initial API and implementation *******************************************************************************/ package org.simantics.browsing.ui.common.extension; import java.util.Arrays; import java.util.HashSet; import java.util.Set; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IExtensionPoint; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.dynamichelpers.ExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IExtensionChangeHandler; import org.eclipse.core.runtime.dynamichelpers.IExtensionTracker; import org.eclipse.core.runtime.dynamichelpers.IFilter; import org.simantics.browsing.ui.common.Activator; import org.simantics.browsing.ui.common.extension.internal.ContributorBindingExtension; import org.simantics.browsing.ui.common.extension.internal.ContributorImplementationBinding; import org.simantics.browsing.ui.common.extension.internal.ContributorReferenceBinding; import org.simantics.browsing.ui.content.Contributor; import org.simantics.browsing.ui.content.ContributorBinding; import org.simantics.scl.reflection.OntologyVersions; import org.simantics.utils.strings.StringUtils; /** * @author Antti Villberg */ public abstract class ContributorBindingExtensionManager implements IExtensionChangeHandler { private final static String NAMESPACE = Activator.PLUGIN_ID; private ExtensionTracker tracker; private static final OntologyVersions VERSIONS = OntologyVersions.getInstance(); @SuppressWarnings("unchecked") private ContributorBindingExtension[] extensions = new ContributorBindingExtension[0]; abstract String getExtensionPointName(); ContributorBindingExtensionManager() { tracker = new ExtensionTracker(); // Cache defined actions IExtensionPoint expt = Platform.getExtensionRegistry().getExtensionPoint(NAMESPACE, getExtensionPointName()); loadExtensions(expt.getConfigurationElements()); // Start tracking for new and removed extensions IFilter filter = ExtensionTracker.createExtensionPointFilter(expt); tracker.registerHandler(this, filter); } @SuppressWarnings("unchecked") void close() { tracker.close(); tracker = null; extensions = new ContributorBindingExtension[0]; } public ContributorBindingExtension[] getExtensions() { return extensions; } abstract ContributorReferenceBinding createReferenceBinding(double preference, String browseContext, String factoryId); @SuppressWarnings("unchecked") private void loadExtensions(IConfigurationElement[] elements) { Set> newExtensions = new HashSet>(Arrays.asList(extensions)); for (IConfigurationElement el : elements) { String browseContext = VERSIONS.currentVersion(StringUtils.safeString(el.getAttribute("browseContext"))); for(IConfigurationElement child : el.getChildren("reference")) { double preference = StringUtils.safeDouble(child.getAttribute("preference")); String factoryId = StringUtils.safeString(child.getAttribute("id")); // ContributionBindingExtension ext = new ImagerContributionReferenceBinding(preference, browseContext, factoryId); ContributorBindingExtension ext = createReferenceBinding(preference, browseContext, factoryId); // Start tracking the new extension object, its removal will be notified of // with removeExtension(extension, Object[]). tracker.registerObject(el.getDeclaringExtension(), ext, IExtensionTracker.REF_STRONG); newExtensions.add(ext); } for(IConfigurationElement child : el.getChildren("implementation")) { double preference = StringUtils.safeDouble(child.getAttribute("preference")); try { Contributor factory = (Contributor) child.createExecutableExtension("class"); ContributorBindingExtension ext = new ContributorImplementationBinding(preference, browseContext, factory); // Start tracking the new extension object, its removal will be notified of // with removeExtension(extension, Object[]). tracker.registerObject(el.getDeclaringExtension(), ext, IExtensionTracker.REF_STRONG); newExtensions.add(ext); } catch (CoreException e) { System.out.println(" == Could not load ViewpointContributionFactory '" + child.getAttribute("class") + "' due to the following error: " + e.getMessage() ); } } } // Atomic assignment this.extensions = newExtensions.toArray(new ContributorBindingExtension[newExtensions.size()]); } @Override public void addExtension(IExtensionTracker tracker, IExtension extension) { loadExtensions(extension.getConfigurationElements()); } @SuppressWarnings("unchecked") @Override public void removeExtension(IExtension extension, Object[] objects) { Set> newExtensions = new HashSet>(Arrays.asList(extensions)); for (Object o : objects) { tracker.unregisterObject(extension, o); newExtensions.remove(o); } // Atomic assignment this.extensions = newExtensions.toArray(new ContributorBindingExtension[newExtensions.size()]); } public Set> getBoundContributions(Set browseContexts) { HashSet> result = new HashSet>(); for(ContributorBindingExtension binding : getExtensions()) { if(browseContexts.contains(binding.getBrowseContext())) { Contributor factory = binding.getFactory(); if(factory != null) { // System.out.println("----------- Plugin contribution " + binding.getFactory() + " " + binding.getPreference()); result.add(new ContributorBindingImpl(binding.getPreference(), factory)); } else { // System.out.println("FAILED: ----------- No factory for " + binding); } } } return result; } }