blob: e2f0893dbbc069ef4f89e5f811669cd405673f28 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2010 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.commands.ExecutionException;
import org.eclipse.core.commands.operations.ICompositeOperation;
import org.eclipse.core.commands.operations.IOperationApprover;
import org.eclipse.core.commands.operations.IOperationHistory;
import org.eclipse.core.commands.operations.IOperationHistoryListener;
import org.eclipse.core.commands.operations.IUndoContext;
import org.eclipse.core.commands.operations.IUndoableOperation;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionPoint;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
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.ContextInjectionFactory;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MElementContainer;
import org.eclipse.e4.ui.model.application.MPart;
import org.eclipse.e4.ui.model.application.MWindow;
import org.eclipse.e4.ui.services.events.IEventBroker;
import org.eclipse.e4.workbench.ui.UIEvents;
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.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.IWorkbenchPage;
import org.eclipse.ui.IWorkingSetManager;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.internal.decorators.DecoratorManager;
import org.eclipse.ui.internal.e4.compatibility.CompatibilityPart;
import org.eclipse.ui.internal.e4.compatibility.E4Util;
import org.eclipse.ui.internal.e4.compatibility.ViewDescriptor;
import org.eclipse.ui.internal.e4.compatibility.ViewReference;
import org.eclipse.ui.internal.e4.compatibility.Workbench;
import org.eclipse.ui.internal.e4.compatibility.WorkbenchPage;
import org.eclipse.ui.internal.e4.compatibility.WorkbenchWindow;
import org.eclipse.ui.internal.misc.StatusUtil;
import org.eclipse.ui.internal.registry.EditorRegistry;
import org.eclipse.ui.internal.registry.IWorkbenchRegistryConstants;
import org.eclipse.ui.internal.registry.WorkingSetRegistry;
import org.eclipse.ui.internal.util.BundleUtility;
import org.eclipse.ui.operations.IWorkbenchOperationSupport;
import org.eclipse.ui.plugin.AbstractUIPlugin;
import org.eclipse.ui.views.IViewDescriptor;
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;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventHandler;
/**
* This class represents the TOP of the workbench UI world
* A plugin class is effectively an application wrapper
* for a plugin & its classes. This class should be thought
* of as the workbench UI's 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 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.
*
* @sicne 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;
// TODO commented out for e4 compatibility
// // Manager that maps resources to descriptors of editors to use
// private EditorRegistry editorRegistry;
//
// Manager for the DecoratorManager
private DecoratorManager decoratorManager;
// TODO commented out for e4 compatibility
//
// // 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 = '/';
// TODO commented out for e4 compatibility
// // 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;
// TODO commented out for e4 compatibility
// private IntroRegistry introRegistry;
//
// private WorkbenchOperationSupport operationSupport;
private BundleListener bundleListener;
private SharedImages sharedImages;
// private WorkbenchOperationSupport operationSupport;
private EditorRegistry editorRegistry;
/**
* Create an instance of the WorkbenchPlugin. The workbench plugin is
* effectively the "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() {
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() {
// TODO commented out for e4 compatibility
// return WorkbenchImages.getImageRegistry();
return null;
}
/**
* Returns the action set registry for the workbench.
*
* @return the workbench action set registry
*/
// TODO commented out for e4 compatibility
// public ActionSetRegistry getActionSetRegistry() {
// if (actionSetRegistry == null) {
// actionSetRegistry = new ActionSetRegistry();
// }
// return actionSetRegistry;
// }
/**
* 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() {
if (editorRegistry == null) {
editorRegistry = new EditorRegistry();
}
return editorRegistry;
}
/**
* 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.
*/
// TODO commented out for e4 compatibility
// 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
*/
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() {
// FIXME: commented out for e4 compatibility, need to do startup
// threading in e4?
// 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;
return PlatformUI.getWorkbench().getPerspectiveRegistry();
}
/**
* Returns the working set manager
*
* @return the working set manager
* @since 2.0
*/
public IWorkingSetManager getWorkingSetManager() {
return PlatformUI.getWorkbench().getWorkingSetManager();
}
/**
* Returns the working set registry
*
* @return the working set registry
* @since 2.0
*/
public WorkingSetRegistry getWorkingSetRegistry() {
if (workingSetRegistry == null) {
workingSetRegistry = new WorkingSetRegistry();
workingSetRegistry.load();
}
return workingSetRegistry;
}
/**
* Returns the introduction registry.
*
* @return the introduction registry.
* @since 3.0
*/
// TODO commented out for e4 compatibility
// public IIntroRegistry getIntroRegistry() {
// if (introRegistry == null) {
// introRegistry = new IntroRegistry();
// }
// return introRegistry;
// }
/**
* Returns the operation support.
*
* @return the workbench operation support.
* @since 3.1
*/
public IWorkbenchOperationSupport getOperationSupport() {
// if (operationSupport == null) {
// operationSupport = new WorkbenchOperationSupport();
// }
// return operationSupport;
// FIXME compat: add operation support
E4Util.unsupported("getOperationSupport"); //$NON-NLS-1$
return new IWorkbenchOperationSupport() {
public IUndoContext getUndoContext() {
// TODO Auto-generated method stub
return null;
}
public IOperationHistory getOperationHistory() {
return new IOperationHistory() {
public IStatus undoOperation(IUndoableOperation operation,
IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
// TODO Auto-generated method stub
return Status.OK_STATUS;
}
public IStatus undo(IUndoContext context, IProgressMonitor monitor,
IAdaptable info) throws ExecutionException {
// TODO Auto-generated method stub
return Status.OK_STATUS;
}
public void setLimit(IUndoContext context, int limit) {
// TODO Auto-generated method stub
}
public void replaceOperation(IUndoableOperation operation,
IUndoableOperation[] replacements) {
// TODO Auto-generated method stub
}
public void removeOperationHistoryListener(IOperationHistoryListener listener) {
// TODO Auto-generated method stub
}
public void removeOperationApprover(IOperationApprover approver) {
// TODO Auto-generated method stub
}
public IStatus redoOperation(IUndoableOperation operation,
IProgressMonitor monitor, IAdaptable info) throws ExecutionException {
// TODO Auto-generated method stub
return Status.OK_STATUS;
}
public IStatus redo(IUndoContext context, IProgressMonitor monitor,
IAdaptable info) throws ExecutionException {
// TODO Auto-generated method stub
return Status.OK_STATUS;
}
public void operationChanged(IUndoableOperation operation) {
// TODO Auto-generated method stub
}
public void openOperation(ICompositeOperation operation, int mode) {
// TODO Auto-generated method stub
}
public IUndoableOperation getUndoOperation(IUndoContext context) {
// TODO Auto-generated method stub
return null;
}
public IUndoableOperation[] getUndoHistory(IUndoContext context) {
// TODO Auto-generated method stub
return null;
}
public IUndoableOperation getRedoOperation(IUndoContext context) {
// TODO Auto-generated method stub
return null;
}
public IUndoableOperation[] getRedoHistory(IUndoContext context) {
// TODO Auto-generated method stub
return null;
}
public int getLimit(IUndoContext context) {
// TODO Auto-generated method stub
return 0;
}
public IStatus execute(IUndoableOperation operation, IProgressMonitor monitor,
IAdaptable info) throws ExecutionException {
operation.execute(new NullProgressMonitor(), null);
// TODO Auto-generated method stub
return Status.OK_STATUS;
}
public void dispose(IUndoContext context, boolean flushUndo, boolean flushRedo,
boolean flushContext) {
// TODO Auto-generated method stub
}
public void closeOperation(boolean operationOK, boolean addToHistory, int mode) {
// TODO Auto-generated method stub
}
public boolean canUndo(IUndoContext context) {
// TODO Auto-generated method stub
return false;
}
public boolean canRedo(IUndoContext context) {
// TODO Auto-generated method stub
return false;
}
public void addOperationHistoryListener(IOperationHistoryListener listener) {
// TODO Auto-generated method stub
}
public void addOperationApprover(IOperationApprover approver) {
// TODO Auto-generated method stub
}
public void add(IUndoableOperation operation) {
// TODO Auto-generated method stub
}
};
}
};
}
/**
* Get the preference manager.
* @return PreferenceManager the preference manager for
* the receiver.
*/
public PreferenceManager getPreferenceManager() {
// TODO commented out for e4 compatibility
// 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;
// FIXME compat: add preference manager support
E4Util.unsupported("getPreferenceManager"); //$NON-NLS-1$
return null;
}
/**
* Returns the shared images for the workbench.
*
* @return the shared image manager
*/
public ISharedImages getSharedImages() {
if (sharedImages == null) {
sharedImages = new SharedImages();
}
return sharedImages;
}
/**
* Returns the theme registry for the workbench.
*
* @return the theme registry
*/
// TODO commented out for e4 compatibility
// public IThemeRegistry getThemeRegistry() {
// if (themeRegistry == null) {
// themeRegistry = new ThemeRegistry();
// ThemeRegistryReader reader = new ThemeRegistryReader();
// reader.readThemes(Platform.getExtensionRegistry(),
// themeRegistry);
// }
// return themeRegistry;
// }
/**
* 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() {
if (this.decoratorManager == null) {
this.decoratorManager = new DecoratorManager();
}
return decoratorManager;
}
/*
* (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);
final IEclipseContext serviceContext = org.eclipse.e4.workbench.ui.internal.E4Workbench
.getServiceContext();
instantiateCompatibilityLayerHooks(serviceContext);
}
} 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.
*/
}
private void instantiateCompatibilityLayerHooks(IEclipseContext context) {
initializeCompatibilityObjects(context);
initializeEventHandling(context);
}
/**
* Creates the necessary 3.x counterparts to the e4 model.
*
* @param context
* the OSGi service context
*/
private void initializeCompatibilityObjects(IEclipseContext context) {
MApplication application = (MApplication) context.get(MApplication.class.getName());
// this will be null when running compatibility tests
if (application != null) {
// instantiate the workbench
PlatformUI.getWorkbench();
// create IWW instances for all windows
for (MWindow window : application.getChildren()) {
WorkbenchWindow wwindow = new WorkbenchWindow(null, null);
ContextInjectionFactory.inject(wwindow, window.getContext());
}
}
}
/**
* Performs the necessary event handling hooks for creating 3.x counterparts
* to the e4 model.
*
* @param context
* the OSGi service context
*/
private void initializeEventHandling(IEclipseContext context) {
IEventBroker broker = (IEventBroker) context.get(
IEventBroker.class.getName());
// watch for parts' "toBeRendered" attribute being flipped to true, if
// they need to be rendered, then they need a corresponding 3.x
// reference
broker.subscribe(UIEvents.buildTopic(UIEvents.UIElement.TOPIC,
UIEvents.UIElement.TOBERENDERED), new EventHandler() {
public void handleEvent(Event event) {
if (Boolean.TRUE.equals(event.getProperty(UIEvents.EventTags.NEW_VALUE))) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (element instanceof MPart) {
MPart part = (MPart) element;
createReference(part);
}
}
}
});
// watch for parts' contexts being set, once they've been set, we need
// to inject the ViewReference/EditorReference into the context
broker.subscribe(UIEvents.buildTopic(UIEvents.Context.TOPIC, UIEvents.Context.CONTEXT),
new EventHandler() {
public void handleEvent(Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (element instanceof MPart) {
MPart part = (MPart) element;
IEclipseContext context = part.getContext();
if (context != null) {
setReference(part, context);
}
}
}
});
// watch for windows' widget being set, when the shell is set, we need a
// corresponding IWorkbenchWindow created for them
broker.subscribe(UIEvents.buildTopic(UIEvents.UIElement.TOPIC, UIEvents.UIElement.WIDGET),
new EventHandler() {
public void handleEvent(Event event) {
Object element = event.getProperty(UIEvents.EventTags.ELEMENT);
if (element instanceof MWindow) {
MWindow window = (MWindow) element;
if (window.getWidget() != null) {
WorkbenchWindow wwindow = new WorkbenchWindow(null, null);
ContextInjectionFactory.inject(wwindow, window.getContext());
}
}
}
});
}
/**
* Returns a workbench page that will contain the specified part. If no page
* can be located, one will be instantiated.
*
* @param part
* the model part to query a parent workbench page for
* @return the workbench page that contains the specified part
*/
private WorkbenchPage getWorkbenchPage(MPart part) {
IEclipseContext context = getWindowContext(part);
WorkbenchPage page = (WorkbenchPage) context.get(IWorkbenchPage.class.getName());
if (page == null) {
MWindow window = (MWindow) context.get(MWindow.class.getName());
Workbench workbench = (Workbench) PlatformUI.getWorkbench();
workbench.openWorkbenchWindow(null, null, window);
page = (WorkbenchPage) context.get(IWorkbenchPage.class.getName());
}
return page;
}
/**
* Sets the 3.x reference of the specified part into its context.
*
* @param part
* the model part that requires a 3.x part reference
* @param context
* the part's context
*/
private void setReference(MPart part, IEclipseContext context) {
String uri = part.getURI();
if (CompatibilityPart.COMPATIBILITY_VIEW_URI.equals(uri)) {
WorkbenchPage page = getWorkbenchPage(part);
ViewReference ref = page.getViewReference(part);
if (ref == null) {
ref = createViewReference(part, page);
}
context.set(ViewReference.class.getName(), ref);
}
}
private ViewReference createViewReference(MPart part, WorkbenchPage page) {
IViewDescriptor desc = page.getWorkbenchWindow().getWorkbench().getViewRegistry().find(
part.getId());
ViewReference ref = new ViewReference(page, part, (ViewDescriptor) desc);
page.addViewReference(ref);
return ref;
}
/**
* Creates a workbench part reference for the specified part.
*
* @param part
* the model part to create a 3.x part reference for
*/
private void createReference(MPart part) {
String uri = part.getURI();
if (CompatibilityPart.COMPATIBILITY_VIEW_URI.equals(uri)) {
WorkbenchPage page = getWorkbenchPage(part);
createViewReference(part, page);
}
}
private IEclipseContext getWindowContext(MPart part) {
MElementContainer<?> parent = part.getParent();
while (!(parent instanceof MWindow)) {
parent = parent.getParent();
}
return ((MWindow) parent).getContext();
}
/**
* 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 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 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() {
// TODO commented out for e4 compatibility
// return NewWizardRegistry.getInstance();
return null;
}
/**
* Return the import wizard registry.
*
* @return the import wizard registry
* @since 3.1
*/
public IWizardRegistry getImportWizardRegistry() {
// TODO commented out for e4 compatibility
// return ImportWizardRegistry.getInstance();
return null;
}
/**
* Return the export wizard registry.
*
* @return the export wizard registry
* @since 3.1
*/
public IWizardRegistry getExportWizardRegistry() {
// TODO commented out for e4 compatibility
// return ExportWizardRegistry.getInstance();
return null;
}
/**
* 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);
}
}
}