blob: 75e7a9411195740178e80cec2836fc0a140018a6 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005, 2008 IBM Corporation and others.
*
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.equinox.internal.app;
import java.security.AccessController;
import java.security.PrivilegedAction;
import org.eclipse.core.runtime.IContributor;
import org.eclipse.core.runtime.IExtensionRegistry;
import org.eclipse.core.runtime.spi.RegistryContributor;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.service.debug.DebugOptions;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
public class Activator implements BundleActivator, ServiceTrackerCustomizer {
public static final String PI_APP = "org.eclipse.equinox.app"; //$NON-NLS-1$
public static boolean DEBUG = false;
private volatile static BundleContext _context;
// PackageAdmin is a system service that never goes away as long
// as the framework is active. No need to track it!!
private volatile static PackageAdmin _packageAdmin;
private volatile static EclipseAppContainer container;
// tracks the FrameworkLog service
private volatile static ServiceTracker _frameworkLogTracker;
// tracks the extension registry and app launcher services
private ServiceTracker registryTracker;
private IExtensionRegistry registry;
public void start(BundleContext bc) {
_context = bc;
// doing simple get service here because we expect the PackageAdmin service to always be available
ServiceReference ref = bc.getServiceReference(PackageAdmin.class.getName());
if (ref != null)
_packageAdmin = (PackageAdmin) bc.getService(ref);
_frameworkLogTracker = new ServiceTracker(bc, FrameworkLog.class.getName(), null);
_frameworkLogTracker.open();
getDebugOptions(bc);
processCommandLineArgs(bc);
// set the app manager context before starting the container
AppPersistence.start(bc);
// we must have an extension registry started before we can start the container
registryTracker = new ServiceTracker(bc, IExtensionRegistry.class.getName(), this);
registryTracker.open();
// start the app commands for the console
try {
AppCommands.create(bc);
} catch (NoClassDefFoundError e) {
// catch incase CommandProvider is not available
}
}
public void stop(BundleContext bc) {
// stop the app commands for the console
try {
AppCommands.destroy(bc);
} catch (NoClassDefFoundError e) {
// catch incase CommandProvider is not available
}
// close the registry tracker; this will stop the container if it was started
registryTracker.close();
registryTracker = null;
// unset the app manager context after the container has been stopped
AppPersistence.stop();
if (_frameworkLogTracker != null) {
_frameworkLogTracker.close();
_frameworkLogTracker = null;
}
_packageAdmin = null; // we do not unget PackageAdmin here; let the framework do it for us
_context = null;
}
private void getDebugOptions(BundleContext context) {
ServiceReference debugRef = context.getServiceReference(DebugOptions.class.getName());
if (debugRef == null)
return;
DebugOptions debugOptions = (DebugOptions) context.getService(debugRef);
DEBUG = debugOptions.getBooleanOption(PI_APP + "/debug", false); //$NON-NLS-1$
context.ungetService(debugRef);
}
private static EnvironmentInfo getEnvironmentInfo() {
BundleContext bc = Activator.getContext();
if (bc == null)
return null;
ServiceReference infoRef = bc.getServiceReference(EnvironmentInfo.class.getName());
if (infoRef == null)
return null;
EnvironmentInfo envInfo = (EnvironmentInfo) bc.getService(infoRef);
if (envInfo == null)
return null;
bc.ungetService(infoRef);
return envInfo;
}
private void processCommandLineArgs(BundleContext bc) {
EnvironmentInfo envInfo = Activator.getEnvironmentInfo();
if (envInfo != null)
CommandLineArgs.processCommandLine(envInfo);
}
public Object addingService(ServiceReference reference) {
BundleContext context = _context;
if (context == null)
return null; // really should never happen since we close the tracker before nulling out context
Object service = null;
EclipseAppContainer startContainer = null;
synchronized (this) {
if (container != null)
return null; // container is already started; do nothing
service = context.getService(reference);
if (registry == null && service instanceof IExtensionRegistry) {
registry = (IExtensionRegistry) service;
// create and start the app container
container = new EclipseAppContainer(context, registry);
startContainer = container;
}
}
// must not start the container while holding a lock because this will register additional services
if (startContainer != null) {
startContainer.start();
return service;
}
// this means there is more than one registry; we don't need a second one
if (service != null)
context.ungetService(reference);
return null;
}
public void modifiedService(ServiceReference reference, Object service) {
// do nothing
}
public void removedService(ServiceReference reference, Object service) {
EclipseAppContainer currentContainer = null;
synchronized (this) {
// either the registry or launcher is going away
if (service == registry)
registry = null;
if (container == null)
return; // do nothing; we have not started the container yet
currentContainer = container;
container = null;
}
// stop the app container outside the sync block
if (currentContainer != null)
currentContainer.stop();
}
// helper used to protect callers from permission checks when opening service trackers
static void openTracker(final ServiceTracker tracker, final boolean allServices) {
if (System.getSecurityManager() == null)
tracker.open(allServices);
else
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
tracker.open(allServices);
return null;
}
});
}
// helper used to protect callers from permission checks when get services
static Object getService(final ServiceTracker tracker) {
if (System.getSecurityManager() == null)
return tracker.getService();
return AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return tracker.getService();
}
});
}
// helper used to protect callers from permission checks when getting locations
static String getLocation(final Bundle bundle) {
if (System.getSecurityManager() == null)
return bundle.getLocation();
return (String) AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
return bundle.getLocation();
}
});
}
// helper method to get a bundle from a contributor.
static Bundle getBundle(IContributor contributor) {
if (contributor instanceof RegistryContributor) {
try {
long id = Long.parseLong(((RegistryContributor) contributor).getActualId());
BundleContext context = _context;
if (context != null)
return context.getBundle(id);
} catch (NumberFormatException e) {
// try using the name of the contributor below
}
}
PackageAdmin packageAdmin = _packageAdmin;
if (packageAdmin == null)
return null;
Bundle[] bundles = packageAdmin.getBundles(contributor.getName(), null);
if (bundles == null)
return null;
//Return the first bundle that is not installed or uninstalled
for (int i = 0; i < bundles.length; i++)
if ((bundles[i].getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0)
return bundles[i];
return null;
}
static BundleContext getContext() {
return _context;
}
public static EclipseAppContainer getContainer() {
return container;
}
static void log(FrameworkLogEntry entry) {
ServiceTracker frameworkLogTracker = _frameworkLogTracker;
FrameworkLog log = frameworkLogTracker == null ? null : (FrameworkLog) frameworkLogTracker.getService();
if (log != null)
log.log(entry);
}
static void setProperty(String key, String value) {
EnvironmentInfo envInfo = getEnvironmentInfo();
if (envInfo != null)
envInfo.setProperty(key, value);
else
System.getProperties().setProperty(key, value);
}
}