diff options
Diffstat (limited to 'bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app')
9 files changed, 180 insertions, 114 deletions
diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/Activator.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/Activator.java index dbd354062..7311f24cb 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/Activator.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/Activator.java @@ -70,7 +70,7 @@ public class Activator implements BundleActivator, ServiceTrackerCustomizer { // create and start the app containerMgr IExtensionRegistry registry = (IExtensionRegistry) bContext.getService(reference); containerMgr = new ContainerManager(bContext, registry); - containerMgr.startContainer(); + containerMgr.startManager(); return registry; } @@ -82,7 +82,7 @@ public class Activator implements BundleActivator, ServiceTrackerCustomizer { if (containerMgr == null) return; // stop the app containerMgr - containerMgr.stopContainer(); + containerMgr.stopManager(); containerMgr = null; } } diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppManager.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppManager.java index 6c8bc20ea..7c9d4bb9b 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppManager.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/AppManager.java @@ -33,8 +33,8 @@ public class AppManager { private static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$ private static final String FILTER_PREFIX = "(&(objectClass=org.eclipse.osgi.service.datalocation.Location)(type="; //$NON-NLS-1$ - static final String FILE_APPLOCKS = ".locks"; //$NON-NLS-1$ - static final String FILE_APPSCHEDULED = ".scheduled"; //$NON-NLS-1$ + private static final String FILE_APPLOCKS = ".locks"; //$NON-NLS-1$ + private static final String FILE_APPSCHEDULED = ".scheduled"; //$NON-NLS-1$ private static final String EVENT_HANDLER = "org.osgi.service.event.EventHandler"; //$NON-NLS-1$ private static final String EVENT_TIMER_TOPIC = "org/osgi/application/timer"; //$NON-NLS-1$ @@ -67,7 +67,7 @@ public class AppManager { private static Collection locks = new ArrayList(); private static Map scheduledApps = new HashMap(); static ArrayList timerApps = new ArrayList(); - private static StorageManager fileManager; + private static StorageManager storageManager; private static boolean dirty; private static boolean scheduling = false; static boolean shutdown = false; @@ -98,9 +98,9 @@ public class AppManager { shutdown = true; stopTimer(); saveData(); - if (fileManager != null) { - fileManager.close(); - fileManager = null; + if (storageManager != null) { + storageManager.close(); + storageManager = null; } closeConfiguration(); closePackageAdmin(); @@ -236,9 +236,9 @@ public class AppManager { return false; File theStorageDir = new File(location.getURL().getPath() + '/' + Activator.PI_APP); boolean readOnly = location.isReadOnly(); - fileManager = new StorageManager(theStorageDir, readOnly ? "none" : null, readOnly); //$NON-NLS-1$ - fileManager.open(!readOnly); - File dataFile = fileManager.lookup(fileName, false); + storageManager = new StorageManager(theStorageDir, readOnly ? "none" : null, readOnly); //$NON-NLS-1$ + storageManager.open(!readOnly); + File dataFile = storageManager.lookup(fileName, false); if (dataFile == null || !dataFile.isFile()) { Location parent = location.getParentLocation(); if (parent != null) { @@ -308,16 +308,16 @@ public class AppManager { } private synchronized static void saveData() { - if (!dirty || fileManager.isReadOnly()) + if (!dirty || storageManager.isReadOnly()) return; try { - File locksData = fileManager.createTempFile(FILE_APPLOCKS); + File locksData = storageManager.createTempFile(FILE_APPLOCKS); saveLocks(locksData); - File schedulesData = fileManager.createTempFile(FILE_APPSCHEDULED); + File schedulesData = storageManager.createTempFile(FILE_APPSCHEDULED); saveSchedules(schedulesData); - fileManager.lookup(FILE_APPLOCKS, true); - fileManager.lookup(FILE_APPSCHEDULED, true); - fileManager.update(new String[] {FILE_APPLOCKS, FILE_APPSCHEDULED}, new String[] {locksData.getName(), schedulesData.getName()}); + storageManager.lookup(FILE_APPLOCKS, true); + storageManager.lookup(FILE_APPSCHEDULED, true); + storageManager.update(new String[] {FILE_APPLOCKS, FILE_APPSCHEDULED}, new String[] {locksData.getName(), schedulesData.getName()}); } catch (IOException e) { // TODO should log this!! } @@ -582,4 +582,8 @@ public class AppManager { } }); } + + static BundleContext getContext() { + return context; + } } diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ContainerManager.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ContainerManager.java index a81466d95..a7a447812 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ContainerManager.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ContainerManager.java @@ -31,16 +31,21 @@ import org.osgi.util.tracker.ServiceTracker; * A MEG application container that understands eclipse applications. This * container will discover installed eclipse applications and register the * appropriate ApplicatoinDescriptor service with the service registry. + * It also manages container extensions which are uses to launch + * different application types. */ public class ContainerManager implements IRegistryChangeListener, SynchronousBundleListener { private static final String PI_RUNTIME = "org.eclipse.core.runtime"; //$NON-NLS-1$ private static final String PT_APPLICATIONS = "applications"; //$NON-NLS-1$ private static final String PT_APP_TYPE = "type"; //$NON-NLS-1$ + private static final String PT_APP_VISIBLE = "visible"; //$NON-NLS-1$ + private static final String PT_APP_SINGLETON = "singleton"; //$NON-NLS-1$ private static final String PT_RUN = "run"; //$NON-NLS-1$ private static final String PT_PRODUCTS = "products"; //$NON-NLS-1$ private static final String PT_CONTAINERS = "containers"; //$NON-NLS-1$ private static final String ATTR_APPLICATION = "application"; //$NON-NLS-1$ - static final String APP_TYPE_MAIN_SINGLETON = "main.singleton"; //$NON-NLS-1$ + private static final String EXT_ERROR_APP = "org.eclipse.equinox.app.error"; //$NON-NLS-1$ + static final String APP_TYPE_MAIN_THREAD = "main.thread"; //$NON-NLS-1$ public static final String PROP_PRODUCT = "eclipse.product"; //$NON-NLS-1$ public static final String PROP_ECLIPSE_APPLICATION = "eclipse.application"; //$NON-NLS-1$ @@ -62,19 +67,20 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun this.extensionRegistry = extensionRegistry; } - void startContainer() { + void startManager() { frameworkLog = new ServiceTracker(context, FrameworkLog.class.getName(), null); frameworkLog.open(); getExtensionRegistry().addRegistryChangeListener(this); registerAppDecriptors(); - containers.put(APP_TYPE_MAIN_SINGLETON, new SingletonContainerMgr(new MainSingletonContainer(this), APP_TYPE_MAIN_SINGLETON, this)); // need to listen for system bundle stopping context.addBundleListener(this); + // Start the default application + startDefaultApp(); } - void stopContainer() { - // stop all applications first - stopAllApplications(); + void stopManager() { + // stop all applications and containers first + stopAll(); context.removeBundleListener(this); getExtensionRegistry().removeRegistryChangeListener(this); frameworkLog.close(); @@ -133,9 +139,13 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun // the appDescriptor does not exist for the app ID; create it IConfigurationElement[] configs = appExtension.getConfigurationElements(); String type = null; - if (configs.length > 0) + boolean visible = true; + if (configs.length > 0) { type = configs[0].getAttribute(PT_APP_TYPE); - appDescriptor = new EclipseAppDescriptor(appExtension.getNamespace(), appExtension.getUniqueIdentifier(), type, this); + String sVisible = configs[0].getAttribute(PT_APP_VISIBLE); + visible = sVisible == null ? true : Boolean.valueOf(sVisible).booleanValue(); + } + appDescriptor = new EclipseAppDescriptor(appExtension.getNamespace(), appExtension.getUniqueIdentifier(), type, visible, this); // register the appDescriptor as a service ServiceRegistration sr = (ServiceRegistration) AccessController.doPrivileged(new RegisterService(ApplicationDescriptor.class.getName(), appDescriptor, appDescriptor.getServiceProperties())); appDescriptor.setServiceRegistration(sr); @@ -181,7 +191,26 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun } } - EclipseAppDescriptor findDefaultApp() { + private void startDefaultApp() { + if (!Boolean.getBoolean(ContainerManager.PROP_ECLIPSE_APPLICATION_NODEFAULT)) { + // find the default application + EclipseAppDescriptor defaultDesc = findDefaultApp(); + // if the default app is a main thread one then we have to just tell the + // main thread container about the default app so it can launch it when it is ready + if (APP_TYPE_MAIN_THREAD.equals(defaultDesc.getType())) { + MainThreadContainer container = (MainThreadContainer) ((SingletonContainer) getContainer(APP_TYPE_MAIN_THREAD)).getContainer(); + container.setDefaultApp(defaultDesc); + } else + // just launch the default application + try { + defaultDesc.launch(null); + } catch (Exception e) { + // TODO should log this!! + } + } + } + + private EclipseAppDescriptor findDefaultApp() { String applicationId = System.getProperty(PROP_ECLIPSE_APPLICATION); if (applicationId == null) { //Derive the application from the product information @@ -190,13 +219,19 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun // use the long way to set the property to compile against eeminimum System.getProperties().setProperty(PROP_ECLIPSE_APPLICATION, applicationId); } - if (applicationId == null) + if (applicationId == null) { // the application id is not set; return a descriptor that will throw an exception - return new EclipseAppDescriptor(Activator.PI_APP, Activator.PI_APP + ".missingapp", null, this, new RuntimeException(Messages.application_noIdFound)); //$NON-NLS-1$ + // return new EclipseAppDescriptor(Activator.PI_APP, Activator.PI_APP + ".missingapp", null, false, this, new RuntimeException(Messages.application_noIdFound)); //$NON-NLS-1$ + ErrorApplication.setError(new RuntimeException(Messages.application_noIdFound)); + return getAppDescriptor(EXT_ERROR_APP); + } EclipseAppDescriptor defaultApp = getAppDescriptor(applicationId); - if (defaultApp == null) + if (defaultApp == null) { // the application id is not available in the registry; return a descriptor that will throw an exception - return new EclipseAppDescriptor(applicationId, applicationId, null, this, new RuntimeException(NLS.bind(Messages.application_notFound, applicationId, getAvailableAppsMsg(getExtensionRegistry())))); + //return new EclipseAppDescriptor(applicationId, applicationId, null, false, this, new RuntimeException(NLS.bind(Messages.application_notFound, applicationId, getAvailableAppsMsg(getExtensionRegistry())))); + ErrorApplication.setError(new RuntimeException(NLS.bind(Messages.application_notFound, applicationId, getAvailableAppsMsg(getExtensionRegistry())))); + return getAppDescriptor(EXT_ERROR_APP); + } return defaultApp; } @@ -225,17 +260,19 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun if (configs.length == 0) return null; String containerType = configs[0].getAttribute(PT_APP_TYPE); - if (type.equals(containerType)) - return createContainer(configs[0], type); + if (type.equals(containerType)) { + boolean singleton = Boolean.valueOf(configs[0].getAttribute(PT_APP_SINGLETON)).booleanValue(); + return createContainer(configs[0], type, singleton); + } } return null; } - private IContainer createContainer(IConfigurationElement config, String type) { + private IContainer createContainer(IConfigurationElement config, String type, boolean singleton) { try { IContainer container = (IContainer) config.createExecutableExtension(PT_RUN); - if (container.isSingletonContainer()) - container = new SingletonContainerMgr(container, type, this); + if (singleton) + container = new SingletonContainer(container, type, this); return container; } catch (CoreException e) { // TODO should log this @@ -309,10 +346,6 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun return (FrameworkLog) AppManager.getService(frameworkLog); } - BundleContext getBundleContext() { - return context; - } - private String getProductAppId() { String productId = System.getProperty(PROP_PRODUCT); if (productId == null) @@ -369,13 +402,11 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun void launch(EclipseAppHandle appHandle) throws Exception { String type = ((EclipseAppDescriptor) appHandle.getApplicationDescriptor()).getType(); if (type == null) - type = APP_TYPE_MAIN_SINGLETON; + type = APP_TYPE_MAIN_THREAD; IContainer container = getContainer(type); - if (container != null) { - if (container instanceof SingletonContainerMgr) - ((SingletonContainerMgr) container).lock(appHandle); + if (container != null) appHandle.setApplication(container.launch(appHandle)); - } else + else throw new UnsupportedOperationException(NLS.bind(Messages.container_notFound, appHandle.getApplicationDescriptor().getApplicationId(), type)); } @@ -415,27 +446,30 @@ public class ContainerManager implements IRegistryChangeListener, SynchronousBun // if this is not the system bundle stopping then ignore the event if ((BundleEvent.STOPPING & event.getType()) == 0 || event.getBundle().getBundleId() != 0) return; - // The system bundle is stopping; better stop all applications now - stopAllApplications(); + // The system bundle is stopping; better stop all applications and containers now + stopAll(); } - private void stopAllApplications() { + private void stopAll() { // get a stapshot of running applications try { ServiceReference[] runningRefs = context.getServiceReferences(ApplicationHandle.class.getName(), "(!(application.state=STOPPING))"); //$NON-NLS-1$ - if (runningRefs == null) - return; - for (int i = 0; i < runningRefs.length; i++) { - ApplicationHandle handle = (ApplicationHandle) context.getService(runningRefs[i]); - try { - handle.destroy(); - } catch (Throwable t) { - // TODO should log this - } + if (runningRefs != null) + for (int i = 0; i < runningRefs.length; i++) { + ApplicationHandle handle = (ApplicationHandle) context.getService(runningRefs[i]); + try { + handle.destroy(); + } catch (Throwable t) { + // TODO should log this + } } } catch (InvalidSyntaxException e) { // do nothing; we already tested the filter string above } - + // shutdown all containers + synchronized (containers) { + for (Iterator iContainers = containers.values().iterator(); iContainers.hasNext();) + ((IContainer) iContainers.next()).shutdown(); + } } } diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppDescriptor.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppDescriptor.java index a98312069..e0cd87123 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppDescriptor.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppDescriptor.java @@ -26,23 +26,19 @@ import org.osgi.service.condpermadmin.ConditionInfo; public class EclipseAppDescriptor extends ApplicationDescriptor { private ServiceRegistration sr; private Boolean locked = Boolean.FALSE; - private SingletonContainerMgr singletonMgr; + private SingletonContainer singletonMgr; private ContainerManager containerMgr; private String namespace; private String type; - private RuntimeException error; + private boolean visible; - protected EclipseAppDescriptor(String namespace, String pid, String type, ContainerManager containerMgr) { + protected EclipseAppDescriptor(String namespace, String pid, String type, boolean visible, ContainerManager containerMgr) { super(pid); - this.type = type == null ? ContainerManager.APP_TYPE_MAIN_SINGLETON : type; + this.type = type == null ? ContainerManager.APP_TYPE_MAIN_THREAD : type; this.namespace = namespace; this.containerMgr = containerMgr; this.locked = AppManager.isLocked(this) ? Boolean.TRUE : Boolean.FALSE; - } - - protected EclipseAppDescriptor(String namespace, String pid, String type, ContainerManager containerMgr, RuntimeException error) { - this(namespace, pid, type, containerMgr); - this.error = error; + this.visible = visible; } protected Map getPropertiesSpecific(String locale) { @@ -96,7 +92,7 @@ public class EclipseAppDescriptor extends ApplicationDescriptor { sr.setProperties(getServiceProperties()); } - void setSingletonMgr(SingletonContainerMgr singletonMgr) { + void setSingletonMgr(SingletonContainer singletonMgr) { this.singletonMgr = singletonMgr; } @@ -114,7 +110,7 @@ public class EclipseAppDescriptor extends ApplicationDescriptor { props.put(ApplicationDescriptor.APPLICATION_LOCATION, getLocation()); props.put(ApplicationDescriptor.APPLICATION_LAUNCHABLE, singletonMgr == null ? Boolean.TRUE : singletonMgr.isLocked() ? Boolean.FALSE : Boolean.TRUE); props.put(ApplicationDescriptor.APPLICATION_LOCKED, locked); - props.put(ApplicationDescriptor.APPLICATION_VISIBLE, Boolean.TRUE); + props.put(ApplicationDescriptor.APPLICATION_VISIBLE, visible ? Boolean.TRUE : Boolean.FALSE); return props; } @@ -130,11 +126,7 @@ public class EclipseAppDescriptor extends ApplicationDescriptor { */ private synchronized EclipseAppHandle createAppHandle() { // TODO not sure what instance pid should be used; for now just use the appDesciptor pid because apps are singletons anyway - EclipseAppHandle newAppHandle; - if (error == null) - newAppHandle = new EclipseAppHandle(getApplicationId(), this); - else - newAppHandle = new EclipseAppHandle(error, containerMgr); + EclipseAppHandle newAppHandle = new EclipseAppHandle(getApplicationId(), this); ServiceRegistration appHandleReg = (ServiceRegistration) AccessController.doPrivileged(containerMgr.getRegServiceAction(ApplicationHandle.class.getName(), newAppHandle, newAppHandle.getServiceProperties())); newAppHandle.setServiceRegistration(appHandleReg); return newAppHandle; diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppHandle.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppHandle.java index b200b567c..fccf2ae6b 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppHandle.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/EclipseAppHandle.java @@ -28,18 +28,9 @@ public class EclipseAppHandle extends ApplicationHandle implements IAppContext { private String state = ApplicationHandle.RUNNING; private int status = IAppContext.ACTIVE; private Object application; - private Exception appNotFound; private Map arguments; /* - * Used to create a dummy handle to throw an exception when run by the ApplicationLauncher. - */ - EclipseAppHandle(Exception appNotFound, ContainerManager containerMgr) { - this("", new EclipseAppDescriptor("", "", null, containerMgr)); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ - this.appNotFound = appNotFound; - } - - /* * Constructs a handle for a single running instance of a eclipse application. */ EclipseAppHandle(String instanceId, EclipseAppDescriptor descriptor) { @@ -125,7 +116,4 @@ public class EclipseAppHandle extends ApplicationHandle implements IAppContext { return configs[0]; } - public Exception getLaunchException() { - return appNotFound; - } } diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ErrorApplication.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ErrorApplication.java new file mode 100755 index 000000000..ba58eaf30 --- /dev/null +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/ErrorApplication.java @@ -0,0 +1,37 @@ +/******************************************************************************* + * Copyright (c) 2005 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.equinox.internal.app; + +import org.eclipse.equinox.app.IApplication; + +/* + * Special case class only used to throw exceptions when an application + * cannot be found. + */ +public class ErrorApplication implements IApplication { + + static private Exception ERROR; + + public Object run(Object args) throws Exception { + if (ERROR != null) + throw ERROR; + throw new IllegalStateException(); + } + + public void stop() { + // do nothing + } + + static void setError(Exception error) { + ERROR = error; + } +} diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainSingletonApplication.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainThreadApplication.java index 3b1116c72..1752b18a7 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainSingletonApplication.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainThreadApplication.java @@ -15,21 +15,21 @@ import org.eclipse.equinox.app.IApplication; import org.eclipse.osgi.service.runnable.ApplicationRunnable; import org.eclipse.osgi.util.NLS; -public class MainSingletonApplication implements ApplicationRunnable { +public class MainThreadApplication implements ApplicationRunnable { private static final String PROP_ECLIPSE_EXITCODE = "eclipse.exitcode"; //$NON-NLS-1$ private Object application; private EclipseAppHandle appContext; private Exception launchException; - public MainSingletonApplication(EclipseAppHandle appContext) { + public MainThreadApplication(EclipseAppHandle appContext) { this.appContext = appContext; - this.launchException = appContext.getLaunchException(); - if (launchException == null) - try { - application = appContext.getConfiguration().createExecutableExtension("run"); //$NON-NLS-1$ - } catch (Exception e) { - this.launchException = e; - } + try { + application = appContext.getConfiguration().createExecutableExtension("run"); //$NON-NLS-1$ + } catch (Exception e) { + // had an error creating the executable extension + // save the exception to throw on the main thread (keeping legacy behavior) + this.launchException = e; + } } public Object run(Object context) throws Exception { diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainSingletonContainer.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainThreadContainer.java index 37ec48459..b25db2424 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainSingletonContainer.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/MainThreadContainer.java @@ -16,16 +16,16 @@ import org.osgi.framework.ServiceReference; import org.osgi.util.tracker.ServiceTracker; import org.osgi.util.tracker.ServiceTrackerCustomizer; -public class MainSingletonContainer implements IContainer, ServiceTrackerCustomizer { +public class MainThreadContainer implements IContainer, ServiceTrackerCustomizer { // tracks the application launcher private ServiceTracker appLauncherTracker; // the application launcher used to launch applications on the main thread. private ApplicationLauncher appLauncher; - private ContainerManager containerMgr; + // the default app to launch once we are ready + private EclipseAppDescriptor defaultDesc; - public MainSingletonContainer(ContainerManager containerMgr) { - this.containerMgr = containerMgr; - appLauncherTracker = new ServiceTracker(containerMgr.getBundleContext(), ApplicationLauncher.class.getName(), this); + public MainThreadContainer() { + appLauncherTracker = new ServiceTracker(AppManager.getContext(), ApplicationLauncher.class.getName(), this); appLauncherTracker.open(); } @@ -34,7 +34,7 @@ public class MainSingletonContainer implements IContainer, ServiceTrackerCustomi // to ensure it is launched on the main thread if (appLauncher == null) throw new IllegalStateException(); - MainSingletonApplication app = new MainSingletonApplication((EclipseAppHandle) appContext); + MainThreadApplication app = new MainThreadApplication((EclipseAppHandle) appContext); appLauncher.launch(app, appContext.getArguments() == null ? null : appContext.getArguments().get(ContainerManager.PROP_ECLIPSE_APPLICATION_ARGS)); return app.getApplication(); } @@ -42,34 +42,37 @@ public class MainSingletonContainer implements IContainer, ServiceTrackerCustomi public Object addingService(ServiceReference reference) { if (appLauncher != null) return null; - appLauncher = (ApplicationLauncher) containerMgr.getBundleContext().getService(reference); - if (!Boolean.getBoolean(ContainerManager.PROP_ECLIPSE_APPLICATION_NODEFAULT)) { - // find the default application - EclipseAppDescriptor defaultDesc = containerMgr.findDefaultApp(); + appLauncher = (ApplicationLauncher) AppManager.getContext().getService(reference); + if (defaultDesc != null) // launch the default application try { defaultDesc.launch(null); + defaultDesc = null; // don't want to launch it more than once } catch (Exception e) { // TODO should log this!! } - } return appLauncher; } public void modifiedService(ServiceReference reference, Object service) { - // TODO Auto-generated method stub - + // do nothing } public synchronized void removedService(ServiceReference reference, Object service) { if (service == appLauncher) { appLauncher = null; - containerMgr.getBundleContext().ungetService(reference); + AppManager.getContext().ungetService(reference); } } - public boolean isSingletonContainer() { - return true; + public void shutdown() { + if (appLauncherTracker != null) { + appLauncherTracker.close(); + appLauncherTracker = null; + } } + public void setDefaultApp(EclipseAppDescriptor defaultDesc) { + this.defaultDesc = defaultDesc; + } } diff --git a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/SingletonContainerMgr.java b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/SingletonContainer.java index 9377ff276..8b61feee9 100755 --- a/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/SingletonContainerMgr.java +++ b/bundles/org.eclipse.equinox.app/src/org/eclipse/equinox/internal/app/SingletonContainer.java @@ -12,21 +12,21 @@ package org.eclipse.equinox.internal.app; import org.eclipse.equinox.app.*; -public class SingletonContainerMgr implements IContainer { +public class SingletonContainer implements IContainer { private EclipseAppHandle singletonHandle; private String type; private IContainer singletonContainer; private ContainerManager containerManager; - public SingletonContainerMgr(IContainer singletonContainer, String type, ContainerManager containerManager) { + public SingletonContainer(IContainer singletonContainer, String type, ContainerManager containerManager) { this.singletonContainer = singletonContainer; this.type = type; this.containerManager = containerManager; } public synchronized IApplication launch(IAppContext context) throws Exception { - if (context != singletonHandle) - throw new IllegalStateException("Only one application of type \"" + type + "\" is allowed to run at a time"); + // attempt to lock this application type; an exception will be thrown if the type cannot be locked + lock((EclipseAppHandle) context); return singletonContainer.launch(context); } @@ -57,4 +57,12 @@ public class SingletonContainerMgr implements IContainer { singletonApps[i].refreshProperties(); } } + + public void shutdown() { + singletonContainer.shutdown(); + } + + IContainer getContainer() { + return singletonContainer; + } } |