blob: 40cf1368fa4d85758ef0ad39d9c46b56ca7974f9 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008 BestSolution.at 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:
* Tom Schindl <tom.schindl@bestsolution.at> - initial API and implementation
* Boris Bokowski, IBM Corporation - initial API and implementation
******************************************************************************/
package org.eclipse.e4.workbench.ui.internal;
import java.io.File;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URLConnection;
import java.util.Collections;
import java.util.Map;
import org.eclipse.core.internal.runtime.PlatformURLPluginConnection;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IConfigurationElement;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.RegistryFactory;
import org.eclipse.e4.core.services.IContributionFactory;
import org.eclipse.e4.core.services.context.EclipseContextFactory;
import org.eclipse.e4.core.services.context.IEclipseContext;
import org.eclipse.e4.core.services.context.spi.ComputedValue;
import org.eclipse.e4.core.services.context.spi.IContextConstants;
import org.eclipse.e4.ui.model.application.ApplicationFactory;
import org.eclipse.e4.ui.model.application.MApplication;
import org.eclipse.e4.ui.model.application.MApplicationElement;
import org.eclipse.e4.ui.model.application.MContributedPart;
import org.eclipse.e4.ui.model.application.MPart;
import org.eclipse.e4.ui.model.application.MWindow;
import org.eclipse.e4.ui.model.workbench.MWorkbenchWindow;
import org.eclipse.e4.ui.model.workbench.WorkbenchPackage;
import org.eclipse.e4.ui.services.IServiceConstants;
import org.eclipse.e4.workbench.ui.IExceptionHandler;
import org.eclipse.e4.workbench.ui.ILegacyHook;
import org.eclipse.e4.workbench.ui.IWorkbench;
import org.eclipse.e4.workbench.ui.IWorkbenchWindowHandler;
import org.eclipse.e4.workbench.ui.renderers.PartFactory;
import org.eclipse.e4.workbench.ui.renderers.PartRenderer;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceFactoryImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.osgi.service.datalocation.Location;
import org.osgi.framework.Bundle;
import org.osgi.service.packageadmin.PackageAdmin;
public class Workbench implements IWorkbench {
public static final String ID = "org.eclipse.e4.workbench.fakedWBWindow"; //$NON-NLS-1$
private MApplication<? extends MWindow> workbench;
private static final boolean saveAndRestore = true;
private File workbenchData;
private IWorkbenchWindowHandler windowHandler;
private Object appWindow;
private final IExtensionRegistry registry;
private ResourceSetImpl resourceSet;
public IEclipseContext getContext() {
return globalContext;
}
// UI Construction...
private PartRenderer renderer;
private int rv;
private ExceptionHandler exceptionHandler;
private IEclipseContext globalContext;
private ReflectionContributionFactory contributionFactory;
public Workbench(Location instanceLocation, IExtensionRegistry registry,
PackageAdmin packageAdmin, URI workbenchXmiURI,
IEclipseContext applicationContext,
IWorkbenchWindowHandler windowHandler) {
this.windowHandler = windowHandler;
exceptionHandler = new ExceptionHandler();
this.registry = registry;
try {
workbenchData = new File(instanceLocation.getURL().toURI());
} catch (URISyntaxException e) {
throw new RuntimeException(e);
}
workbenchData = new File(workbenchData, ".metadata"); //$NON-NLS-1$
workbenchData = new File(workbenchData, ".plugins"); //$NON-NLS-1$
workbenchData = new File(workbenchData, "org.eclipse.e4.workbench"); //$NON-NLS-1$
workbenchData = new File(workbenchData, "workbench.xmi"); //$NON-NLS-1$
contributionFactory = new ReflectionContributionFactory(registry);
resourceSet = new ResourceSetImpl();
// Register the appropriate resource factory to handle all file
// extensions.
//
resourceSet.getResourceFactoryRegistry().getExtensionToFactoryMap()
.put(Resource.Factory.Registry.DEFAULT_EXTENSION,
new XMIResourceFactoryImpl());
// Register the package to ensure it is available during loading.
//
resourceSet.getPackageRegistry().put(WorkbenchPackage.eNS_URI,
WorkbenchPackage.eINSTANCE);
globalContext = createContext(applicationContext);
if (workbenchData != null && workbenchData.exists() && saveAndRestore) {
createWorkbenchModel(URI.createFileURI(workbenchData
.getAbsolutePath()), workbenchXmiURI);
} else {
createWorkbenchModel(null, workbenchXmiURI);
}
}
private IEclipseContext createContext(IEclipseContext applicationContext) {
final IEclipseContext mainContext = EclipseContextFactory.create(
applicationContext, UIContextScheduler.instance);
mainContext.set(IContextConstants.DEBUG_STRING, "globalContext"); //$NON-NLS-1$
IConfigurationElement[] contributions = registry
.getConfigurationElementsFor("org.eclipse.e4.services"); //$NON-NLS-1$
for (IConfigurationElement contribution : contributions) {
try {
for (IConfigurationElement serviceElement : contribution
.getChildren("service")) { //$NON-NLS-1$
Object factory = contribution
.createExecutableExtension("class"); //$NON-NLS-1$
String apiClassname = serviceElement.getAttribute("api"); //$NON-NLS-1$
mainContext.set(apiClassname, factory);
}
} catch (CoreException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
mainContext.set(IWorkbench.class.getName(), this);
mainContext.set(IExceptionHandler.class.getName(), exceptionHandler);
mainContext.set(IExtensionRegistry.class.getName(), registry);
mainContext.set(IServiceConstants.SELECTION,
new ActiveChildOutputValue(IServiceConstants.SELECTION));
mainContext.set(IServiceConstants.INPUT, new ComputedValue() {
public Object compute(IEclipseContext context, Object[] arguments) {
Class adapterType = null;
if (arguments.length > 0 && arguments[0] instanceof Class) {
adapterType = (Class) arguments[0];
}
Object newInput = null;
Object newValue = mainContext.get(IServiceConstants.SELECTION);
if (adapterType == null || adapterType.isInstance(newValue)) {
newInput = newValue;
} else if (newValue != null && adapterType != null) {
Object adapted = Platform.getAdapterManager().loadAdapter(
newValue, adapterType.getName());
if (adapted != null) {
newInput = adapted;
}
}
return newInput;
}
});
return mainContext;
}
private MApplication<? extends MWindow> createWorkbenchModel(
URI restoreLocation, URI applicationDefinitionInstance) {
long restoreLastModified = restoreLocation == null ? 0L : new File(
restoreLocation.toFileString()).lastModified();
long appLastModified = 0L;
ResourceSetImpl resourceSetImpl = new ResourceSetImpl();
Map<String, ?> attributes = resourceSetImpl
.getURIConverter()
.getAttributes(
applicationDefinitionInstance,
Collections
.singletonMap(
URIConverter.OPTION_REQUESTED_ATTRIBUTES,
Collections
.singleton(URIConverter.ATTRIBUTE_TIME_STAMP)));
Object timestamp = attributes.get(URIConverter.ATTRIBUTE_TIME_STAMP);
if (timestamp instanceof Long) {
appLastModified = ((Long) timestamp).longValue();
} else if (applicationDefinitionInstance.isPlatformPlugin()) {
try {
java.net.URL url = new java.net.URL(
applicationDefinitionInstance.toString());
Object[] obj = PlatformURLPluginConnection.parse(url.getFile()
.trim(), url);
Bundle b = (Bundle) obj[0];
URLConnection openConnection = b.getResource((String) obj[1])
.openConnection();
appLastModified = openConnection.getLastModified();
} catch (Exception e) {
// ignore
}
}
// new java.util.Date(appLastModified)
boolean restore = restoreLastModified > appLastModified;
if (restore) {
System.err.println("Restoring workbench: " + restoreLocation); //$NON-NLS-1$
workbench = (MApplication<MWindow>) resourceSetImpl.getResource(
restoreLocation, true).getContents().get(0);
} else {
System.err
.println("Initializing workbench: " + applicationDefinitionInstance); //$NON-NLS-1$
Resource resource = new XMIResourceImpl();
workbench = loadDefaultModel(applicationDefinitionInstance);
resource.getContents().add((EObject) workbench);
resource.setURI(URI.createFileURI(workbenchData.getAbsolutePath()));
}
init(workbench);
return workbench;
}
private MApplication<? extends MWindow> loadDefaultModel(
URI defaultModelPath) {
Resource resource = new ResourceSetImpl().getResource(defaultModelPath,
true);
MApplication<MWindow> app = (MApplication<MWindow>) resource
.getContents().get(0);
processPartContributions(resource, app.getWindows().get(0));
return app;
}
private void processPartContributions(Resource resource, MWindow mWindow) {
IExtensionRegistry registry = RegistryFactory.getRegistry();
String extId = "org.eclipse.e4.workbench.parts"; //$NON-NLS-1$
IConfigurationElement[] parts = registry
.getConfigurationElementsFor(extId);
for (int i = 0; i < parts.length; i++) {
MContributedPart<?> part = ApplicationFactory.eINSTANCE
.createMContributedPart();
part.setName(parts[i].getAttribute("label")); //$NON-NLS-1$
part.setIconURI("platform:/plugin/" //$NON-NLS-1$
+ parts[i].getContributor().getName() + "/" //$NON-NLS-1$
+ parts[i].getAttribute("icon")); //$NON-NLS-1$
part.setURI("platform:/plugin/" //$NON-NLS-1$
+ parts[i].getContributor().getName() + "/" //$NON-NLS-1$
+ parts[i].getAttribute("class")); //$NON-NLS-1$
String parentId = parts[i].getAttribute("parentId"); //$NON-NLS-1$
MPart parent = (MPart) findObject(resource.getAllContents(),
parentId);
if (parent != null) {
parent.getChildren().add(part);
}
}
}
private EObject findObject(TreeIterator<EObject> it, String id) {
while (it.hasNext()) {
EObject el = it.next();
if (el instanceof MApplicationElement) {
if (el.eResource().getURIFragment(el).equals(id)) {
return el;
}
}
}
return null;
}
private void init(MApplication<? extends MWindow> workbench2) {
// Capture the MApplication into the context
globalContext.set(MApplication.class.getName(), workbench);
// Initialize the workbench for legacy support if required
globalContext.get(ILegacyHook.class.getName());
}
public int run() {
MWindow wbw = workbench.getWindows().get(0);
createGUI(wbw);
rv = 0;
Platform.endSplash();
// A position of 0 is not possible on OS-X because then the title-bar is
// hidden
// below the MMenu-Bar
windowHandler.setBounds(appWindow, wbw.getX(), wbw.getY(), wbw
.getWidth(), wbw.getHeight());
windowHandler.layout(appWindow);
windowHandler.open(appWindow);
windowHandler.runEvenLoop(appWindow);
if (workbenchData != null && saveAndRestore && workbench != null) {
try {
System.err.println("Saving workbench: " //$NON-NLS-1$
+ ((EObject) workbench).eResource().getURI());
// workbenchData.getParentFile().mkdirs();
// workbenchData.createNewFile();
// FileOutputStream fos = new FileOutputStream(workbenchData);
// ((EObject)workbench).eResource().save(fos, null);
// fos.close();
((EObject) workbench).eResource().save(null);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return rv;
}
/**
* Initialize a part renderer from the extension point.
*
* @param registry
* the registry for the EP
* @param r
* the created renderer
* @param context
* the context for the part factories
* @param f
* the IContributionFactory already provided to <code>r</code>
*/
public static void initializeRenderer(IExtensionRegistry registry,
PartRenderer r, IEclipseContext context, IContributionFactory f) {
// add the factories from the extension point, sort by dependency
// * Need to make the EP more declarative to avoid aggressive
// loading
IConfigurationElement[] factories = registry
.getConfigurationElementsFor("org.eclipse.e4.workbench.partfactory"); //$NON-NLS-1$
// Sort the factories based on their dependence
// This is a hack, should be based on plug-in dependencies
int offset = 0;
for (int i = 0; i < factories.length; i++) {
String clsSpec = factories[i].getAttribute("class"); //$NON-NLS-1$
if (clsSpec.indexOf("Legacy") >= 0 //$NON-NLS-1$
|| clsSpec.indexOf("PartSash") >= 0) { //$NON-NLS-1$
IConfigurationElement tmp = factories[offset];
factories[offset++] = factories[i];
factories[i] = tmp;
}
}
for (int i = 0; i < factories.length; i++) {
PartFactory factory = null;
try {
factory = (PartFactory) factories[i]
.createExecutableExtension("class"); //$NON-NLS-1$
} catch (CoreException e) {
e.printStackTrace();
}
if (factory != null) {
factory.init(r, context, f);
r.addPartFactory(factory);
}
}
}
private void createGUI(MWindow wbw) {
if (renderer == null) {
renderer = new PartRenderer(contributionFactory, globalContext);
initializeRenderer(registry, renderer, globalContext,
contributionFactory);
}
renderer.createGui(wbw);
appWindow = wbw.getWidget();
}
public void close() {
windowHandler.dispose(appWindow);
}
// public Display getDisplay() {
// return appWindow.getDisplay();
// }
public void closeWindow(MWorkbenchWindow workbenchWindow) {
windowHandler.close(workbenchWindow.getWidget());
}
public Object getWindow() {
return appWindow;
}
}