blob: 83fee5434ca82311d6ac8fb02eb8b8ff4dd0dbb4 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2008 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 com.ibm.icu.text.MessageFormat;
import java.io.OutputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.HashSet;
import java.util.Locale;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.context.spi.ContextFunction;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.preference.PreferenceManager;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.jface.window.Window;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IDecoratorManager;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IElementFactory;
import org.eclipse.ui.IPerspectiveRegistry;
import org.eclipse.ui.ISharedImages;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.StartupThreading.StartupRunnable;
import org.eclipse.ui.internal.decorators.DecoratorManager;
import org.eclipse.ui.internal.dialogs.WorkbenchPreferenceManager;
import org.eclipse.ui.internal.intro.IIntroRegistry;
import org.eclipse.ui.internal.intro.IntroRegistry;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.operations.WorkbenchOperationSupport;
import org.eclipse.ui.internal.progress.ProgressManager;
import org.eclipse.ui.internal.registry.ActionSetRegistry;
import org.eclipse.ui.internal.registry.EditorRegistry;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.registry.PerspectiveRegistry;
import org.eclipse.ui.internal.registry.PreferencePageRegistryReader;
import org.eclipse.ui.internal.registry.ViewRegistry;
import org.eclipse.ui.internal.registry.WorkingSetRegistry;
import org.eclipse.ui.internal.themes.IThemeRegistry;
import org.eclipse.ui.internal.themes.ThemeRegistry;
import org.eclipse.ui.internal.themes.ThemeRegistryReader;
import org.eclipse.ui.internal.util.BundleUtility;
import org.eclipse.ui.internal.wizards.ExportWizardRegistry;
import org.eclipse.ui.internal.wizards.ImportWizardRegistry;
import org.eclipse.ui.internal.wizards.NewWizardRegistry;
import org.eclipse.ui.operations.IWorkbenchOperationSupport;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.presentations.AbstractPresentationFactory;
import org.eclipse.ui.views.IViewRegistry;
import org.eclipse.ui.wizards.IWizardRegistry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleException;
import org.osgi.framework.BundleListener;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.SynchronousBundleListener;
/**
* This class represents the TOP of the workbench UI world A plugin class is
* effectively an org.eclipse.e4.ui.model.application wrapper for a plugin & its classes. This class
* should be thought of as the workbench UI's org.eclipse.e4.ui.model.application class.
*
* This class is responsible for tracking various registries font, preference,
* graphics, dialog store.
*
* This class is explicitly referenced by the workbench plugin's "plugin.xml"
* and places it into the UI start extension point of the main overall
* org.eclipse.e4.ui.model.application harness
*
* When is this class started? When the Application calls
* createExecutableExtension to create an executable instance of our workbench
* class.
*/
public class WorkbenchPlugin extends AbstractUIPlugin {
/**
* Splash shell constant.
*/
private static final String DATA_SPLASH_SHELL = "org.eclipse.ui.workbench.splashShell"; //$NON-NLS-1$
/**
* The OSGi splash property.
*
* @since 3.4
*/
private static final String PROP_SPLASH_HANDLE = "org.eclipse.equinox.launcher.splash.handle"; //$NON-NLS-1$
private static final String LEFT_TO_RIGHT = "ltr"; //$NON-NLS-1$
private static final String RIGHT_TO_LEFT = "rtl";//$NON-NLS-1$
private static final String ORIENTATION_COMMAND_LINE = "-dir";//$NON-NLS-1$
private static final String ORIENTATION_PROPERTY = "eclipse.orientation";//$NON-NLS-1$
private static final String NL_USER_PROPERTY = "osgi.nl.user"; //$NON-NLS-1$
// Default instance of the receiver
private static WorkbenchPlugin inst;
// Manager that maps resources to descriptors of editors to use
private EditorRegistry editorRegistry;
// Manager for the DecoratorManager
private DecoratorManager decoratorManager;
// Theme registry
private ThemeRegistry themeRegistry;
// Manager for working sets (IWorkingSet)
private WorkingSetManager workingSetManager;
// Working set registry, stores working set dialogs
private WorkingSetRegistry workingSetRegistry;
// The context within which this plugin was started.
private BundleContext bundleContext;
// The set of currently starting bundles
private Collection startingBundles = new HashSet();
/**
* Global workbench ui plugin flag. Only workbench implementation is allowed
* to use this flag All other plugins, examples, or test cases must *not*
* use this flag.
*/
public static boolean DEBUG = false;
/**
* The workbench plugin ID.
*
* @issue we should just drop this constant and use PlatformUI.PLUGIN_ID
* instead
*/
public static String PI_WORKBENCH = PlatformUI.PLUGIN_ID;
/**
* The character used to separate preference page category ids
*/
public static char PREFERENCE_PAGE_CATEGORY_SEPARATOR = '/';
// Other data.
private WorkbenchPreferenceManager preferenceManager;
private ViewRegistry viewRegistry;
private PerspectiveRegistry perspRegistry;
private ActionSetRegistry actionSetRegistry;
private SharedImages sharedImages;
/**
* Information describing the product (formerly called "primary plugin");
* lazily initialized.
*
* @since 3.0
*/
private ProductInfo productInfo = null;
private IntroRegistry introRegistry;
private WorkbenchOperationSupport operationSupport;
private BundleListener bundleListener;
private IEclipseContext e4Context;
/**
* Create an instance of the WorkbenchPlugin. The workbench plugin is
* effectively the "org.eclipse.e4.ui.model.application" for the workbench UI. The entire UI
* operates as a good plugin citizen.
*/
public WorkbenchPlugin() {
super();
inst = this;
}
/**
* Unload all members. This can be used to run a second instance of a
* workbench.
*
* @since 3.0
*/
void reset() {
editorRegistry = null;
if (decoratorManager != null) {
decoratorManager.dispose();
decoratorManager = null;
}
ProgressManager.shutdownProgressManager();
themeRegistry = null;
if (workingSetManager != null) {
workingSetManager.dispose();
workingSetManager = null;
}
workingSetRegistry = null;
preferenceManager = null;
if (viewRegistry != null) {
viewRegistry.dispose();
viewRegistry = null;
}
if (perspRegistry != null) {
perspRegistry.dispose();
perspRegistry = null;
}
actionSetRegistry = null;
sharedImages = null;
productInfo = null;
introRegistry = null;
if (operationSupport != null) {
operationSupport.dispose();
operationSupport = null;
}
DEBUG = false;
}
/**
* Creates an extension. If the extension plugin has not been loaded a busy
* cursor will be activated during the duration of the load.
*
* @param element
* the config element defining the extension
* @param classAttribute
* the name of the attribute carrying the class
* @return the extension object
* @throws CoreException
* if the extension cannot be created
*/
public static Object createExtension(final IConfigurationElement element,
final String classAttribute) throws CoreException {
try {
// If plugin has been loaded create extension.
// Otherwise, show busy cursor then create extension.
if (BundleUtility.isActivated(element.getDeclaringExtension()
.getNamespace())) {
return element.createExecutableExtension(classAttribute);
}
final Object[] ret = new Object[1];
final CoreException[] exc = new CoreException[1];
BusyIndicator.showWhile(null, new Runnable() {
public void run() {
try {
ret[0] = element
.createExecutableExtension(classAttribute);
} catch (CoreException e) {
exc[0] = e;
}
}
});
if (exc[0] != null) {
throw exc[0];
}
return ret[0];
} catch (CoreException core) {
throw core;
} catch (Exception e) {
throw new CoreException(new Status(IStatus.ERROR, PI_WORKBENCH,
IStatus.ERROR, WorkbenchMessages.WorkbenchPlugin_extension,
e));
}
}
/**
* Answers whether the provided element either has an attribute with the
* given name or a child element with the given name with an attribute
* called class.
*
* @param element
* the element to test
* @param extensionName
* the name of the extension to test for
* @return whether or not the extension is declared
* @since 3.3
*/
public static boolean hasExecutableExtension(IConfigurationElement element,
String extensionName) {
if (element.getAttribute(extensionName) != null)
return true;
String elementText = element.getValue();
if (elementText != null && !elementText.equals("")) //$NON-NLS-1$
return true;
IConfigurationElement[] children = element.getChildren(extensionName);
if (children.length == 1) {
if (children[0].getAttribute(IWorkbenchRegistryConstants.ATT_CLASS) != null)
return true;
}
return false;
}
/**
* Checks to see if the provided element has the syntax for an executable
* extension with a given name that resides in a bundle that is already
* active. Determining the bundle happens in one of two ways:<br/>
* <ul>
* <li>The element has an attribute with the specified name or element text
* in the form <code>bundle.id/class.name[:optional attributes]</code></li>
* <li>The element has a child element with the specified name that has a
* <code>plugin</code> attribute</li>
* </ul>
*
* @param element
* the element to test
* @param extensionName
* the name of the extension to test for
* @return whether or not the bundle expressed by the above criteria is
* active. If the bundle cannot be determined then the state of the
* bundle that declared the element is returned.
* @since 3.3
*/
public static boolean isBundleLoadedForExecutableExtension(
IConfigurationElement element, String extensionName) {
Bundle bundle = getBundleForExecutableExtension(element, extensionName);
if (bundle == null)
return true;
return bundle.getState() == Bundle.ACTIVE;
}
/**
* Returns the bundle that contains the class referenced by an executable
* extension. Determining the bundle happens in one of two ways:<br/>
* <ul>
* <li>The element has an attribute with the specified name or element text
* in the form <code>bundle.id/class.name[:optional attributes]</code></li>
* <li>The element has a child element with the specified name that has a
* <code>plugin</code> attribute</li>
* </ul>
*
* @param element
* the element to test
* @param extensionName
* the name of the extension to test for
* @return the bundle referenced by the extension. If that bundle cannot be
* determined the bundle that declared the element is returned. Note
* that this may be <code>null</code>.
* @since 3.3
*/
public static Bundle getBundleForExecutableExtension(
IConfigurationElement element, String extensionName) {
// this code is derived heavily from
// ConfigurationElement.createExecutableExtension.
String prop = null;
String executable;
String contributorName = null;
int i;
if (extensionName != null)
prop = element.getAttribute(extensionName);
else {
// property not specified, try as element value
prop = element.getValue();
if (prop != null) {
prop = prop.trim();
if (prop.equals("")) //$NON-NLS-1$
prop = null;
}
}
if (prop == null) {
// property not defined, try as a child element
IConfigurationElement[] exec = element.getChildren(extensionName);
if (exec.length != 0)
contributorName = exec[0].getAttribute("plugin"); //$NON-NLS-1$
} else {
// simple property or element value, parse it into its components
i = prop.indexOf(':');
if (i != -1)
executable = prop.substring(0, i).trim();
else
executable = prop;
i = executable.indexOf('/');
if (i != -1)
contributorName = executable.substring(0, i).trim();
}
if (contributorName == null)
contributorName = element.getContributor().getName();
return Platform.getBundle(contributorName);
}
/**
* Returns the image registry for this plugin.
*
* Where are the images? The images (typically gifs) are found in the same
* plugins directory.
*
* @see ImageRegistry
*
* Note: The workbench uses the standard JFace ImageRegistry to track
* its images. In addition the class WorkbenchGraphicResources provides
* convenience access to the graphics resources and fast field access
* for some of the commonly used graphical images.
*/
protected ImageRegistry createImageRegistry() {
return WorkbenchImages.getImageRegistry();
}
/**
* Returns the action set registry for the workbench.
*
* @return the workbench action set registry
*/
public ActionSetRegistry getActionSetRegistry() {
return (ActionSetRegistry) e4Context.get(ActionSetRegistry.class
.getName());
}
/**
* Return the default instance of the receiver. This represents the runtime
* plugin.
*
* @return WorkbenchPlugin
* @see AbstractUIPlugin for the typical implementation pattern for plugin
* classes.
*/
public static WorkbenchPlugin getDefault() {
return inst;
}
/**
* Answer the manager that maps resource types to a the description of the
* editor to use
*
* @return IEditorRegistry the editor registry used by this plug-in.
*/
public IEditorRegistry getEditorRegistry() {
return (IEditorRegistry) e4Context.get(IEditorRegistry.class.getName());
}
/**
* Answer the element factory for an id, or <code>null</code. if not found.
*
* @param targetID
* @return IElementFactory
*/
public IElementFactory getElementFactory(String targetID) {
// Get the extension point registry.
IExtensionPoint extensionPoint;
extensionPoint = Platform.getExtensionRegistry().getExtensionPoint(
PI_WORKBENCH, IWorkbenchRegistryConstants.PL_ELEMENT_FACTORY);
if (extensionPoint == null) {
WorkbenchPlugin
.log("Unable to find element factory. Extension point: " + IWorkbenchRegistryConstants.PL_ELEMENT_FACTORY + " not found"); //$NON-NLS-2$ //$NON-NLS-1$
return null;
}
// Loop through the config elements.
IConfigurationElement targetElement = null;
IConfigurationElement[] configElements = extensionPoint
.getConfigurationElements();
for (int j = 0; j < configElements.length; j++) {
String strID = configElements[j].getAttribute("id"); //$NON-NLS-1$
if (targetID.equals(strID)) {
targetElement = configElements[j];
break;
}
}
if (targetElement == null) {
// log it since we cannot safely display a dialog.
WorkbenchPlugin.log("Unable to find element factory: " + targetID); //$NON-NLS-1$
return null;
}
// Create the extension.
IElementFactory factory = null;
try {
factory = (IElementFactory) createExtension(targetElement, "class"); //$NON-NLS-1$
} catch (CoreException e) {
// log it since we cannot safely display a dialog.
WorkbenchPlugin.log(
"Unable to create element factory.", e.getStatus()); //$NON-NLS-1$
factory = null;
}
return factory;
}
/**
* Returns the presentation factory with the given id, or <code>null</code>
* if not found.
*
* @param targetID
* The id of the presentation factory to use.
* @return AbstractPresentationFactory or <code>null</code> if not factory
* matches that id.
*/
public AbstractPresentationFactory getPresentationFactory(String targetID) {
Object o = createExtension(
IWorkbenchRegistryConstants.PL_PRESENTATION_FACTORIES,
"factory", targetID); //$NON-NLS-1$
if (o instanceof AbstractPresentationFactory) {
return (AbstractPresentationFactory) o;
}
WorkbenchPlugin
.log("Error creating presentation factory: " + targetID + " -- class is not an AbstractPresentationFactory"); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
/**
* Looks up the configuration element with the given id on the given
* extension point and instantiates the class specified by the class
* attributes.
*
* @param extensionPointId
* the extension point id (simple id)
* @param elementName
* the name of the configuration element, or <code>null</code> to
* match any element
* @param targetID
* the target id
* @return the instantiated extension object, or <code>null</code> if not
* found
*/
private Object createExtension(String extensionPointId, String elementName,
String targetID) {
IExtensionPoint extensionPoint = Platform.getExtensionRegistry()
.getExtensionPoint(PI_WORKBENCH, extensionPointId);
if (extensionPoint == null) {
WorkbenchPlugin
.log("Unable to find extension. Extension point: " + extensionPointId + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
return null;
}
// Loop through the config elements.
IConfigurationElement targetElement = null;
IConfigurationElement[] elements = extensionPoint
.getConfigurationElements();
for (int j = 0; j < elements.length; j++) {
IConfigurationElement element = elements[j];
if (elementName == null || elementName.equals(element.getName())) {
String strID = element.getAttribute("id"); //$NON-NLS-1$
if (targetID.equals(strID)) {
targetElement = element;
break;
}
}
}
if (targetElement == null) {
// log it since we cannot safely display a dialog.
WorkbenchPlugin.log("Unable to find extension: " + targetID //$NON-NLS-1$
+ " in extension point: " + extensionPointId); //$NON-NLS-1$
return null;
}
// Create the extension.
try {
return createExtension(targetElement, "class"); //$NON-NLS-1$
} catch (CoreException e) {
// log it since we cannot safely display a dialog.
WorkbenchPlugin.log("Unable to create extension: " + targetID //$NON-NLS-1$
+ " in extension point: " + extensionPointId //$NON-NLS-1$
+ ", status: ", e.getStatus()); //$NON-NLS-1$
}
return null;
}
/**
* Return the perspective registry.
*
* @return IPerspectiveRegistry. The registry for the receiver.
*/
public IPerspectiveRegistry getPerspectiveRegistry() {
if (perspRegistry == null) {
perspRegistry = new PerspectiveRegistry();
// the load methods can touch on WorkbenchImages if
// an image is
// missing so we need to wrap the call in
// a startup block for the case where a custom
// descriptor exists on
// startup that does not have an image
// associated with it. See bug 196352.
StartupThreading.runWithoutExceptions(new StartupRunnable() {
public void runWithException() throws Throwable {
perspRegistry.load();
}
});
}
return perspRegistry;
}
/**
* Returns the working set manager
*
* @return the working set manager
* @since 2.0
*/
public IWorkingSetManager getWorkingSetManager() {
return (IWorkingSetManager) e4Context.get(IWorkingSetManager.class
.getName());
}
/**
* Returns the working set registry
*
* @return the working set registry
* @since 2.0
*/
public WorkingSetRegistry getWorkingSetRegistry() {
return (WorkingSetRegistry) e4Context.get(WorkingSetRegistry.class
.getName());
}
/**
* Returns the introduction registry.
*
* @return the introduction registry.
* @since 3.0
*/
public IIntroRegistry getIntroRegistry() {
return (IIntroRegistry) e4Context.get(IIntroRegistry.class.getName());
}
/**
* Returns the operation support.
*
* @return the workbench operation support.
* @since 3.1
*/
public IWorkbenchOperationSupport getOperationSupport() {
return (IWorkbenchOperationSupport) e4Context
.get(IWorkbenchOperationSupport.class.getName());
}
/**
* Get the preference manager.
*
* @return PreferenceManager the preference manager for the receiver.
*/
public PreferenceManager getPreferenceManager() {
return (PreferenceManager) e4Context.get(PreferenceManager.class
.getName());
}
/**
* Returns the shared images for the workbench.
*
* @return the shared image manager
*/
public ISharedImages getSharedImages() {
return (ISharedImages) e4Context.get(ISharedImages.class.getName());
}
/**
* Returns the theme registry for the workbench.
*
* @return the theme registry
*/
public IThemeRegistry getThemeRegistry() {
return (IThemeRegistry) e4Context.get(IThemeRegistry.class.getName());
}
/**
* Answer the view registry.
*
* @return IViewRegistry the view registry for the receiver.
*/
public IViewRegistry getViewRegistry() {
return (IViewRegistry) e4Context.get(IViewRegistry.class.getName());
}
/**
* Answer the workbench.
*
* @deprecated Use <code>PlatformUI.getWorkbench()</code> instead.
*/
public IWorkbench getWorkbench() {
return PlatformUI.getWorkbench();
}
/**
* Set default preference values. This method must be called whenever the
* preference store is initially loaded because the default values are not
* stored in the preference store.
*/
protected void initializeDefaultPreferences(IPreferenceStore store) {
// Do nothing. This should not be called.
// Prefs are initialized in WorkbenchPreferenceInitializer.
}
/**
* Logs the given message to the platform log.
*
* If you have an exception in hand, call log(String, Throwable) instead.
*
* If you have a status object in hand call log(String, IStatus) instead.
*
* This convenience method is for internal use by the Workbench only and
* must not be called outside the Workbench.
*
* @param message
* A high level UI message describing when the problem happened.
*/
public static void log(String message) {
getDefault().getLog().log(
StatusUtil.newStatus(IStatus.ERROR, message, null));
}
/**
* Log the throwable.
*
* @param t
*/
public static void log(Throwable t) {
getDefault().getLog().log(getStatus(t));
}
/**
* Return the status from throwable
*
* @param t
* throwable
* @return IStatus
*/
public static IStatus getStatus(Throwable t) {
String message = StatusUtil.getLocalizedMessage(t);
return newError(message, t);
}
/**
* Create a new error from the message and the throwable.
*
* @param message
* @param t
* @return IStatus
*/
public static IStatus newError(String message, Throwable t) {
String pluginId = "org.eclipse.ui.workbench"; //$NON-NLS-1$
int errorCode = IStatus.OK;
// If this was a CoreException, keep the original plugin ID and error
// code
if (t instanceof CoreException) {
CoreException ce = (CoreException) t;
pluginId = ce.getStatus().getPlugin();
errorCode = ce.getStatus().getCode();
}
return new Status(IStatus.ERROR, pluginId, errorCode, message,
StatusUtil.getCause(t));
}
/**
* Logs the given message and throwable to the platform log.
*
* If you have a status object in hand call log(String, IStatus) instead.
*
* This convenience method is for internal use by the Workbench only and
* must not be called outside the Workbench.
*
* @param message
* A high level UI message describing when the problem happened.
* @param t
* The throwable from where the problem actually occurred.
*/
public static void log(String message, Throwable t) {
IStatus status = StatusUtil.newStatus(IStatus.ERROR, message, t);
log(message, status);
}
/**
* Logs the given throwable to the platform log, indicating the class and
* method from where it is being logged (this is not necessarily where it
* occurred).
*
* This convenience method is for internal use by the Workbench only and
* must not be called outside the Workbench.
*
* @param clazz
* The calling class.
* @param methodName
* The calling method name.
* @param t
* The throwable from where the problem actually occurred.
*/
public static void log(Class clazz, String methodName, Throwable t) {
String msg = MessageFormat.format("Exception in {0}.{1}: {2}", //$NON-NLS-1$
new Object[] { clazz.getName(), methodName, t });
log(msg, t);
}
/**
* Logs the given message and status to the platform log.
*
* This convenience method is for internal use by the Workbench only and
* must not be called outside the Workbench.
*
* @param message
* A high level UI message describing when the problem happened.
* May be <code>null</code>.
* @param status
* The status describing the problem. Must not be null.
*/
public static void log(String message, IStatus status) {
// 1FTUHE0: ITPCORE:ALL - API - Status & logging - loss of semantic info
if (message != null) {
getDefault().getLog().log(
StatusUtil.newStatus(IStatus.ERROR, message, null));
}
getDefault().getLog().log(status);
}
/**
* Log the status to the default log.
*
* @param status
*/
public static void log(IStatus status) {
getDefault().getLog().log(status);
}
/**
* Get the decorator manager for the receiver
*
* @return DecoratorManager the decorator manager for the receiver.
*/
public DecoratorManager getDecoratorManager() {
return (DecoratorManager) e4Context.get(IDecoratorManager.class
.getName());
}
/*
* (non-Javadoc)
*
* @see
* org.osgi.framework.BundleActivator#start(org.osgi.framework.BundleContext
* )
*/
public void start(BundleContext context) throws Exception {
context.addBundleListener(getBundleListener());
super.start(context);
bundleContext = context;
JFaceUtil.initializeJFace();
Window.setDefaultOrientation(getDefaultOrientation());
// The UI plugin needs to be initialized so that it can install the
// callback in PrefUtil,
// which needs to be done as early as possible, before the workbench
// accesses any API preferences.
Bundle uiBundle = Platform.getBundle(PlatformUI.PLUGIN_ID);
try {
// Attempt to load the activator of the ui bundle. This will force
// lazy start
// of the ui bundle. Using the bundle activator class here because
// it is a
// class that needs to be loaded anyway so it should not cause extra
// classes
// to be loaded.s
if (uiBundle != null)
uiBundle.start(Bundle.START_TRANSIENT);
} catch (BundleException e) {
WorkbenchPlugin.log("Unable to load UI activator", e); //$NON-NLS-1$
}
/*
* DO NOT RUN ANY OTHER CODE AFTER THIS LINE. If you do, then you are
* likely to cause a deadlock in class loader code. Please see Bug 86450
* for more information.
*/
}
/**
* Get the default orientation from the command line arguments. If there are
* no arguments imply the orientation.
*
* @return int
* @see SWT#NONE
* @see SWT#RIGHT_TO_LEFT
* @see SWT#LEFT_TO_RIGHT
*/
private int getDefaultOrientation() {
String[] commandLineArgs = Platform.getCommandLineArgs();
int orientation = getCommandLineOrientation(commandLineArgs);
if (orientation != SWT.NONE) {
return orientation;
}
orientation = getSystemPropertyOrientation();
if (orientation != SWT.NONE) {
return orientation;
}
return checkCommandLineLocale(); // Use the default value if there is
// nothing specified
}
/**
* Check to see if the command line parameter for -nl has been set. If so
* imply the orientation from this specified Locale. If it is a
* bidirectional Locale return SWT#RIGHT_TO_LEFT. If it has not been set or
* has been set to a unidirectional Locale then return SWT#NONE.
*
* Locale is determined differently by different JDKs and may not be
* consistent with the users expectations.
*
*
* @return int
* @see SWT#NONE
* @see SWT#RIGHT_TO_LEFT
*/
private int checkCommandLineLocale() {
// Check if the user property is set. If not do not
// rely on the vm.
if (System.getProperty(NL_USER_PROPERTY) == null) {
return SWT.NONE;
}
Locale locale = Locale.getDefault();
String lang = locale.getLanguage();
if ("iw".equals(lang) || "he".equals(lang) || "ar".equals(lang) || //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
"fa".equals(lang) || "ur".equals(lang)) { //$NON-NLS-1$ //$NON-NLS-2$
return SWT.RIGHT_TO_LEFT;
}
return SWT.NONE;
}
/**
* Check to see if the orientation was set in the system properties. If
* there is no orientation specified return SWT#NONE.
*
* @return int
* @see SWT#NONE
* @see SWT#RIGHT_TO_LEFT
* @see SWT#LEFT_TO_RIGHT
*/
private int getSystemPropertyOrientation() {
String orientation = System.getProperty(ORIENTATION_PROPERTY);
if (RIGHT_TO_LEFT.equals(orientation)) {
return SWT.RIGHT_TO_LEFT;
}
if (LEFT_TO_RIGHT.equals(orientation)) {
return SWT.LEFT_TO_RIGHT;
}
return SWT.NONE;
}
/**
* Find the orientation in the commandLineArgs. If there is no orientation
* specified return SWT#NONE.
*
* @param commandLineArgs
* @return int
* @see SWT#NONE
* @see SWT#RIGHT_TO_LEFT
* @see SWT#LEFT_TO_RIGHT
*/
private int getCommandLineOrientation(String[] commandLineArgs) {
// Do not process the last one as it will never have a parameter
for (int i = 0; i < commandLineArgs.length - 1; i++) {
if (commandLineArgs[i].equalsIgnoreCase(ORIENTATION_COMMAND_LINE)) {
String orientation = commandLineArgs[i + 1];
if (orientation.equals(RIGHT_TO_LEFT)) {
System.setProperty(ORIENTATION_PROPERTY, RIGHT_TO_LEFT);
return SWT.RIGHT_TO_LEFT;
}
if (orientation.equals(LEFT_TO_RIGHT)) {
System.setProperty(ORIENTATION_PROPERTY, LEFT_TO_RIGHT);
return SWT.LEFT_TO_RIGHT;
}
}
}
return SWT.NONE;
}
/**
* Return an array of all bundles contained in this workbench.
*
* @return an array of bundles in the workbench or an empty array if none
* @since 3.0
*/
public Bundle[] getBundles() {
return bundleContext == null ? new Bundle[0] : bundleContext
.getBundles();
}
/**
* Returns the bundle context associated with the workbench plug-in.
*
* @return the bundle context
* @since 3.1
*/
public BundleContext getBundleContext() {
return bundleContext;
}
/**
* Returns the org.eclipse.e4.ui.model.application name.
* <p>
* Note this is never shown to the user. It is used to initialize the SWT
* Display. On Motif, for example, this can be used to set the name used for
* resource lookup.
* </p>
*
* @return the org.eclipse.e4.ui.model.application name, or <code>null</code>
* @see org.eclipse.swt.widgets.Display#setAppName
* @since 3.0
*/
public String getAppName() {
return getProductInfo().getAppName();
}
/**
* Returns the name of the product.
*
* @return the product name, or <code>null</code> if none
* @since 3.0
*/
public String getProductName() {
return getProductInfo().getProductName();
}
/**
* Returns the image descriptors for the window image to use for this
* product.
*
* @return an array of the image descriptors for the window image, or
* <code>null</code> if none
* @since 3.0
*/
public ImageDescriptor[] getWindowImages() {
return getProductInfo().getWindowImages();
}
/**
* Returns an instance that describes this plugin's product (formerly
* "primary plugin").
*
* @return ProductInfo the product info for the receiver
*/
private ProductInfo getProductInfo() {
if (productInfo == null) {
productInfo = new ProductInfo(Platform.getProduct());
}
return productInfo;
}
/*
* (non-Javadoc)
*
* @see
* org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext
* )
*/
public void stop(BundleContext context) throws Exception {
if (bundleListener != null) {
context.removeBundleListener(bundleListener);
bundleListener = null;
}
// TODO normally super.stop(*) would be the last statement in this
// method
super.stop(context);
}
/**
* Return the new wizard registry.
*
* @return the new wizard registry
* @since 3.1
*/
public IWizardRegistry getNewWizardRegistry() {
return (IWizardRegistry) e4Context.get(NewWizardRegistry.class
.getName());
}
/**
* Return the import wizard registry.
*
* @return the import wizard registry
* @since 3.1
*/
public IWizardRegistry getImportWizardRegistry() {
return (IWizardRegistry) e4Context.get(ImportWizardRegistry.class
.getName());
}
/**
* Return the export wizard registry.
*
* @return the export wizard registry
* @since 3.1
*/
public IWizardRegistry getExportWizardRegistry() {
return (IWizardRegistry) e4Context.get(ExportWizardRegistry.class
.getName());
}
/**
* FOR INTERNAL WORKBENCH USE ONLY.
*
* Returns the path to a location in the file system that can be used to
* persist/restore state between workbench invocations. If the location did
* not exist prior to this call it will be created. Returns
* <code>null</code> if no such location is available.
*
* @return path to a location in the file system where this plug-in can
* persist data between sessions, or <code>null</code> if no such
* location is available.
* @since 3.1
*/
public IPath getDataLocation() {
try {
return getStateLocation();
} catch (IllegalStateException e) {
// This occurs if -data=@none is explicitly specified, so ignore
// this silently.
// Is this OK? See bug 85071.
return null;
}
}
/* package */void addBundleListener(BundleListener bundleListener) {
bundleContext.addBundleListener(bundleListener);
}
/* package */void removeBundleListener(BundleListener bundleListener) {
bundleContext.removeBundleListener(bundleListener);
}
/* package */int getBundleCount() {
return bundleContext.getBundles().length;
}
/* package */OutputStream getSplashStream() {
// assumes the output stream is available as a service
// see EclipseStarter.publishSplashScreen
ServiceReference[] ref;
try {
ref = bundleContext.getServiceReferences(OutputStream.class
.getName(), null);
} catch (InvalidSyntaxException e) {
return null;
}
if (ref == null) {
return null;
}
for (int i = 0; i < ref.length; i++) {
String name = (String) ref[i].getProperty("name"); //$NON-NLS-1$
if (name != null && name.equals("splashstream")) { //$NON-NLS-1$
Object result = bundleContext.getService(ref[i]);
bundleContext.ungetService(ref[i]);
return (OutputStream) result;
}
}
return null;
}
/**
* @return
*/
private BundleListener getBundleListener() {
if (bundleListener == null) {
bundleListener = new SynchronousBundleListener() {
public void bundleChanged(BundleEvent event) {
WorkbenchPlugin.this.bundleChanged(event);
}
};
}
return bundleListener;
}
private void bundleChanged(BundleEvent event) {
// a bundle in the STARTING state generates 2 events, LAZY_ACTIVATION
// when it enters STARTING and STARTING when it exists STARTING :-)
synchronized (startingBundles) {
switch (event.getType()) {
case BundleEvent.STARTING:
startingBundles.add(event.getBundle());
break;
case BundleEvent.STARTED:
case BundleEvent.STOPPED:
startingBundles.remove(event.getBundle());
break;
default:
break;
}
}
}
public boolean isStarting(Bundle bundle) {
synchronized (startingBundles) {
return startingBundles.contains(bundle);
}
}
/**
* Return whether or not the OSGi framework has specified the handle of a
* splash shell.
*
* @return whether or not the OSGi framework has specified the handle of a
* splash shell
* @since 3.4
*/
public static boolean isSplashHandleSpecified() {
return System.getProperty(PROP_SPLASH_HANDLE) != null;
}
/**
* Get the splash shell for this workbench instance, if any. This will find
* the splash created by the launcher (native) code and wrap it in a SWT
* shell. This may have the side effect of setting data on the provided
* {@link Display}.
*
* @param display
* the display to parent the shell on
*
* @return the splash shell or <code>null</code>
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws IllegalArgumentException
* @throws NumberFormatException
* @see Display#setData(String, Object)
* @since 3.4
*/
public static Shell getSplashShell(Display display)
throws NumberFormatException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
Shell splashShell = (Shell) display.getData(DATA_SPLASH_SHELL);
if (splashShell != null)
return splashShell;
String splashHandle = System.getProperty(PROP_SPLASH_HANDLE);
if (splashHandle == null) {
return null;
}
// look for the 32 bit internal_new shell method
try {
Method method = Shell.class.getMethod(
"internal_new", new Class[] { Display.class, int.class }); //$NON-NLS-1$
// we're on a 32 bit platform so invoke it with splash
// handle as an int
splashShell = (Shell) method.invoke(null, new Object[] { display,
new Integer(splashHandle) });
} catch (NoSuchMethodException e) {
// look for the 64 bit internal_new shell method
try {
Method method = Shell.class
.getMethod(
"internal_new", new Class[] { Display.class, long.class }); //$NON-NLS-1$
// we're on a 64 bit platform so invoke it with a long
splashShell = (Shell) method.invoke(null, new Object[] {
display, new Long(splashHandle) });
} catch (NoSuchMethodException e2) {
// cant find either method - don't do anything.
}
}
display.setData(DATA_SPLASH_SHELL, splashShell);
return splashShell;
}
/**
* Removes any splash shell data set on the provided display and disposes
* the shell if necessary.
*
* @param display
* the display to parent the shell on
* @since 3.4
*/
public static void unsetSplashShell(Display display) {
Shell splashShell = (Shell) display.getData(DATA_SPLASH_SHELL);
if (splashShell != null) {
if (!splashShell.isDisposed())
splashShell.dispose();
display.setData(DATA_SPLASH_SHELL, null);
}
}
public void initializeContext(IEclipseContext context) {
e4Context = context;
context.set(ActionSetRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (actionSetRegistry == null) {
actionSetRegistry = new ActionSetRegistry();
}
return actionSetRegistry;
}
});
context.set(IDecoratorManager.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (decoratorManager == null) {
decoratorManager = new DecoratorManager();
}
return decoratorManager;
}
});
context.set(IEditorRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (editorRegistry == null) {
editorRegistry = new EditorRegistry();
}
return editorRegistry;
}
});
context.set(ExportWizardRegistry.class.getName(),
new ContextFunction() {
@Override
public Object compute(IEclipseContext context,
Object[] arguments) {
return ExportWizardRegistry.getInstance();
}
});
context.set(ImportWizardRegistry.class.getName(),
new ContextFunction() {
@Override
public Object compute(IEclipseContext context,
Object[] arguments) {
return ImportWizardRegistry.getInstance();
}
});
context.set(IIntroRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (introRegistry == null) {
introRegistry = new IntroRegistry();
}
return introRegistry;
}
});
context.set(NewWizardRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
return NewWizardRegistry.getInstance();
}
});
context.set(IWorkbenchOperationSupport.class.getName(),
new ContextFunction() {
@Override
public Object compute(IEclipseContext context,
Object[] arguments) {
if (operationSupport == null) {
operationSupport = new WorkbenchOperationSupport();
}
return operationSupport;
}
});
context.set(IPerspectiveRegistry.class.getName(),
new ContextFunction() {
@Override
public Object compute(IEclipseContext context,
Object[] arguments) {
return getPerspectiveRegistry();
}
});
context.set(PreferenceManager.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (preferenceManager == null) {
preferenceManager = new WorkbenchPreferenceManager(
PREFERENCE_PAGE_CATEGORY_SEPARATOR);
// Get the pages from the registry
PreferencePageRegistryReader registryReader = new PreferencePageRegistryReader(
getWorkbench());
registryReader.loadFromRegistry(Platform
.getExtensionRegistry());
preferenceManager.addPages(registryReader
.getTopLevelNodes());
}
return preferenceManager;
}
});
context.set(ISharedImages.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (sharedImages == null) {
sharedImages = new SharedImages();
}
return sharedImages;
}
});
context.set(IThemeRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (themeRegistry == null) {
themeRegistry = new ThemeRegistry();
ThemeRegistryReader reader = new ThemeRegistryReader();
reader.readThemes(Platform.getExtensionRegistry(),
themeRegistry);
}
return themeRegistry;
}
});
context.set(IViewRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (viewRegistry == null) {
viewRegistry = new ViewRegistry();
}
return viewRegistry;
}
});
context.set(IWorkingSetManager.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (workingSetManager == null) {
workingSetManager = new WorkingSetManager(bundleContext);
workingSetManager.restoreState();
}
return workingSetManager;
}
});
context.set(WorkingSetRegistry.class.getName(), new ContextFunction() {
@Override
public Object compute(IEclipseContext context, Object[] arguments) {
if (workingSetRegistry == null) {
workingSetRegistry = new WorkingSetRegistry();
workingSetRegistry.load();
}
return workingSetRegistry;
}
});
}
}