| /* |
| * Copyright (c) 2005, 2010 Borland Software Corporation and others |
| * |
| * 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: |
| * Artem Tikhomirov (Borland) - initial API and implementation |
| */ |
| package org.eclipse.gmf.tests.setup; |
| |
| import java.net.MalformedURLException; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.LinkedList; |
| import java.util.StringTokenizer; |
| |
| import junit.framework.Assert; |
| |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IRegistryChangeEvent; |
| import org.eclipse.core.runtime.IRegistryChangeListener; |
| import org.eclipse.core.runtime.InvalidRegistryObjectException; |
| import org.eclipse.core.runtime.Platform; |
| import org.eclipse.core.runtime.RegistryFactory; |
| import org.eclipse.emf.common.notify.AdapterFactory; |
| import org.eclipse.emf.ecore.plugin.RegistryReader.PluginClassDescriptor; |
| import org.eclipse.emf.ecore.resource.Resource; |
| import org.eclipse.emf.edit.provider.ComposedAdapterFactory; |
| import org.eclipse.gmf.codegen.gmfgen.GenEditorGenerator; |
| import org.eclipse.gmf.tests.JobTracker; |
| import org.eclipse.gmf.tests.Plugin; |
| import org.eclipse.gmf.tests.Utils; |
| import org.eclipse.swt.widgets.Display; |
| import org.osgi.framework.Bundle; |
| import org.osgi.framework.BundleException; |
| |
| /** |
| * Installs generated GMF plugins to allow invocation of generated code |
| * @author artem |
| */ |
| public class GenProjectSetup extends GenProjectBaseSetup { |
| |
| private ArrayList<Bundle> myAllInstalledBundes = new ArrayList<Bundle>(); |
| private Bundle myBundle; |
| private final boolean myIsFullRuntimeRun; |
| |
| public GenProjectSetup(GeneratorConfiguration generatorFactory) { |
| super(generatorFactory); |
| myIsFullRuntimeRun = generatorFactory instanceof RuntimeBasedGeneratorConfiguration; |
| } |
| |
| public GenProjectSetup init(DiaGenSource diaGenSource) throws BundleException { |
| return init(diaGenSource.getGenDiagram().getEditorGen()); |
| } |
| |
| /** |
| * Assertion fails on compilation errors. |
| * @return <code>this</code> for convenience |
| * @throws BundleException only when shouldInstallInRuntime is true and bundle install fails |
| * FIXME introduce DiaGenSourceBase with single getDiagram() accessor |
| */ |
| public GenProjectSetup init(GenEditorGenerator genEditor) throws BundleException { |
| final boolean[] extensionChangeNotification = new boolean[] {true}; |
| final IRegistryChangeListener listener = new IRegistryChangeListener() { |
| public void registryChanged(IRegistryChangeEvent event) { |
| extensionChangeNotification[0] = false; |
| } |
| }; |
| try { |
| if (myIsFullRuntimeRun) { |
| RegistryFactory.getRegistry().addRegistryChangeListener(listener, "org.eclipse.gmf.runtime.emf.type.core"); |
| } else { |
| //Wait for org.eclipse.ui.editors extension point to update. Otherwise, AbstractDiagramEditorTest subclasses fail mysteriously. |
| RegistryFactory.getRegistry().addRegistryChangeListener(listener, "org.eclipse.ui"); |
| } |
| myBundle = null; |
| JobTracker jt = new JobTracker(); |
| jt.start(); |
| generateAndCompile(genEditor); |
| myBundle.start(); |
| jt.freeze(); |
| // System.out.println("Jobs to wait:" + jt.getJobsCount()); 13! |
| registerExtensions(myBundle); |
| registerEMFEditExtensions(); |
| // there should be hit, any .diagram plugin is supposed to register extensions we monitor with the listener above. |
| monitorExtensionLoad(extensionChangeNotification, 60); |
| monitorExtensionLoad(jt.getNonEmptyCondition(), 10); |
| jt.stop(); |
| } catch (BundleException ex) { |
| throw ex; |
| } catch (Exception ex) { |
| Assert.fail(ex.getClass().getSimpleName() + ":" + ex.getMessage()); |
| } finally { |
| RegistryFactory.getRegistry().removeRegistryChangeListener(listener); |
| } |
| return this; |
| } |
| |
| /** |
| * Workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=136446 |
| */ |
| private void monitorExtensionLoad(boolean[] flag, int timeoutSeconds) { |
| if (null != Display.getCurrent()) { |
| if (!Utils.dispatchDisplayMessages(flag, timeoutSeconds)) { |
| // timeout |
| Plugin.logError("Timeout while waiting for extension point registry to refresh !!!"); |
| // left caller on its own... |
| } |
| } |
| } |
| |
| protected void hookProjectBuild(IProject p) throws Exception { |
| super.hookProjectBuild(p); |
| try { |
| String url = p.getLocation().toFile().toURL().toExternalForm(); |
| myBundle = Plugin.getBundleContext().installBundle(url); |
| myAllInstalledBundes.add(myBundle); |
| } catch (MalformedURLException ex) { |
| Assert.fail(ex.getMessage()); |
| } |
| } |
| |
| /** |
| * Manually registering all extensions from the generated (diagramming) plugin into eclipse registries |
| */ |
| private void registerExtensions(Bundle bundle) { |
| IConfigurationElement[] configElements = getConfigurationElements(bundle.getSymbolicName(), "org.eclipse.emf.ecore.extension_parser"); |
| for (int i = 0; i < configElements.length; i++) { |
| try { |
| Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put(configElements[i].getAttribute("type"), configElements[i].createExecutableExtension("class")); |
| } catch (InvalidRegistryObjectException e) { |
| Assert.fail(e.getMessage()); |
| } catch (CoreException e) { |
| Assert.fail(e.getMessage()); |
| } |
| } |
| } |
| |
| private void registerEMFEditExtensions() { |
| for(Bundle next : myAllInstalledBundes) { |
| IConfigurationElement[] configElements = getConfigurationElements(next.getSymbolicName(), "org.eclipse.emf.edit.itemProviderAdapterFactories"); |
| for(int i = 0; i < configElements.length; i++) { |
| IConfigurationElement element = configElements[i]; |
| if (element.getName().equals("factory")) { |
| String packageURI = element.getAttribute("uri"); |
| String className = element.getAttribute("class"); |
| String supportedTypes = element.getAttribute("supportedTypes"); |
| if (packageURI == null) { |
| continue; |
| } |
| else if (className == null) { |
| continue; |
| } |
| else if (supportedTypes == null) { |
| continue; |
| } |
| class PluginAdapterFactoryDescriptor extends PluginClassDescriptor implements ComposedAdapterFactory.Descriptor { |
| public PluginAdapterFactoryDescriptor(IConfigurationElement element, String attributeName) { |
| super(element, attributeName); |
| } |
| |
| public AdapterFactory createAdapterFactory() { |
| return (AdapterFactory)createInstance(); |
| } |
| } |
| |
| for (StringTokenizer stringTokenizer = new StringTokenizer(supportedTypes); stringTokenizer.hasMoreTokens(); ) { |
| String supportedType = stringTokenizer.nextToken(); |
| ArrayList<String> key = new ArrayList<String>(2); |
| key.add(packageURI); |
| key.add(supportedType); |
| ((ComposedAdapterFactory.Descriptor.Registry.Impl) ComposedAdapterFactory.Descriptor.Registry.INSTANCE).put(key, new PluginAdapterFactoryDescriptor(element, "class")); |
| } |
| |
| } |
| } |
| } |
| } |
| |
| private IConfigurationElement[] getConfigurationElements(String bundlID, String extensionPointID) { |
| IConfigurationElement[] configs = Platform.getExtensionRegistry().getConfigurationElementsFor(extensionPointID); |
| Collection<IConfigurationElement> ownConfigs = new LinkedList<IConfigurationElement>(); |
| for (int i = 0; i < configs.length; i++) { |
| if (bundlID.equals(configs[i].getContributor().getName())) { |
| ownConfigs.add(configs[i]); |
| } |
| } |
| return ownConfigs.toArray(new IConfigurationElement[ownConfigs.size()]); |
| } |
| |
| public final Bundle getBundle() { |
| assert myBundle != null : "GenProjectSetup was not initialized"; |
| return myBundle; |
| } |
| |
| public void uninstall() throws Exception { |
| final JobTracker jt = new JobTracker(); |
| jt.start(); |
| for (Bundle next : myAllInstalledBundes) { |
| next.uninstall(); |
| } |
| jt.freeze(); |
| // need timeout for ExtensionRegistry to dispatch changes about removed extensions, e.g. |
| // EditorManager#removeExtensions removes IEditorParts from EditorHistory, to prevent issues |
| // like https://bugs.eclipse.org/bugs/show_bug.cgi?id=154767 |
| // ExtensionRegistry (namely EqunoxRegistryStrategy) does that either using jobs (ExtensionEventDispatcherJob) or |
| // in RegistryEventThread, hence all we need to do is give it a chance to complete |
| Utils.assertDispatchDisplayMessages(jt.getNonEmptyCondition(), 10); |
| jt.stop(); |
| // |
| // Then UIExtensionTracker re-dispatches this notification to EditorManager in UI thread, hence need to let them |
| // reach EditorManager#removeExtensions method |
| Utils.assertDispatchDisplayMessages(3); |
| } |
| } |