001: /*******************************************************************************
002: * Copyright (c) 2004, 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.ui.internal;
011:
012: import java.lang.reflect.InvocationTargetException;
013: import java.lang.reflect.Method;
014:
015: import org.eclipse.core.runtime.CoreException;
016: import org.eclipse.core.runtime.IConfigurationElement;
017: import org.eclipse.core.runtime.IExtension;
018: import org.eclipse.core.runtime.IStatus;
019: import org.eclipse.core.runtime.Platform;
020: import org.eclipse.core.runtime.Status;
021: import org.eclipse.jface.util.SafeRunnable;
022: import org.eclipse.ui.IStartup;
023: import org.osgi.framework.Bundle;
024:
025: /**
026: * A utility class used to call #earlyStartup on the proper instance for a given
027: * configuration element. There are a few steps to the process in order to
028: * ensure compatibility with pre-3.0 plugins.
029: *
030: * @since 3.0
031: */
032: public class EarlyStartupRunnable extends SafeRunnable {
033:
034: private static final String EXTENSION_CLASS = "org.eclipse.core.runtime.IExtension"; //$NON-NLS-1$
035:
036: // private static final String PLUGIN_DESC_CLASS = "org.eclipse.core.runtime.IPluginDescriptor"; //$NON-NLS-1$
037:
038: private static final String GET_PLUGIN_METHOD = "getPlugin"; //$NON-NLS-1$
039:
040: private static final String GET_DESC_METHOD = "getDeclaringPluginDescriptor"; //$NON-NLS-1$
041:
042: private static final String PI_RUNTIME_COMPATIBILITY = "org.eclipse.core.runtime.compatibility"; //$NON-NLS-1$
043:
044: private IExtension extension;
045:
046: /**
047: * @param extension
048: * must not be null
049: */
050: public EarlyStartupRunnable(IExtension extension) {
051: this .extension = extension;
052: }
053:
054: public void run() throws Exception {
055: IConfigurationElement[] configElements = extension
056: .getConfigurationElements();
057:
058: // look for the startup tag in each element and run the extension
059: boolean foundAtLeastOne = false;
060: for (int i = 0; i < configElements.length; ++i) {
061: IConfigurationElement element = configElements[i];
062: if (element != null
063: && element.getName().equals(
064: IWorkbenchConstants.TAG_STARTUP)) {
065: runEarlyStartup(getExecutableExtension(element));
066: foundAtLeastOne = true;
067: }
068: }
069:
070: // if no startup tags were found, then try the plugin object
071: if (!foundAtLeastOne) {
072: runEarlyStartup(getPluginForCompatibility());
073: }
074: }
075:
076: public void handleException(Throwable exception) {
077: IStatus status = new Status(
078: IStatus.ERROR,
079: extension.getNamespace(),
080: 0,
081: "Unable to execute early startup code for an extension", //$NON-NLS-1$
082: exception);
083: WorkbenchPlugin.log("Unhandled Exception", status); //$NON-NLS-1$
084: }
085:
086: private void runEarlyStartup(Object executableExtension) {
087: if (executableExtension != null
088: && executableExtension instanceof IStartup) {
089: ((IStartup) executableExtension).earlyStartup();
090: } else {
091: IStatus status = new Status(
092: IStatus.ERROR,
093: extension.getNamespace(),
094: 0,
095: "startup class must implement org.eclipse.ui.IStartup", //$NON-NLS-1$
096: null);
097: WorkbenchPlugin.log("Bad extension specification", status); //$NON-NLS-1$
098: }
099: }
100:
101: /**
102: * In 3.0 the class attribute is a mandatory element of the startup element.
103: * However, 2.1 plugins should still be able to run if the compatibility
104: * bundle is loaded.
105: *
106: * @return an executable extension for this startup element or null if an
107: * extension (or plugin) could not be found
108: */
109: private Object getExecutableExtension(IConfigurationElement element)
110: throws CoreException {
111:
112: String classname = element
113: .getAttribute(IWorkbenchConstants.TAG_CLASS);
114:
115: // if class attribute is absent then try to use the compatibility
116: // bundle to return the plugin object
117: if (classname == null || classname.length() <= 0) {
118: return getPluginForCompatibility();
119: }
120:
121: // otherwise the 3.0 runtime should be able to do it
122: return WorkbenchPlugin.createExtension(element,
123: IWorkbenchConstants.TAG_CLASS);
124: }
125:
126: /**
127: * If the compatiblity bundle is loaded, then return the plugin object for
128: * the extension on this runnable. Return null if the compatibility bundle
129: * is not loaded or the plugin object cannot be created.
130: */
131: private Object getPluginForCompatibility() {
132: // make sure the compatibility bundle is available
133: Bundle compatBundle = Platform
134: .getBundle(PI_RUNTIME_COMPATIBILITY);
135: if (compatBundle == null) {
136: return null;
137: }
138:
139: // use reflection to try to access the plugin object
140: try {
141: // IPluginDescriptor pluginDesc =
142: // extension.getDeclaringPluginDescriptor();
143: Class extensionClass = compatBundle
144: .loadClass(EXTENSION_CLASS);
145: Method getDescMethod = extensionClass.getDeclaredMethod(
146: GET_DESC_METHOD, new Class[0]);
147: Object pluginDesc = getDescMethod.invoke(extension,
148: new Object[0]);
149: if (pluginDesc == null) {
150: return null;
151: }
152:
153: // Plugin plugin = pluginDesc.getPlugin();
154: Class pluginDescClass = pluginDesc.getClass();
155: Method getPluginMethod = pluginDescClass.getDeclaredMethod(
156: GET_PLUGIN_METHOD, new Class[0]);
157: return getPluginMethod.invoke(pluginDesc, new Object[0]);
158: } catch (ClassNotFoundException e) {
159: handleException(e);
160: } catch (IllegalAccessException e) {
161: handleException(e);
162: } catch (InvocationTargetException e) {
163: handleException(e);
164: } catch (NoSuchMethodException e) {
165: handleException(e);
166: }
167:
168: return null;
169: }
170: }
|