/******************************************************************************* * Copyright (c) 2004, 2006 IBM 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.ui.internal; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IConfigurationElement; import org.eclipse.core.runtime.IExtension; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.Platform; import org.eclipse.core.runtime.Status; import org.eclipse.jface.util.SafeRunnable; import org.eclipse.ui.IStartup; import org.osgi.framework.Bundle; /** * A utility class used to call #earlyStartup on the proper instance for a given * configuration element. There are a few steps to the process in order to * ensure compatibility with pre-3.0 plugins. * * @since 3.0 */ public class EarlyStartupRunnable extends SafeRunnable { private static final String EXTENSION_CLASS = "org.eclipse.core.runtime.IExtension"; //$NON-NLS-1$ // private static final String PLUGIN_DESC_CLASS = "org.eclipse.core.runtime.IPluginDescriptor"; //$NON-NLS-1$ private static final String GET_PLUGIN_METHOD = "getPlugin"; //$NON-NLS-1$ private static final String GET_DESC_METHOD = "getDeclaringPluginDescriptor"; //$NON-NLS-1$ private static final String PI_RUNTIME_COMPATIBILITY = "org.eclipse.core.runtime.compatibility"; //$NON-NLS-1$ private IExtension extension; /** * @param extension * must not be null */ public EarlyStartupRunnable(IExtension extension) { this.extension = extension; } public void run() throws Exception { IConfigurationElement[] configElements = extension .getConfigurationElements(); // look for the startup tag in each element and run the extension boolean foundAtLeastOne = false; for (int i = 0; i < configElements.length; ++i) { IConfigurationElement element = configElements[i]; if (element != null && element.getName() .equals(IWorkbenchConstants.TAG_STARTUP)) { runEarlyStartup(getExecutableExtension(element)); foundAtLeastOne = true; } } // if no startup tags were found, then try the plugin object if (!foundAtLeastOne) { runEarlyStartup(getPluginForCompatibility()); } } public void handleException(Throwable exception) { IStatus status = new Status(IStatus.ERROR, extension.getNamespace(), 0, "Unable to execute early startup code for an extension", //$NON-NLS-1$ exception); WorkbenchPlugin.log("Unhandled Exception", status); //$NON-NLS-1$ } private void runEarlyStartup(Object executableExtension) { if (executableExtension != null && executableExtension instanceof IStartup) { ((IStartup) executableExtension).earlyStartup(); } else { IStatus status = new Status(IStatus.ERROR, extension.getNamespace(), 0, "startup class must implement org.eclipse.ui.IStartup", //$NON-NLS-1$ null); WorkbenchPlugin.log("Bad extension specification", status); //$NON-NLS-1$ } } /** * In 3.0 the class attribute is a mandatory element of the startup element. * However, 2.1 plugins should still be able to run if the compatibility * bundle is loaded. * * @return an executable extension for this startup element or null if an * extension (or plugin) could not be found */ private Object getExecutableExtension(IConfigurationElement element) throws CoreException { String classname = element.getAttribute(IWorkbenchConstants.TAG_CLASS); // if class attribute is absent then try to use the compatibility // bundle to return the plugin object if (classname == null || classname.length() <= 0) { return getPluginForCompatibility(); } // otherwise the 3.0 runtime should be able to do it return WorkbenchPlugin.createExtension(element, IWorkbenchConstants.TAG_CLASS); } /** * If the compatiblity bundle is loaded, then return the plugin object for * the extension on this runnable. Return null if the compatibility bundle * is not loaded or the plugin object cannot be created. */ private Object getPluginForCompatibility() { // make sure the compatibility bundle is available Bundle compatBundle = Platform.getBundle(PI_RUNTIME_COMPATIBILITY); if (compatBundle == null) { return null; } // use reflection to try to access the plugin object try { // IPluginDescriptor pluginDesc = // extension.getDeclaringPluginDescriptor(); Class extensionClass = compatBundle.loadClass(EXTENSION_CLASS); Method getDescMethod = extensionClass.getDeclaredMethod( GET_DESC_METHOD, new Class[0]); Object pluginDesc = getDescMethod.invoke(extension, new Object[0]); if (pluginDesc == null) { return null; } // Plugin plugin = pluginDesc.getPlugin(); Class pluginDescClass = pluginDesc.getClass(); Method getPluginMethod = pluginDescClass.getDeclaredMethod( GET_PLUGIN_METHOD, new Class[0]); return getPluginMethod.invoke(pluginDesc, new Object[0]); } catch (ClassNotFoundException e) { handleException(e); } catch (IllegalAccessException e) { handleException(e); } catch (InvocationTargetException e) { handleException(e); } catch (NoSuchMethodException e) { handleException(e); } return null; } }