Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/infra/org.eclipse.papyrus.infra.extendedtypes/src/org/eclipse/papyrus/infra/extendedtypes/ConfigurableElementMatcherFactoryRegistry.java')
-rw-r--r--plugins/infra/org.eclipse.papyrus.infra.extendedtypes/src/org/eclipse/papyrus/infra/extendedtypes/ConfigurableElementMatcherFactoryRegistry.java246
1 files changed, 246 insertions, 0 deletions
diff --git a/plugins/infra/org.eclipse.papyrus.infra.extendedtypes/src/org/eclipse/papyrus/infra/extendedtypes/ConfigurableElementMatcherFactoryRegistry.java b/plugins/infra/org.eclipse.papyrus.infra.extendedtypes/src/org/eclipse/papyrus/infra/extendedtypes/ConfigurableElementMatcherFactoryRegistry.java
new file mode 100644
index 00000000000..533e7b86434
--- /dev/null
+++ b/plugins/infra/org.eclipse.papyrus.infra.extendedtypes/src/org/eclipse/papyrus/infra/extendedtypes/ConfigurableElementMatcherFactoryRegistry.java
@@ -0,0 +1,246 @@
+/*****************************************************************************
+ * Copyright (c) 2013 CEA LIST.
+ *
+ * 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:
+ * Remi Schnekenburger (CEA LIST) - Initial API and implementation
+ *
+ *****************************************************************************/
+package org.eclipse.papyrus.infra.extendedtypes;
+
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import org.eclipse.core.runtime.IConfigurationElement;
+import org.eclipse.core.runtime.Platform;
+import org.eclipse.gmf.runtime.emf.type.core.IElementMatcher;
+import org.osgi.framework.Bundle;
+
+/**
+ * Registry for all element matcher factories for element matcher based on {@link MatcherConfiguration}.
+ */
+public class ConfigurableElementMatcherFactoryRegistry {
+
+ /** private singleton instance */
+ private static ConfigurableElementMatcherFactoryRegistry registry;
+
+ protected Map<String, IConfigurableElementMatcherFactory<MatcherConfiguration>> configurationTypeToMatcherFactory = null;
+
+ protected List<String> configurationTypeFactoryExceptions = null;
+
+ /**
+ * returns the singleton instance of this registry
+ *
+ * @return the singleton instance of this registry
+ */
+ public static synchronized ConfigurableElementMatcherFactoryRegistry getInstance() {
+ if(registry == null) {
+ registry = new ConfigurableElementMatcherFactoryRegistry();
+ registry.init();
+ }
+ return registry;
+ }
+
+ /**
+ * Inits the registry.
+ */
+ protected void init() {
+ configurationTypeToMatcherFactory = new HashMap<String, IConfigurableElementMatcherFactory<MatcherConfiguration>>();
+
+ }
+
+ /**
+ * Creates the {@link IElementMatcher} specific to the given rule configuration
+ *
+ * @param ruleConfiguration
+ * the rule configuration that will configure the created matcher
+ * @return the {@link IElementMatcher} created or <code>null</code> if none could be created
+ */
+ public IConfigurableElementMatcher<MatcherConfiguration> createElementMatcher(MatcherConfiguration matcherConfiguration) {
+ String configurationType = matcherConfiguration.eClass().getInstanceTypeName();
+ IConfigurableElementMatcherFactory<MatcherConfiguration> factory = configurationTypeToMatcherFactory.get(configurationType);
+ // check factory is not on the exception table
+ if(factory == null && isNotInFactoryExceptionList(configurationType)) {
+ Class<IConfigurableElementMatcherFactory<MatcherConfiguration>> factoryClass = retrieveFactoryClassFromExtensionPoint(configurationType);
+ if(factoryClass != null) {
+ try {
+ factory = factoryClass.newInstance();
+ } catch (InstantiationException e) {
+ if(configurationTypeFactoryExceptions == null) {
+ configurationTypeFactoryExceptions = new ArrayList<String>();
+ }
+ configurationTypeFactoryExceptions.add(configurationType);
+ } catch (IllegalAccessException e) {
+ if(configurationTypeFactoryExceptions == null) {
+ configurationTypeFactoryExceptions = new ArrayList<String>();
+ }
+ configurationTypeFactoryExceptions.add(configurationType);
+ }
+ configurationTypeToMatcherFactory.put(configurationType, factory);
+ }
+ }
+ if(factory != null) {
+ IConfigurableElementMatcher<MatcherConfiguration> elementMatcher = factory.createElementMatcher(matcherConfiguration);
+ if(elementMatcher !=null) {
+ //elementMatcher.init(matcherConfiguration);
+ return elementMatcher;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * check this configuration type has not already caused issues du
+ *
+ * @param configurationType
+ * @return
+ */
+ protected boolean isNotInFactoryExceptionList(String configurationType) {
+ if(configurationTypeFactoryExceptions == null) {
+ return true;
+ }
+ // this is not null, check the configuration type is not in the list
+ return !configurationTypeFactoryExceptions.contains(configurationType);
+ }
+
+ /**
+ * Returns the {@link IExtendedElementTypeFactory} class used to instantiate element type for the given configuration
+ *
+ * @return the {@link IExtendedElementTypeFactory} found or <code>null</code> if none was found
+ */
+ @SuppressWarnings("unchecked")
+ protected Class<IConfigurableElementMatcherFactory<MatcherConfiguration>> retrieveFactoryClassFromExtensionPoint(String configurationType) {
+ IConfigurationElement[] elements = Platform.getExtensionRegistry().getConfigurationElementsFor(IElementMatcherExtensionPoint.EXTENSION_POINT_ID);
+ for(IConfigurationElement configurationElement : elements) {
+ String eCoreClassName = configurationElement.getAttribute(IElementMatcherExtensionPoint.MATCHER_CONFIGURATION_CLASS);
+ if(configurationType.equals(eCoreClassName)) {
+ // retrieve factory to load
+ String factoryClassName = configurationElement.getAttribute(IElementMatcherExtensionPoint.MATCHER_FACTORY_CLASS);
+ return (Class<IConfigurableElementMatcherFactory<MatcherConfiguration>>)loadClass(factoryClassName, configurationElement.getContributor().getName());
+ }
+ }
+ return null;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // loading resource
+ ///////////////////////////////////////////////////////////////////////////
+ /** A map of classes that have been successfully loaded, keyed on the class name optionally prepended by the plugin ID, if specified. */
+ private static Map<String, WeakReference<Class<?>>> successLookupTable = new HashMap<String, WeakReference<Class<?>>>();
+
+ /** A map of classes that could not be loaded, keyed on the class name, optionally prepended by the plugin ID if specified. */
+ private static Set<String> failureLookupTable = new HashSet<String>();
+
+ /** A map to hold the bundle to exception list */
+ private static Map<Bundle, Set<String>> bundleToExceptionsSetMap = new HashMap<Bundle, Set<String>>();
+
+ /**
+ * A utility method to load a class using its name and a given class loader.
+ *
+ * @param className
+ * The class name
+ * @param bundle
+ * The class loader
+ * @return The loaded class or <code>null</code> if could not be loaded
+ */
+ protected static Class<?> loadClass(String className, String pluginId) {
+ StringBuffer keyStringBuf = new StringBuffer(className.length() + pluginId.length() + 2); // 2 is for . and extra.
+ keyStringBuf.append(pluginId);
+ keyStringBuf.append('.');
+ keyStringBuf.append(className);
+ String keyString = keyStringBuf.toString();
+ WeakReference<Class<?>> ref = successLookupTable.get(keyString);
+ Class<?> found = (ref != null) ? ref.get() : null;
+ if(found == null) {
+ if(ref != null)
+ successLookupTable.remove(keyString);
+ if(!failureLookupTable.contains(keyString)) {
+ try {
+ Bundle bundle = basicGetPluginBundle(pluginId);
+ if(bundle != null) {
+ // never load the class if the bundle is not active other wise
+ // we will cause the plugin to load
+ // unless the class is in the exception list
+ int state = bundle.getState();
+ if(state == org.osgi.framework.Bundle.ACTIVE || isInExceptionList(bundle, className)) {
+ found = bundle.loadClass(className);
+ successLookupTable.put(keyString, new WeakReference<Class<?>>(found));
+ if(state == org.osgi.framework.Bundle.ACTIVE) {
+ bundleToExceptionsSetMap.remove(bundle);
+ }
+ }
+ } else {
+ failureLookupTable.add(keyString);
+ }
+ } catch (ClassNotFoundException e) {
+ failureLookupTable.add(keyString);
+ }
+ }
+ }
+ return found;
+ }
+
+ /**
+ * Given a bundle id, it checks if the bundle is found and activated. If it
+ * is, the method returns the bundle, otherwise it returns <code>null</code>.
+ *
+ * @param pluginId
+ * the bundle ID
+ * @return the bundle, if found
+ */
+ protected static Bundle getPluginBundle(String pluginId) {
+ Bundle bundle = basicGetPluginBundle(pluginId);
+ if(null != bundle && bundle.getState() == org.osgi.framework.Bundle.ACTIVE)
+ return bundle;
+ return null;
+ }
+
+ private static Bundle basicGetPluginBundle(String pluginId) {
+ return Platform.getBundle(pluginId);
+ }
+
+ private static boolean isInExceptionList(Bundle bundle, String className) {
+ String packageName = className.substring(0, className.lastIndexOf('.'));
+ Set<String> exceptionSet = bundleToExceptionsSetMap.get(bundle);
+ if(exceptionSet == null) {
+ Dictionary<String, String> dict = bundle.getHeaders();
+ String value = dict.get("Eclipse-LazyStart"); //$NON-NLS-1$
+ if(value != null) {
+ int index = value.indexOf("exceptions"); //$NON-NLS-1$
+ if(index != -1) {
+ try {
+ int start = value.indexOf('"', index + 1);
+ int end = value.indexOf('"', start + 1);
+ String exceptions = value.substring(start + 1, end);
+ exceptionSet = new HashSet<String>(2);
+ StringTokenizer tokenizer = new StringTokenizer(exceptions, ","); //$NON-NLS-1$
+ while(tokenizer.hasMoreTokens()) {
+ exceptionSet.add(tokenizer.nextToken().trim());
+ }
+ } catch (IndexOutOfBoundsException exception) {
+ // this means the MF did not follow the documented format for the exceptions list so i'll consider it empty
+ exceptionSet = Collections.emptySet();
+ }
+ } else {
+ exceptionSet = Collections.emptySet();
+ }
+ } else {
+ exceptionSet = Collections.emptySet();
+ }
+ bundleToExceptionsSetMap.put(bundle, exceptionSet);
+ }
+ return exceptionSet.contains(packageName);
+ }
+}

Back to the top