Eclipse Startup
- First of all, we take a look at class EclipseStarter
/*******************************************************************************
* Copyright (c) 2003, 2012 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
* Alex Blewitt (bug 172969)
*******************************************************************************/
package org.eclipse.core.runtime.adaptor; import java.io.*;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.net.*;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.*;
import org.eclipse.core.runtime.internal.adaptor.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.baseadaptor.BaseStorageHook;
import org.eclipse.osgi.internal.profile.Profile;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.resolver.*;
import org.eclipse.osgi.service.runnable.ApplicationLauncher;
import org.eclipse.osgi.service.runnable.StartupMonitor;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.service.packageadmin.PackageAdmin;
import org.osgi.service.startlevel.StartLevel;
import org.osgi.util.tracker.ServiceTracker; /**
* Special startup class for the Eclipse Platform. This class cannot be
* instantiated; all functionality is provided by static methods.
* <p>
* The Eclipse Platform makes heavy use of Java class loaders for loading
* plug-ins. Even the Eclipse Runtime itself and the OSGi framework need
* to be loaded by special class loaders. The upshot is that a
* client program (such as a Java main program, a servlet) cannot
* reference any part of Eclipse directly. Instead, a client must use this
* loader class to start the platform, invoking functionality defined
* in plug-ins, and shutting down the platform when done.
* </p>
* <p>Note that the fields on this class are not API. </p>
* @since 3.0
* @noextend This class is not intended to be subclassed by clients.
*/
public class EclipseStarter {
private static FrameworkAdaptor adaptor;
private static BundleContext context;
private static boolean initialize = false;
public static boolean debug = false;
private static boolean running = false;
private static Framework framework = null;
private static ServiceRegistration<?> defaultMonitorRegistration = null;
private static ServiceRegistration<?> appLauncherRegistration = null;
private static ServiceRegistration<?> splashStreamRegistration = null; // command line arguments
private static final String CLEAN = "-clean"; //$NON-NLS-1$
private static final String CONSOLE = "-console"; //$NON-NLS-1$
private static final String CONSOLE_LOG = "-consoleLog"; //$NON-NLS-1$
private static final String DEBUG = "-debug"; //$NON-NLS-1$
private static final String INITIALIZE = "-initialize"; //$NON-NLS-1$
private static final String DEV = "-dev"; //$NON-NLS-1$
private static final String WS = "-ws"; //$NON-NLS-1$
private static final String OS = "-os"; //$NON-NLS-1$
private static final String ARCH = "-arch"; //$NON-NLS-1$
private static final String NL = "-nl"; //$NON-NLS-1$
private static final String NL_EXTENSIONS = "-nlExtensions"; //$NON-NLS-1$
private static final String CONFIGURATION = "-configuration"; //$NON-NLS-1$
private static final String USER = "-user"; //$NON-NLS-1$
private static final String NOEXIT = "-noExit"; //$NON-NLS-1$
private static final String LAUNCHER = "-launcher"; //$NON-NLS-1$ // this is more of an Eclipse argument but this OSGi implementation stores its
// metadata alongside Eclipse's.
private static final String DATA = "-data"; //$NON-NLS-1$ // System properties
public static final String PROP_BUNDLES = "osgi.bundles"; //$NON-NLS-1$
public static final String PROP_BUNDLES_STARTLEVEL = "osgi.bundles.defaultStartLevel"; //$NON-NLS-1$ //The start level used to install the bundles
public static final String PROP_EXTENSIONS = "osgi.framework.extensions"; //$NON-NLS-1$
public static final String PROP_INITIAL_STARTLEVEL = "osgi.startLevel"; //$NON-NLS-1$ //The start level when the fwl start
public static final String PROP_DEBUG = "osgi.debug"; //$NON-NLS-1$
public static final String PROP_DEV = "osgi.dev"; //$NON-NLS-1$
public static final String PROP_CLEAN = "osgi.clean"; //$NON-NLS-1$
public static final String PROP_CONSOLE = "osgi.console"; //$NON-NLS-1$
public static final String PROP_CONSOLE_CLASS = "osgi.consoleClass"; //$NON-NLS-1$
public static final String PROP_CHECK_CONFIG = "osgi.checkConfiguration"; //$NON-NLS-1$
public static final String PROP_OS = "osgi.os"; //$NON-NLS-1$
public static final String PROP_WS = "osgi.ws"; //$NON-NLS-1$
public static final String PROP_NL = "osgi.nl"; //$NON-NLS-1$
private static final String PROP_NL_EXTENSIONS = "osgi.nl.extensions"; //$NON-NLS-1$
public static final String PROP_ARCH = "osgi.arch"; //$NON-NLS-1$
public static final String PROP_ADAPTOR = "osgi.adaptor"; //$NON-NLS-1$
public static final String PROP_SYSPATH = "osgi.syspath"; //$NON-NLS-1$
public static final String PROP_LOGFILE = "osgi.logfile"; //$NON-NLS-1$
public static final String PROP_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$
public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
public static final String PROP_FRAMEWORK_SHAPE = "osgi.framework.shape"; //$NON-NLS-1$ //the shape of the fwk (jar, or folder)
public static final String PROP_NOSHUTDOWN = "osgi.noShutdown"; //$NON-NLS-1$
private static final String PROP_FORCED_RESTART = "osgi.forcedRestart"; //$NON-NLS-1$ public static final String PROP_EXITCODE = "eclipse.exitcode"; //$NON-NLS-1$
public static final String PROP_EXITDATA = "eclipse.exitdata"; //$NON-NLS-1$
public static final String PROP_CONSOLE_LOG = "eclipse.consoleLog"; //$NON-NLS-1$
public static final String PROP_IGNOREAPP = "eclipse.ignoreApp"; //$NON-NLS-1$
public static final String PROP_REFRESH_BUNDLES = "eclipse.refreshBundles"; //$NON-NLS-1$
private static final String PROP_ALLOW_APPRELAUNCH = "eclipse.allowAppRelaunch"; //$NON-NLS-1$
private static final String PROP_APPLICATION_LAUNCHDEFAULT = "eclipse.application.launchDefault"; //$NON-NLS-1$ private static final String FILE_SCHEME = "file:"; //$NON-NLS-1$
private static final String REFERENCE_SCHEME = "reference:"; //$NON-NLS-1$
private static final String REFERENCE_PROTOCOL = "reference"; //$NON-NLS-1$
private static final String INITIAL_LOCATION = "initial@"; //$NON-NLS-1$
/** string containing the classname of the adaptor to be used in this framework instance */
protected static final String DEFAULT_ADAPTOR_CLASS = "org.eclipse.osgi.baseadaptor.BaseAdaptor"; //$NON-NLS-1$ private static final int DEFAULT_INITIAL_STARTLEVEL = 6; // default value for legacy purposes
private static final String DEFAULT_BUNDLES_STARTLEVEL = "4"; //$NON-NLS-1$ private static FrameworkLog log;
// directory of serch candidates keyed by directory abs path -> directory listing (bug 122024)
private static Map<String, String[]> searchCandidates = new HashMap<String, String[]>(4);
private static EclipseAppLauncher appLauncher;
private static List<Runnable> shutdownHandlers; private static ConsoleManager consoleMgr = null; /**
* This is the main to start osgi.
* It only works when the framework is being jared as a single jar
*/
public static void main(String[] args) throws Exception {
if (FrameworkProperties.getProperty("eclipse.startTime") == null) //$NON-NLS-1$
FrameworkProperties.setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis())); //$NON-NLS-1$
if (FrameworkProperties.getProperty(PROP_NOSHUTDOWN) == null)
FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
// set the compatibility boot delegation flag to false to get "standard" OSGi behavior WRT boot delegation (bug 178477)
if (FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION) == null)
FrameworkProperties.setProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
Object result = run(args, null);
if (result instanceof Integer && !Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
System.exit(((Integer) result).intValue());
} /**
* Launches the platform and runs a single application. The application is either identified
* in the given arguments (e.g., -application <app id>) or in the <code>eclipse.application</code>
* System property. This convenience method starts
* up the platform, runs the indicated application, and then shuts down the
* platform. The platform must not be running already.
*
* @param args the command line-style arguments used to configure the platform
* @param endSplashHandler the block of code to run to tear down the splash
* screen or <code>null</code> if no tear down is required
* @return the result of running the application
* @throws Exception if anything goes wrong
*/
public static Object run(String[] args, Runnable endSplashHandler) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.run()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
boolean startupFailed = true;
try {
startup(args, endSplashHandler);
startupFailed = false;
if (Boolean.valueOf(FrameworkProperties.getProperty(PROP_IGNOREAPP)).booleanValue() || isForcedRestart())
return null;
return run(null);
} catch (Throwable e) {
// ensure the splash screen is down
if (endSplashHandler != null)
endSplashHandler.run();
// may use startupFailed to understand where the error happened
FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, startupFailed ? EclipseAdaptorMsg.ECLIPSE_STARTUP_STARTUP_ERROR : EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
// TODO desperate measure - ideally, we should write this to disk (a la Main.log)
e.printStackTrace();
} finally {
try {
// The application typically sets the exit code however the framework can request that
// it be re-started. We need to check for this and potentially override the exit code.
if (isForcedRestart())
FrameworkProperties.setProperty(PROP_EXITCODE, "23"); //$NON-NLS-1$
if (!Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
shutdown();
} catch (Throwable e) {
FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_SHUTDOWN_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
// TODO desperate measure - ideally, we should write this to disk (a la Main.log)
e.printStackTrace();
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("EclipseStarter.run()"); //$NON-NLS-1$
if (Profile.PROFILE) {
String report = Profile.getProfileLog();
// avoiding writing to the console if there is nothing to print
if (report != null && report.length() > 0)
System.out.println(report);
}
}
// we only get here if an error happened
if (FrameworkProperties.getProperty(PROP_EXITCODE) == null) {
FrameworkProperties.setProperty(PROP_EXITCODE, "13"); //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_EXITDATA, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_CHECK_LOG, log == null ? null : log.getFile().getPath()));
}
return null;
} /**
* Returns true if the platform is already running, false otherwise.
* @return whether or not the platform is already running
*/
public static boolean isRunning() {
return running;
} /**
* Starts the platform and sets it up to run a single application. The application is either identified
* in the given arguments (e.g., -application <app id>) or in the <code>eclipse.application</code>
* System property. The platform must not be running already.
* <p>
* The given runnable (if not <code>null</code>) is used to tear down the splash screen if required.
* </p>
* @param args the arguments passed to the application
* @return BundleContext the context of the system bundle
* @throws Exception if anything goes wrong
*/
public static BundleContext startup(String[] args, Runnable endSplashHandler) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.startup()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
FrameworkProperties.initializeProperties();
processCommandLine(args);
LocationManager.initializeLocations();
loadConfigurationInfo();
finalizeProperties();
if (Profile.PROFILE)
Profile.initProps(); // catch any Profile properties set in eclipse.properties...
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "props inited"); //$NON-NLS-1$ //$NON-NLS-2$
adaptor = createAdaptor();
log = adaptor.getFrameworkLog();
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "adapter created"); //$NON-NLS-1$ //$NON-NLS-2$
framework = new Framework(adaptor);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "OSGi created"); //$NON-NLS-1$ //$NON-NLS-2$
context = framework.getBundle(0).getBundleContext();
registerFrameworkShutdownHandlers();
publishSplashScreen(endSplashHandler);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "osgi launched"); //$NON-NLS-1$ //$NON-NLS-2$
consoleMgr = ConsoleManager.startConsole(framework);
if (Profile.PROFILE && Profile.STARTUP) {
Profile.logTime("EclipseStarter.startup()", "console started"); //$NON-NLS-1$ //$NON-NLS-2$
}
framework.launch();
// save the cached timestamp before loading basic bundles; this is needed so we can do a proper timestamp check when logging resolver errors
long stateStamp = adaptor.getState().getTimeStamp();
Bundle[] startBundles = loadBasicBundles(); if (startBundles == null || ("true".equals(FrameworkProperties.getProperty(PROP_REFRESH_BUNDLES)) && refreshPackages(getCurrentBundles(false)))) { //$NON-NLS-1$
waitForShutdown();
return context; // cannot continue; loadBasicBundles caused refreshPackages to shutdown the framework
} if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "loading basic bundles"); //$NON-NLS-1$ //$NON-NLS-2$ // set the framework start level to the ultimate value. This will actually start things
// running if they are persistently active.
setStartLevel(getStartLevel());
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "StartLevel set"); //$NON-NLS-1$ //$NON-NLS-2$
// they should all be active by this time
ensureBundlesActive(startBundles); // in the case where the built-in console is disabled we should try to start the console bundle
try {
consoleMgr.checkForConsoleBundle();
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null);
log.log(entry);
}
if (debug || FrameworkProperties.getProperty(PROP_DEV) != null)
// only spend time showing unresolved bundles in dev/debug mode and the state has changed
if (stateStamp != adaptor.getState().getTimeStamp())
logUnresolvedBundles(context.getBundles());
running = true;
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("EclipseStarter.startup()"); //$NON-NLS-1$
return context;
} private static int getStartLevel() {
String level = FrameworkProperties.getProperty(PROP_INITIAL_STARTLEVEL);
if (level != null)
try {
return Integer.parseInt(level);
} catch (NumberFormatException e) {
if (debug)
System.out.println("Start level = " + level + " parsed. Using hardcoded default: 6"); //$NON-NLS-1$ //$NON-NLS-2$
}
return DEFAULT_INITIAL_STARTLEVEL;
} /**
* Runs the application for which the platform was started. The platform
* must be running.
* <p>
* The given argument is passed to the application being run. If it is <code>null</code>
* then the command line arguments used in starting the platform, and not consumed
* by the platform code, are passed to the application as a <code>String[]</code>.
* </p>
* @param argument the argument passed to the application. May be <code>null</code>
* @return the result of running the application
* @throws Exception if anything goes wrong
*/
public static Object run(Object argument) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.run(Object)()", null); //$NON-NLS-1$
if (!running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_NOT_RUNNING);
// if we are just initializing, do not run the application just return.
if (initialize)
return new Integer(0);
try {
if (appLauncher == null) {
boolean launchDefault = Boolean.valueOf(FrameworkProperties.getProperty(PROP_APPLICATION_LAUNCHDEFAULT, "true")).booleanValue(); //$NON-NLS-1$
// create the ApplicationLauncher and register it as a service
appLauncher = new EclipseAppLauncher(context, Boolean.valueOf(FrameworkProperties.getProperty(PROP_ALLOW_APPRELAUNCH)).booleanValue(), launchDefault, log);
appLauncherRegistration = context.registerService(ApplicationLauncher.class.getName(), appLauncher, null);
// must start the launcher AFTER service restration because this method
// blocks and runs the application on the current thread. This method
// will return only after the application has stopped.
return appLauncher.start(argument);
}
return appLauncher.reStart(argument);
} catch (Exception e) {
if (log != null && context != null) // context can be null if OSGi failed to launch (bug 151413)
logUnresolvedBundles(context.getBundles());
throw e;
}
} /**
* Shuts down the Platform. The state of the Platform is not automatically
* saved before shutting down.
* <p>
* On return, the Platform will no longer be running (but could be re-launched
* with another call to startup). If relaunching, care must be taken to reinitialize
* any System properties which the platform uses (e.g., osgi.instance.area) as
* some policies in the platform do not allow resetting of such properties on
* subsequent runs.
* </p><p>
* Any objects handed out by running Platform,
* including Platform runnables obtained via getRunnable, will be
* permanently invalid. The effects of attempting to invoke methods
* on invalid objects is undefined.
* </p>
* @throws Exception if anything goes wrong
*/
public static void shutdown() throws Exception {
if (!running || framework == null)
return;
if (appLauncherRegistration != null)
appLauncherRegistration.unregister();
if (splashStreamRegistration != null)
splashStreamRegistration.unregister();
if (defaultMonitorRegistration != null)
defaultMonitorRegistration.unregister();
if (appLauncher != null)
appLauncher.shutdown();
appLauncherRegistration = null;
appLauncher = null;
splashStreamRegistration = null;
defaultMonitorRegistration = null;
if (consoleMgr != null) {
consoleMgr.stopConsole();
consoleMgr = null;
}
framework.close();
framework = null;
context = null;
running = false;
} private static void ensureBundlesActive(Bundle[] bundles) {
ServiceTracker<StartLevel, StartLevel> tracker = null;
try {
for (int i = 0; i < bundles.length; i++) {
if (bundles[i].getState() != Bundle.ACTIVE) {
if (bundles[i].getState() == Bundle.INSTALLED) {
// Log that the bundle is not resolved
log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundles[i].getLocation()), 0, null, null));
continue;
}
// check that the startlevel allows the bundle to be active (111550)
if (tracker == null) {
tracker = new ServiceTracker<StartLevel, StartLevel>(context, StartLevel.class.getName(), null);
tracker.open();
}
StartLevel sl = tracker.getService();
if (sl != null && (sl.getBundleStartLevel(bundles[i]) <= sl.getStartLevel())) {
log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_ACTIVE, bundles[i]), 0, null, null));
}
}
}
} finally {
if (tracker != null)
tracker.close();
}
} private static void logUnresolvedBundles(Bundle[] bundles) {
State state = adaptor.getState();
FrameworkLog logService = adaptor.getFrameworkLog();
StateHelper stateHelper = adaptor.getPlatformAdmin().getStateHelper(); // first lets look for missing leaf constraints (bug 114120)
VersionConstraint[] leafConstraints = stateHelper.getUnsatisfiedLeaves(state.getBundles());
// hash the missing leaf constraints by the declaring bundles
Map<BundleDescription, List<VersionConstraint>> missing = new HashMap<BundleDescription, List<VersionConstraint>>();
for (int i = 0; i < leafConstraints.length; i++) {
// only include non-optional and non-dynamic constraint leafs
if (leafConstraints[i] instanceof BundleSpecification && ((BundleSpecification) leafConstraints[i]).isOptional())
continue;
if (leafConstraints[i] instanceof ImportPackageSpecification) {
if (ImportPackageSpecification.RESOLUTION_OPTIONAL.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE)))
continue;
if (ImportPackageSpecification.RESOLUTION_DYNAMIC.equals(((ImportPackageSpecification) leafConstraints[i]).getDirective(Constants.RESOLUTION_DIRECTIVE)))
continue;
}
BundleDescription bundle = leafConstraints[i].getBundle();
List<VersionConstraint> constraints = missing.get(bundle);
if (constraints == null) {
constraints = new ArrayList<VersionConstraint>();
missing.put(bundle, constraints);
}
constraints.add(leafConstraints[i]);
} // found some bundles with missing leaf constraints; log them first
if (missing.size() > 0) {
FrameworkLogEntry[] rootChildren = new FrameworkLogEntry[missing.size()];
int rootIndex = 0;
for (Iterator<BundleDescription> iter = missing.keySet().iterator(); iter.hasNext(); rootIndex++) {
BundleDescription description = iter.next();
String symbolicName = description.getSymbolicName() == null ? FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME : description.getSymbolicName();
String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, description.getLocation());
List<VersionConstraint> constraints = missing.get(description);
FrameworkLogEntry[] logChildren = new FrameworkLogEntry[constraints.size()];
for (int i = 0; i < logChildren.length; i++)
logChildren[i] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, MessageHelper.getResolutionFailureMessage(constraints.get(i)), 0, null, null);
rootChildren[rootIndex] = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, generalMessage, 0, null, logChildren);
}
logService.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_ROOTS_NOT_RESOLVED, 0, null, rootChildren));
} // There may be some bundles unresolved for other reasons, causing the system to be unresolved
// log all unresolved constraints now
List<FrameworkLogEntry> allChildren = new ArrayList<FrameworkLogEntry>();
for (int i = 0; i < bundles.length; i++)
if (bundles[i].getState() == Bundle.INSTALLED) {
String symbolicName = bundles[i].getSymbolicName() == null ? FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME : bundles[i].getSymbolicName();
String generalMessage = NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundles[i]);
BundleDescription description = state.getBundle(bundles[i].getBundleId());
// for some reason, the state does not know about that bundle
if (description == null)
continue;
FrameworkLogEntry[] logChildren = null;
VersionConstraint[] unsatisfied = stateHelper.getUnsatisfiedConstraints(description);
if (unsatisfied.length > 0) {
// the bundle wasn't resolved due to some of its constraints were unsatisfiable
logChildren = new FrameworkLogEntry[unsatisfied.length];
for (int j = 0; j < unsatisfied.length; j++)
logChildren[j] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, MessageHelper.getResolutionFailureMessage(unsatisfied[j]), 0, null, null);
} else {
ResolverError[] resolverErrors = state.getResolverErrors(description);
if (resolverErrors.length > 0) {
logChildren = new FrameworkLogEntry[resolverErrors.length];
for (int j = 0; j < resolverErrors.length; j++)
logChildren[j] = new FrameworkLogEntry(symbolicName, FrameworkLogEntry.WARNING, 0, resolverErrors[j].toString(), 0, null, null);
}
} allChildren.add(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, generalMessage, 0, null, logChildren));
}
if (allChildren.size() > 0)
logService.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.WARNING, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_ALL_NOT_RESOLVED, 0, null, allChildren.toArray(new FrameworkLogEntry[allChildren.size()])));
} private static void publishSplashScreen(final Runnable endSplashHandler) {
if (endSplashHandler == null)
return;
// register the output stream to the launcher if it exists
try {
Method method = endSplashHandler.getClass().getMethod("getOutputStream", new Class[0]); //$NON-NLS-1$
Object outputStream = method.invoke(endSplashHandler, new Object[0]);
if (outputStream instanceof OutputStream) {
Dictionary<String, Object> osProperties = new Hashtable<String, Object>();
osProperties.put("name", "splashstream"); //$NON-NLS-1$//$NON-NLS-2$
splashStreamRegistration = context.registerService(OutputStream.class.getName(), outputStream, osProperties);
}
} catch (Exception ex) {
// ignore
}
// keep this splash handler as the default startup monitor
try {
Dictionary<String, Object> monitorProps = new Hashtable<String, Object>();
monitorProps.put(Constants.SERVICE_RANKING, new Integer(Integer.MIN_VALUE));
defaultMonitorRegistration = context.registerService(StartupMonitor.class.getName(), new DefaultStartupMonitor(endSplashHandler), monitorProps);
} catch (IllegalStateException e) {
//splash handler did not provide the necessary methods, ignore it
}
} @SuppressWarnings("deprecation")
private static URL searchForBundle(String name, String parent) throws MalformedURLException {
URL url = null;
File fileLocation = null;
boolean reference = false;
try {
new URL(name); // quick check to see if the name is a valid URL
url = new URL(new File(parent).toURL(), name);
} catch (MalformedURLException e) {
// TODO this is legacy support for non-URL names. It should be removed eventually.
// if name was not a URL then construct one.
// Assume it should be a reference and that it is relative. This support need not
// be robust as it is temporary..
File child = new File(name);
fileLocation = child.isAbsolute() ? child : new File(parent, name);
url = new URL(REFERENCE_PROTOCOL, null, fileLocation.toURL().toExternalForm());
reference = true;
}
// if the name was a URL then see if it is relative. If so, insert syspath.
if (!reference) {
URL baseURL = url;
// if it is a reference URL then strip off the reference: and set base to the file:...
if (url.getProtocol().equals(REFERENCE_PROTOCOL)) {
reference = true;
String baseSpec = url.getFile();
if (baseSpec.startsWith(FILE_SCHEME)) {
File child = new File(baseSpec.substring(5));
baseURL = child.isAbsolute() ? child.toURL() : new File(parent, child.getPath()).toURL();
} else
baseURL = new URL(baseSpec);
} fileLocation = new File(baseURL.getFile());
// if the location is relative, prefix it with the parent
if (!fileLocation.isAbsolute())
fileLocation = new File(parent, fileLocation.toString());
}
// If the result is a reference then search for the real result and
// reconstruct the answer.
if (reference) {
String result = searchFor(fileLocation.getName(), new File(fileLocation.getParent()).getAbsolutePath());
if (result != null)
url = new URL(REFERENCE_PROTOCOL, null, FILE_SCHEME + result);
else
return null;
} // finally we have something worth trying
try {
URLConnection result = url.openConnection();
result.connect();
return url;
} catch (IOException e) {
// int i = location.lastIndexOf('_');
// return i == -1? location : location.substring(0, i);
return null;
}
} /*
* Ensure all basic bundles are installed, resolved and scheduled to start. Returns an array containing
* all basic bundles that are marked to start.
* Returns null if the framework has been shutdown as a result of refreshPackages
*/
private static Bundle[] loadBasicBundles() {
long startTime = System.currentTimeMillis();
String osgiBundles = FrameworkProperties.getProperty(PROP_BUNDLES);
String osgiExtensions = FrameworkProperties.getProperty(PROP_EXTENSIONS);
if (osgiExtensions != null && osgiExtensions.length() > 0) {
osgiBundles = osgiExtensions + ',' + osgiBundles;
FrameworkProperties.setProperty(PROP_BUNDLES, osgiBundles);
}
String[] installEntries = getArrayFromList(osgiBundles, ","); //$NON-NLS-1$
// get the initial bundle list from the installEntries
InitialBundle[] initialBundles = getInitialBundles(installEntries);
// get the list of currently installed initial bundles from the framework
Bundle[] curInitBundles = getCurrentBundles(true); // list of bundles to be refreshed
List<Bundle> toRefresh = new ArrayList<Bundle>(curInitBundles.length);
// uninstall any of the currently installed bundles that do not exist in the
// initial bundle list from installEntries.
uninstallBundles(curInitBundles, initialBundles, toRefresh); // install the initialBundles that are not already installed.
List<Bundle> startBundles = new ArrayList<Bundle>(installEntries.length);
List<Bundle> lazyActivationBundles = new ArrayList<Bundle>(installEntries.length);
installBundles(initialBundles, curInitBundles, startBundles, lazyActivationBundles, toRefresh); // If we installed/uninstalled something, force a refresh of all installed/uninstalled bundles
if (!toRefresh.isEmpty() && refreshPackages(toRefresh.toArray(new Bundle[toRefresh.size()])))
return null; // cannot continue; refreshPackages shutdown the framework // schedule all basic bundles to be started
Bundle[] startInitBundles = startBundles.toArray(new Bundle[startBundles.size()]);
Bundle[] lazyInitBundles = lazyActivationBundles.toArray(new Bundle[lazyActivationBundles.size()]);
startBundles(startInitBundles, lazyInitBundles); if (debug)
System.out.println("Time to load bundles: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
return startInitBundles;
} private static InitialBundle[] getInitialBundles(String[] installEntries) {
searchCandidates.clear();
List<InitialBundle> result = new ArrayList<InitialBundle>(installEntries.length);
int defaultStartLevel = Integer.parseInt(FrameworkProperties.getProperty(PROP_BUNDLES_STARTLEVEL, DEFAULT_BUNDLES_STARTLEVEL));
String syspath = getSysPath();
// should canonicalize the syspath.
try {
syspath = new File(syspath).getCanonicalPath();
} catch (IOException ioe) {
// do nothing
}
for (int i = 0; i < installEntries.length; i++) {
String name = installEntries[i];
int level = defaultStartLevel;
boolean start = false;
int index = name.lastIndexOf('@');
if (index >= 0) {
String[] attributes = getArrayFromList(name.substring(index + 1, name.length()), ":"); //$NON-NLS-1$
for (int j = 0; j < attributes.length; j++) {
String attribute = attributes[j];
if (attribute.equals("start")) //$NON-NLS-1$
start = true;
else {
try {
level = Integer.parseInt(attribute);
} catch (NumberFormatException e) { // bug 188089
index = name.length();
continue;
}
}
}
name = name.substring(0, index);
}
try {
URL location = searchForBundle(name, syspath);
if (location == null) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_BUNDLE_NOT_FOUND, installEntries[i]), 0, null, null);
log.log(entry);
// skip this entry
continue;
}
location = makeRelative(LocationManager.getInstallLocation().getURL(), location);
String locationString = INITIAL_LOCATION + location.toExternalForm();
result.add(new InitialBundle(locationString, location, level, start));
} catch (IOException e) {
log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
}
}
return result.toArray(new InitialBundle[result.size()]);
} // returns true if the refreshPackages operation caused the framework to shutdown
private static boolean refreshPackages(Bundle[] bundles) {
ServiceReference<?> packageAdminRef = context.getServiceReference(PackageAdmin.class.getName());
PackageAdmin packageAdmin = null;
if (packageAdminRef != null)
packageAdmin = (PackageAdmin) context.getService(packageAdminRef);
if (packageAdmin == null)
return false;
// TODO this is such a hack it is silly. There are still cases for race conditions etc
// but this should allow for some progress...
final Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.PACKAGES_REFRESHED);
context.addFrameworkListener(listener);
context.addBundleListener(listener);
packageAdmin.refreshPackages(bundles);
context.ungetService(packageAdminRef);
updateSplash(semaphore, listener);
if (isForcedRestart())
return true;
return false;
} private static void waitForShutdown() {
if (!isForcedRestart())
return;
// wait for the system bundle to stop
Bundle systemBundle = framework.getBundle(0);
int i = 0;
while (i < 5000 && (systemBundle.getState() & (Bundle.STARTING | Bundle.ACTIVE | Bundle.STOPPING)) != 0) {
i += 200;
try {
Thread.sleep(200);
} catch (InterruptedException e) {
break;
}
}
} /**
* Creates and returns the adaptor
*
* @return a FrameworkAdaptor object
*/
private static FrameworkAdaptor createAdaptor() throws Exception {
String adaptorClassName = FrameworkProperties.getProperty(PROP_ADAPTOR, DEFAULT_ADAPTOR_CLASS);
Class<?> adaptorClass = Class.forName(adaptorClassName);
Class<?>[] constructorArgs = new Class[] {String[].class};
Constructor<?> constructor = adaptorClass.getConstructor(constructorArgs);
return (FrameworkAdaptor) constructor.newInstance(new Object[] {new String[0]});
} private static String[] processCommandLine(String[] args) throws Exception {
EclipseEnvironmentInfo.setAllArgs(args);
if (args.length == 0) {
EclipseEnvironmentInfo.setFrameworkArgs(args);
EclipseEnvironmentInfo.setAllArgs(args);
return args;
}
int[] configArgs = new int[args.length];
configArgs[0] = -1; // need to initialize the first element to something that could not be an index.
int configArgIndex = 0;
for (int i = 0; i < args.length; i++) {
boolean found = false;
// check for args without parameters (i.e., a flag arg) // check if debug should be enabled for the entire platform
// If this is the last arg or there is a following arg (i.e., arg+1 has a leading -),
// simply enable debug. Otherwise, assume that that the following arg is
// actually the filename of an options file. This will be processed below.
if (args[i].equalsIgnoreCase(DEBUG) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_DEBUG, ""); //$NON-NLS-1$
debug = true;
found = true;
} // check if development mode should be enabled for the entire platform
// If this is the last arg or there is a following arg (i.e., arg+1 has a leading -),
// simply enable development mode. Otherwise, assume that that the following arg is
// actually some additional development time class path entries. This will be processed below.
if (args[i].equalsIgnoreCase(DEV) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_DEV, ""); //$NON-NLS-1$
found = true;
} // look for the initialization arg
if (args[i].equalsIgnoreCase(INITIALIZE)) {
initialize = true;
found = true;
} // look for the clean flag.
if (args[i].equalsIgnoreCase(CLEAN)) {
FrameworkProperties.setProperty(PROP_CLEAN, "true"); //$NON-NLS-1$
found = true;
} // look for the consoleLog flag
if (args[i].equalsIgnoreCase(CONSOLE_LOG)) {
FrameworkProperties.setProperty(PROP_CONSOLE_LOG, "true"); //$NON-NLS-1$
found = true;
} // look for the console with no port.
if (args[i].equalsIgnoreCase(CONSOLE) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_CONSOLE, ""); //$NON-NLS-1$
found = true;
} if (args[i].equalsIgnoreCase(NOEXIT)) {
FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
found = true;
} if (found) {
configArgs[configArgIndex++] = i;
continue;
}
// check for args with parameters. If we are at the last argument or if the next one
// has a '-' as the first character, then we can't have an arg with a parm so continue.
if (i == args.length - 1 || args[i + 1].startsWith("-")) { //$NON-NLS-1$
continue;
}
String arg = args[++i]; // look for the console and port.
if (args[i - 1].equalsIgnoreCase(CONSOLE)) {
FrameworkProperties.setProperty(PROP_CONSOLE, arg);
found = true;
} // look for the configuration location .
if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
FrameworkProperties.setProperty(LocationManager.PROP_CONFIG_AREA, arg);
found = true;
} // look for the data location for this instance.
if (args[i - 1].equalsIgnoreCase(DATA)) {
FrameworkProperties.setProperty(LocationManager.PROP_INSTANCE_AREA, arg);
found = true;
} // look for the user location for this instance.
if (args[i - 1].equalsIgnoreCase(USER)) {
FrameworkProperties.setProperty(LocationManager.PROP_USER_AREA, arg);
found = true;
} // look for the launcher location
if (args[i - 1].equalsIgnoreCase(LAUNCHER)) {
FrameworkProperties.setProperty(LocationManager.PROP_LAUNCHER, arg);
found = true;
}
// look for the development mode and class path entries.
if (args[i - 1].equalsIgnoreCase(DEV)) {
FrameworkProperties.setProperty(PROP_DEV, arg);
found = true;
} // look for the debug mode and option file location.
if (args[i - 1].equalsIgnoreCase(DEBUG)) {
FrameworkProperties.setProperty(PROP_DEBUG, arg);
debug = true;
found = true;
} // look for the window system.
if (args[i - 1].equalsIgnoreCase(WS)) {
FrameworkProperties.setProperty(PROP_WS, arg);
found = true;
} // look for the operating system
if (args[i - 1].equalsIgnoreCase(OS)) {
FrameworkProperties.setProperty(PROP_OS, arg);
found = true;
} // look for the system architecture
if (args[i - 1].equalsIgnoreCase(ARCH)) {
FrameworkProperties.setProperty(PROP_ARCH, arg);
found = true;
} // look for the nationality/language
if (args[i - 1].equalsIgnoreCase(NL)) {
FrameworkProperties.setProperty(PROP_NL, arg);
found = true;
} // look for the locale extensions
if (args[i - 1].equalsIgnoreCase(NL_EXTENSIONS)) {
FrameworkProperties.setProperty(PROP_NL_EXTENSIONS, arg);
found = true;
} // done checking for args. Remember where an arg was found
if (found) {
configArgs[configArgIndex++] = i - 1;
configArgs[configArgIndex++] = i;
}
} // remove all the arguments consumed by this argument parsing
if (configArgIndex == 0) {
EclipseEnvironmentInfo.setFrameworkArgs(new String[0]);
EclipseEnvironmentInfo.setAppArgs(args);
return args;
}
String[] appArgs = new String[args.length - configArgIndex];
String[] frameworkArgs = new String[configArgIndex];
configArgIndex = 0;
int j = 0;
int k = 0;
for (int i = 0; i < args.length; i++) {
if (i == configArgs[configArgIndex]) {
frameworkArgs[k++] = args[i];
configArgIndex++;
} else
appArgs[j++] = args[i];
}
EclipseEnvironmentInfo.setFrameworkArgs(frameworkArgs);
EclipseEnvironmentInfo.setAppArgs(appArgs);
return appArgs;
} /**
* Returns the result of converting a list of comma-separated tokens into an array
*
* @return the array of string tokens
* @param prop the initial comma-separated string
*/
private static String[] getArrayFromList(String prop, String separator) {
return ManifestElement.getArrayFromList(prop, separator);
} protected static String getSysPath() {
String result = FrameworkProperties.getProperty(PROP_SYSPATH);
if (result != null)
return result;
result = getSysPathFromURL(FrameworkProperties.getProperty(PROP_FRAMEWORK));
if (result == null)
result = getSysPathFromCodeSource();
if (result == null)
throw new IllegalStateException("Can not find the system path."); //$NON-NLS-1$
if (Character.isUpperCase(result.charAt(0))) {
char[] chars = result.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
result = new String(chars);
}
FrameworkProperties.setProperty(PROP_SYSPATH, result);
return result;
} private static String getSysPathFromURL(String urlSpec) {
if (urlSpec == null)
return null;
URL url = LocationHelper.buildURL(urlSpec, false);
if (url == null)
return null;
File fwkFile = new File(url.getFile());
fwkFile = new File(fwkFile.getAbsolutePath());
fwkFile = new File(fwkFile.getParent());
return fwkFile.getAbsolutePath();
} private static String getSysPathFromCodeSource() {
ProtectionDomain pd = EclipseStarter.class.getProtectionDomain();
if (pd == null)
return null;
CodeSource cs = pd.getCodeSource();
if (cs == null)
return null;
URL url = cs.getLocation();
if (url == null)
return null;
String result = url.getFile();
if (result.endsWith(".jar")) { //$NON-NLS-1$
result = result.substring(0, result.lastIndexOf('/'));
if ("folder".equals(FrameworkProperties.getProperty(PROP_FRAMEWORK_SHAPE))) //$NON-NLS-1$
result = result.substring(0, result.lastIndexOf('/'));
} else {
if (result.endsWith("/")) //$NON-NLS-1$
result = result.substring(0, result.length() - 1);
result = result.substring(0, result.lastIndexOf('/'));
result = result.substring(0, result.lastIndexOf('/'));
}
return result;
} private static Bundle[] getCurrentBundles(boolean includeInitial) {
Bundle[] installed = context.getBundles();
List<Bundle> initial = new ArrayList<Bundle>();
for (int i = 0; i < installed.length; i++) {
Bundle bundle = installed[i];
if (bundle.getLocation().startsWith(INITIAL_LOCATION)) {
if (includeInitial)
initial.add(bundle);
} else if (!includeInitial && bundle.getBundleId() != 0)
initial.add(bundle);
}
return initial.toArray(new Bundle[initial.size()]);
} private static Bundle getBundleByLocation(String location, Bundle[] bundles) {
for (int i = 0; i < bundles.length; i++) {
Bundle bundle = bundles[i];
if (location.equalsIgnoreCase(bundle.getLocation()))
return bundle;
}
return null;
} private static void uninstallBundles(Bundle[] curInitBundles, InitialBundle[] newInitBundles, List<Bundle> toRefresh) {
for (int i = 0; i < curInitBundles.length; i++) {
boolean found = false;
for (int j = 0; j < newInitBundles.length; j++) {
if (curInitBundles[i].getLocation().equalsIgnoreCase(newInitBundles[j].locationString)) {
found = true;
break;
}
}
if (!found)
try {
curInitBundles[i].uninstall();
toRefresh.add(curInitBundles[i]);
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_UNINSTALL, curInitBundles[i].getLocation()), 0, e, null);
log.log(entry);
}
}
} private static void installBundles(InitialBundle[] initialBundles, Bundle[] curInitBundles, List<Bundle> startBundles, List<Bundle> lazyActivationBundles, List<Bundle> toRefresh) {
ServiceReference<?> reference = context.getServiceReference(StartLevel.class.getName());
StartLevel startService = null;
if (reference != null)
startService = (StartLevel) context.getService(reference);
try {
for (int i = 0; i < initialBundles.length; i++) {
Bundle osgiBundle = getBundleByLocation(initialBundles[i].locationString, curInitBundles);
try {
// don't need to install if it is already installed
if (osgiBundle == null) {
InputStream in = initialBundles[i].location.openStream();
try {
osgiBundle = context.installBundle(initialBundles[i].locationString, in);
} catch (BundleException e) {
StatusException status = e instanceof StatusException ? (StatusException) e : null;
if (status != null && status.getStatusCode() == StatusException.CODE_OK && status.getStatus() instanceof Bundle) {
osgiBundle = (Bundle) status.getStatus();
} else
throw e;
}
// only check for lazy activation header if this is a newly installed bundle and is not marked for persistent start
if (!initialBundles[i].start && hasLazyActivationPolicy(osgiBundle))
lazyActivationBundles.add(osgiBundle);
}
// always set the startlevel incase it has changed (bug 111549)
// this is a no-op if the level is the same as previous launch.
if ((osgiBundle.getState() & Bundle.UNINSTALLED) == 0 && initialBundles[i].level >= 0 && startService != null)
startService.setBundleStartLevel(osgiBundle, initialBundles[i].level);
// if this bundle is supposed to be started then add it to the start list
if (initialBundles[i].start)
startBundles.add(osgiBundle);
// include basic bundles in case they were not resolved before
if ((osgiBundle.getState() & Bundle.INSTALLED) != 0)
toRefresh.add(osgiBundle);
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
log.log(entry);
} catch (IOException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundles[i].location), 0, e, null);
log.log(entry);
}
}
} finally {
if (reference != null)
context.ungetService(reference);
}
} @SuppressWarnings("deprecation")
private static boolean hasLazyActivationPolicy(Bundle target) {
// check the bundle manifest to see if it defines a lazy activation policy
Dictionary<String, String> headers = target.getHeaders(""); //$NON-NLS-1$
// first check to see if this is a fragment bundle
String fragmentHost = headers.get(Constants.FRAGMENT_HOST);
if (fragmentHost != null)
return false; // do not activate fragment bundles
// look for the OSGi defined Bundle-ActivationPolicy header
String activationPolicy = headers.get(Constants.BUNDLE_ACTIVATIONPOLICY);
try {
if (activationPolicy != null) {
ManifestElement[] elements = ManifestElement.parseHeader(Constants.BUNDLE_ACTIVATIONPOLICY, activationPolicy);
if (elements != null && elements.length > 0) {
// if the value is "lazy" then it has a lazy activation poliyc
if (Constants.ACTIVATION_LAZY.equals(elements[0].getValue()))
return true;
}
} else {
// check for Eclipse specific lazy start headers "Eclipse-LazyStart" and "Eclipse-AutoStart"
String eclipseLazyStart = headers.get(Constants.ECLIPSE_LAZYSTART);
if (eclipseLazyStart == null)
eclipseLazyStart = headers.get(Constants.ECLIPSE_AUTOSTART);
ManifestElement[] elements = ManifestElement.parseHeader(Constants.ECLIPSE_LAZYSTART, eclipseLazyStart);
if (elements != null && elements.length > 0) {
// if the value is true then it is lazy activated
if ("true".equals(elements[0].getValue())) //$NON-NLS-1$
return true;
// otherwise it is only lazy activated if it defines an exceptions directive.
else if (elements[0].getDirective("exceptions") != null) //$NON-NLS-1$
return true;
}
}
} catch (BundleException be) {
// ignore this
}
return false;
} private static void startBundles(Bundle[] startBundles, Bundle[] lazyBundles) {
for (int i = 0; i < startBundles.length; i++)
startBundle(startBundles[i], 0);
for (int i = 0; i < lazyBundles.length; i++)
startBundle(lazyBundles[i], Bundle.START_ACTIVATION_POLICY);
} private static void startBundle(Bundle bundle, int options) {
try {
bundle.start(options);
} catch (BundleException e) {
if ((bundle.getState() & Bundle.RESOLVED) != 0) {
// only log errors if the bundle is resolved
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
log.log(entry);
}
}
} private static void loadConfigurationInfo() {
Location configArea = LocationManager.getConfigurationLocation();
if (configArea == null)
return; URL location = null;
try {
location = new URL(configArea.getURL().toExternalForm() + LocationManager.CONFIG_FILE);
} catch (MalformedURLException e) {
// its ok. This should never happen
}
mergeProperties(FrameworkProperties.getProperties(), loadProperties(location));
} private static Properties loadProperties(URL location) {
Properties result = new Properties();
if (location == null)
return result;
try {
InputStream in = location.openStream();
try {
result.load(in);
} finally {
in.close();
}
} catch (IOException e) {
// its ok if there is no file. We'll just use the defaults for everything
// TODO but it might be nice to log something with gentle wording (i.e., it is not an error)
}
return substituteVars(result);
} private static Properties substituteVars(Properties result) {
if (result == null) {
//nothing todo.
return null;
}
for (Enumeration<Object> eKeys = result.keys(); eKeys.hasMoreElements();) {
Object key = eKeys.nextElement();
if (key instanceof String) {
String value = result.getProperty((String) key);
if (value != null)
result.put(key, BaseStorageHook.substituteVars(value));
}
}
return result;
} /**
* Returns a URL which is equivalent to the given URL relative to the
* specified base URL. Works only for file: URLs
* @throws MalformedURLException
*/
private static URL makeRelative(URL base, URL location) throws MalformedURLException {
if (base == null)
return location;
if (!"file".equals(base.getProtocol())) //$NON-NLS-1$
return location;
if (!location.getProtocol().equals(REFERENCE_PROTOCOL))
return location; // we can only make reference urls relative
URL nonReferenceLocation = new URL(location.getPath());
// if some URL component does not match, return the original location
if (!base.getProtocol().equals(nonReferenceLocation.getProtocol()))
return location;
File locationPath = new File(nonReferenceLocation.getPath());
// if location is not absolute, return original location
if (!locationPath.isAbsolute())
return location;
File relativePath = makeRelative(new File(base.getPath()), locationPath);
String urlPath = relativePath.getPath();
if (File.separatorChar != '/')
urlPath = urlPath.replace(File.separatorChar, '/');
if (nonReferenceLocation.getPath().endsWith("/")) //$NON-NLS-1$
// restore original trailing slash
urlPath += '/';
// couldn't use File to create URL here because it prepends the path with user.dir
URL relativeURL = new URL(base.getProtocol(), base.getHost(), base.getPort(), urlPath);
// now make it back to a reference URL
relativeURL = new URL(REFERENCE_SCHEME + relativeURL.toExternalForm());
return relativeURL;
} private static File makeRelative(File base, File location) {
if (!location.isAbsolute())
return location;
File relative = new File(new FilePath(base).makeRelative(new FilePath(location)));
return relative;
} private static void mergeProperties(Properties destination, Properties source) {
for (Enumeration<?> e = source.keys(); e.hasMoreElements();) {
String key = (String) e.nextElement();
String value = source.getProperty(key);
if (destination.getProperty(key) == null)
destination.setProperty(key, value);
}
} private static void setStartLevel(final int value) {
ServiceReference<?> reference = context.getServiceReference(StartLevel.class.getName());
final StartLevel startLevel = reference != null ? (StartLevel) context.getService(reference) : null;
if (startLevel == null)
return;
final Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.STARTLEVEL_CHANGED);
context.addFrameworkListener(listener);
context.addBundleListener(listener);
startLevel.setStartLevel(value);
context.ungetService(reference);
updateSplash(semaphore, listener);
} static class StartupEventListener implements SynchronousBundleListener, FrameworkListener {
private final Semaphore semaphore;
private final int frameworkEventType; public StartupEventListener(Semaphore semaphore, int frameworkEventType) {
this.semaphore = semaphore;
this.frameworkEventType = frameworkEventType;
} public void bundleChanged(BundleEvent event) {
if (event.getBundle().getBundleId() == 0 && event.getType() == BundleEvent.STOPPING)
semaphore.release();
} public void frameworkEvent(FrameworkEvent event) {
if (event.getType() == frameworkEventType)
semaphore.release();
} } private static void updateSplash(Semaphore semaphore, StartupEventListener listener) {
ServiceTracker<StartupMonitor, StartupMonitor> monitorTracker = new ServiceTracker<StartupMonitor, StartupMonitor>(context, StartupMonitor.class.getName(), null);
monitorTracker.open();
try {
while (true) {
StartupMonitor monitor = monitorTracker.getService();
if (monitor != null) {
try {
monitor.update();
} catch (Throwable e) {
// ignore exceptions thrown by the monitor
}
}
// can we acquire the semaphore yet?
if (semaphore.acquire(50))
break; //done
//else still working, spin another update
}
} finally {
if (listener != null) {
context.removeFrameworkListener(listener);
context.removeBundleListener(listener);
}
monitorTracker.close();
}
} /**
* Searches for the given target directory immediately under
* the given start location. If one is found then this location is returned;
* otherwise an exception is thrown.
*
* @return the location where target directory was found
* @param start the location to begin searching
*/
private static String searchFor(final String target, String start) {
String[] candidates = searchCandidates.get(start);
if (candidates == null) {
File startFile = new File(start);
// Pre-check if file exists, if not, and it contains escape characters,
// try decoding the path
if (!startFile.exists() && start.indexOf('%') >= 0) {
String decodePath = FrameworkProperties.decode(start);
File f = new File(decodePath);
if (f.exists())
startFile = f;
}
candidates = startFile.list();
if (candidates != null)
searchCandidates.put(start, candidates);
}
if (candidates == null)
return null;
String result = null;
Object[] maxVersion = null;
boolean resultIsFile = false;
for (int i = 0; i < candidates.length; i++) {
String candidateName = candidates[i];
if (!candidateName.startsWith(target))
continue;
boolean simpleJar = false;
final char versionSep = candidateName.length() > target.length() ? candidateName.charAt(target.length()) : 0;
if (candidateName.length() > target.length() && versionSep != '_' && versionSep != '-') {
// make sure this is not just a jar with no (_|-)version tacked on the end
if (candidateName.length() == 4 + target.length() && candidateName.endsWith(".jar")) //$NON-NLS-1$
simpleJar = true;
else
// name does not match the target properly with an (_|-) version at the end
continue;
}
// Note: directory with version suffix is always > than directory without version suffix
String version = candidateName.length() > target.length() + 1 && (versionSep == '_' || versionSep == '-') ? candidateName.substring(target.length() + 1) : ""; //$NON-NLS-1$
Object[] currentVersion = getVersionElements(version);
if (currentVersion != null && compareVersion(maxVersion, currentVersion) < 0) {
File candidate = new File(start, candidateName);
boolean candidateIsFile = candidate.isFile();
// if simple jar; make sure it is really a file before accepting it
if (!simpleJar || candidateIsFile) {
result = candidate.getAbsolutePath();
resultIsFile = candidateIsFile;
maxVersion = currentVersion;
}
}
}
if (result == null)
return null;
return result.replace(File.separatorChar, '/') + (resultIsFile ? "" : "/"); //$NON-NLS-1$ //$NON-NLS-2$
} /**
* Do a quick parse of version identifier so its elements can be correctly compared.
* If we are unable to parse the full version, remaining elements are initialized
* with suitable defaults.
* @return an array of size 4; first three elements are of type Integer (representing
* major, minor and service) and the fourth element is of type String (representing
* qualifier). A value of null is returned if there are no valid Integers. Note, that
* returning anything else will cause exceptions in the caller.
*/
private static Object[] getVersionElements(String version) {
Object[] result = {new Integer(-1), new Integer(-1), new Integer(-1), ""}; //$NON-NLS-1$
StringTokenizer t = new StringTokenizer(version, "."); //$NON-NLS-1$
String token;
for (int i = 0; t.hasMoreTokens() && i < 4; i++) {
token = t.nextToken();
if (i < 3) {
// major, minor or service ... numeric values
try {
result[i] = new Integer(token);
} catch (Exception e) {
if (i == 0)
return null; // return null if no valid numbers are present
// invalid number format - use default numbers (-1) for the rest
break;
}
} else {
// qualifier ... string value
result[i] = token;
}
}
return result;
} /**
* Compares version strings.
* @return result of comparison, as integer;
* <code><0</code> if left < right;
* <code>0</code> if left == right;
* <code>>0</code> if left > right;
*/
private static int compareVersion(Object[] left, Object[] right) {
if (left == null)
return -1;
int result = ((Integer) left[0]).compareTo((Integer) right[0]); // compare major
if (result != 0)
return result; result = ((Integer) left[1]).compareTo((Integer) right[1]); // compare minor
if (result != 0)
return result; result = ((Integer) left[2]).compareTo((Integer) right[2]); // compare service
if (result != 0)
return result; return ((String) left[3]).compareTo((String) right[3]); // compare qualifier
} private static void finalizeProperties() {
// if check config is unknown and we are in dev mode,
if (FrameworkProperties.getProperty(PROP_DEV) != null && FrameworkProperties.getProperty(PROP_CHECK_CONFIG) == null)
FrameworkProperties.setProperty(PROP_CHECK_CONFIG, "true"); //$NON-NLS-1$
} private static class InitialBundle {
public final String locationString;
public final URL location;
public final int level;
public final boolean start; InitialBundle(String locationString, URL location, int level, boolean start) {
this.locationString = locationString;
this.location = location;
this.level = level;
this.start = start;
}
} /**
* Sets the initial properties for the platform.
* This method must be called before calling the {@link #run(String[], Runnable)} or
* {@link #startup(String[], Runnable)} methods for the properties to be used in
* a launched instance of the platform.
* <p>
* If the specified properties contains a null value then the key for that value
* will be cleared from the properties of the platform.
* </p>
* @param initialProperties the initial properties to set for the platform.
* @since 3.2
*/
public static void setInitialProperties(Map<String, String> initialProperties) {
if (initialProperties == null || initialProperties.isEmpty())
return;
for (Map.Entry<String, String> entry : initialProperties.entrySet()) {
if (entry.getValue() != null)
FrameworkProperties.setProperty(entry.getKey(), entry.getValue());
else
FrameworkProperties.clearProperty(entry.getKey());
}
} /**
* Returns the context of the system bundle. A value of
* <code>null</code> is returned if the platform is not running.
* @return the context of the system bundle
* @throws java.lang.SecurityException If the caller does not have the
* appropriate <code>AdminPermission[system.bundle,CONTEXT]</code>, and
* the Java Runtime Environment supports permissions.
*/
public static BundleContext getSystemBundleContext() {
if (context == null || !running)
return null;
return context.getBundle().getBundleContext();
} private static boolean isForcedRestart() {
return Boolean.valueOf(FrameworkProperties.getProperty(PROP_FORCED_RESTART)).booleanValue();
} /*
* NOTE: This is an internal/experimental method used by launchers that need to react when the framework
* is shutdown internally.
*
* Adds a framework shutdown handler. <p>
* A handler implements the {@link Runnable} interface. When the framework is shutdown
* the {@link Runnable#run()} method is called for each registered handler. Handlers should
* make no assumptions on the thread it is being called from. If a handler object is
* registered multiple times it will be called once for each registration.
* <p>
* At the time a handler is called the framework is shutdown. Handlers must not depend on
* a running framework to execute or attempt to load additional classes from bundles
* installed in the framework.
* @param handler the framework shutdown handler
* @throws IllegalStateException if the platform is already running
*/
static void internalAddFrameworkShutdownHandler(Runnable handler) {
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING); if (shutdownHandlers == null)
shutdownHandlers = new ArrayList<Runnable>(); shutdownHandlers.add(handler);
} /*
* NOTE: This is an internal/experimental method used by launchers that need to react when the framework
* is shutdown internally.
*
* Removes a framework shutdown handler. <p>
* @param handler the framework shutdown handler
* @throws IllegalStateException if the platform is already running
*/
static void internalRemoveFrameworkShutdownHandler(Runnable handler) {
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING); if (shutdownHandlers != null)
shutdownHandlers.remove(handler);
} private static void registerFrameworkShutdownHandlers() {
if (shutdownHandlers == null)
return; final Bundle systemBundle = context.getBundle();
for (Iterator<Runnable> it = shutdownHandlers.iterator(); it.hasNext();) {
final Runnable handler = it.next();
BundleListener listener = new BundleListener() {
public void bundleChanged(BundleEvent event) {
if (event.getBundle() == systemBundle && event.getType() == BundleEvent.STOPPED) {
handler.run();
}
}
};
context.addBundleListener(listener);
}
}
}ElipseStarter
- main() in class EclipseStarter
/**
* This is the main to start osgi.
* It only works when the framework is being jared as a single jar
*/
public static void main(String[] args) throws Exception {
if (FrameworkProperties.getProperty("eclipse.startTime") == null) //$NON-NLS-1$
FrameworkProperties.setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis())); //$NON-NLS-1$
if (FrameworkProperties.getProperty(PROP_NOSHUTDOWN) == null)
FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
// set the compatibility boot delegation flag to false to get "standard" OSGi behavior WRT boot delegation (bug 178477)
if (FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION) == null)
FrameworkProperties.setProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "false"); //$NON-NLS-1$
Object result = run(args, null);
if (result instanceof Integer && !Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
System.exit(((Integer) result).intValue());
}- run() in class ElipseStarter
/**
* Launches the platform and runs a single application. The application is either identified
* in the given arguments (e.g., -application <app id>) or in the <code>eclipse.application</code>
* System property. This convenience method starts
* up the platform, runs the indicated application, and then shuts down the
* platform. The platform must not be running already.
*
* @param args the command line-style arguments used to configure the platform
* @param endSplashHandler the block of code to run to tear down the splash
* screen or <code>null</code> if no tear down is required
* @return the result of running the application
* @throws Exception if anything goes wrong
*/
public static Object run(String[] args, Runnable endSplashHandler) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.run()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
boolean startupFailed = true;
try {
startup(args, endSplashHandler);//endSplashHandler == null
startupFailed = false;
if (Boolean.valueOf(FrameworkProperties.getProperty(PROP_IGNOREAPP)).booleanValue() || isForcedRestart())
return null;
return run(null);//make EclipseAppLauncher run to starup platform
} catch (Throwable e) {
// ensure the splash screen is down
if (endSplashHandler != null)
endSplashHandler.run();
// may use startupFailed to understand where the error happened
FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, startupFailed ? EclipseAdaptorMsg.ECLIPSE_STARTUP_STARTUP_ERROR : EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
// TODO desperate measure - ideally, we should write this to disk (a la Main.log)
e.printStackTrace();
} finally {
try {
// The application typically sets the exit code however the framework can request that
// it be re-started. We need to check for this and potentially override the exit code.
if (isForcedRestart())
FrameworkProperties.setProperty(PROP_EXITCODE, "23"); //$NON-NLS-1$
if (!Boolean.valueOf(FrameworkProperties.getProperty(PROP_NOSHUTDOWN)).booleanValue())
shutdown();
} catch (Throwable e) {
FrameworkLogEntry logEntry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_SHUTDOWN_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
// TODO desperate measure - ideally, we should write this to disk (a la Main.log)
e.printStackTrace();
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("EclipseStarter.run()"); //$NON-NLS-1$
if (Profile.PROFILE) {
String report = Profile.getProfileLog();
// avoiding writing to the console if there is nothing to print
if (report != null && report.length() > 0)
System.out.println(report);
}
}
// we only get here if an error happened
if (FrameworkProperties.getProperty(PROP_EXITCODE) == null) {
FrameworkProperties.setProperty(PROP_EXITCODE, "13"); //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_EXITDATA, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_CHECK_LOG, log == null ? null : log.getFile().getPath()));
}
return null;
}- startup in class ElicpseStartup
/**
* Starts the platform and sets it up to run a single application. The application is either identified
* in the given arguments (e.g., -application <app id>) or in the <code>eclipse.application</code>
* System property. The platform must not be running already.
* <p>
* The given runnable (if not <code>null</code>) is used to tear down the splash screen if required.
* </p>
* @param args the arguments passed to the application
* @return BundleContext the context of the system bundle
* @throws Exception if anything goes wrong
*/
public static BundleContext startup(String[] args, Runnable endSplashHandler) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.startup()", null); //$NON-NLS-1$
if (running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ALREADY_RUNNING);
FrameworkProperties.initializeProperties(); // initialize some framework properties that must always be set
processCommandLine(args);
LocationManager.initializeLocations();
loadConfigurationInfo();
finalizeProperties();
if (Profile.PROFILE)
Profile.initProps(); // catch any Profile properties set in eclipse.properties...
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "props inited"); //$NON-NLS-1$ //$NON-NLS-2$
adaptor = createAdaptor();
log = adaptor.getFrameworkLog();
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "adapter created"); //$NON-NLS-1$ //$NON-NLS-2$
framework = new Framework(adaptor);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "OSGi created"); //$NON-NLS-1$ //$NON-NLS-2$
context = framework.getBundle(0).getBundleContext();
registerFrameworkShutdownHandlers();
publishSplashScreen(endSplashHandler);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "osgi launched"); //$NON-NLS-1$ //$NON-NLS-2$
consoleMgr = ConsoleManager.startConsole(framework);
if (Profile.PROFILE && Profile.STARTUP) {
Profile.logTime("EclipseStarter.startup()", "console started"); //$NON-NLS-1$ //$NON-NLS-2$
}
framework.launch();
// save the cached timestamp before loading basic bundles; this is needed so we can do a proper timestamp check when logging resolver errors
long stateStamp = adaptor.getState().getTimeStamp();
Bundle[] startBundles = loadBasicBundles(); if (startBundles == null || ("true".equals(FrameworkProperties.getProperty(PROP_REFRESH_BUNDLES)) && refreshPackages(getCurrentBundles(false)))) { //$NON-NLS-1$
waitForShutdown();
return context; // cannot continue; loadBasicBundles caused refreshPackages to shutdown the framework
} if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "loading basic bundles"); //$NON-NLS-1$ //$NON-NLS-2$ // set the framework start level to the ultimate value. This will actually start things
// running if they are persistently active.
setStartLevel(getStartLevel());
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("EclipseStarter.startup()", "StartLevel set"); //$NON-NLS-1$ //$NON-NLS-2$
// they should all be active by this time
ensureBundlesActive(startBundles); // in the case where the built-in console is disabled we should try to start the console bundle
try {
consoleMgr.checkForConsoleBundle();
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null);
log.log(entry);
}
if (debug || FrameworkProperties.getProperty(PROP_DEV) != null)
// only spend time showing unresolved bundles in dev/debug mode and the state has changed
if (stateStamp != adaptor.getState().getTimeStamp())
logUnresolvedBundles(context.getBundles());
running = true;
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("EclipseStarter.startup()"); //$NON-NLS-1$
return context;
}- processCommandLine() in class ElicpseStartup
private static String[] processCommandLine(String[] args) throws Exception {
EclipseEnvironmentInfo.setAllArgs(args);//set environment information for use by application runing on Elicpse
if (args.length == 0) {
EclipseEnvironmentInfo.setFrameworkArgs(args);
EclipseEnvironmentInfo.setAllArgs(args);
return args;
}
int[] configArgs = new int[args.length];
configArgs[0] = -1; // need to initialize the first element to something that could not be an index.
int configArgIndex = 0;
for (int i = 0; i < args.length; i++) {
boolean found = false;
// check for args without parameters (i.e., a flag arg) // check if debug should be enabled for the entire platform
// If this is the last arg or there is a following arg (i.e., arg+1 has a leading -),
// simply enable debug. Otherwise, assume that that the following arg is
// actually the filename of an options file. This will be processed below.
if (args[i].equalsIgnoreCase(DEBUG) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_DEBUG, ""); //$NON-NLS-1$
debug = true;
found = true;
} // check if development mode should be enabled for the entire platform
// If this is the last arg or there is a following arg (i.e., arg+1 has a leading -),
// simply enable development mode. Otherwise, assume that that the following arg is
// actually some additional development time class path entries. This will be processed below.
if (args[i].equalsIgnoreCase(DEV) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_DEV, ""); //$NON-NLS-1$
found = true;
} // look for the initialization arg
if (args[i].equalsIgnoreCase(INITIALIZE)) {
initialize = true;
found = true;
} // look for the clean flag.
if (args[i].equalsIgnoreCase(CLEAN)) {
FrameworkProperties.setProperty(PROP_CLEAN, "true"); //$NON-NLS-1$
found = true;
} // look for the consoleLog flag
if (args[i].equalsIgnoreCase(CONSOLE_LOG)) {
FrameworkProperties.setProperty(PROP_CONSOLE_LOG, "true"); //$NON-NLS-1$
found = true;
} // look for the console with no port.
if (args[i].equalsIgnoreCase(CONSOLE) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) { //$NON-NLS-1$
FrameworkProperties.setProperty(PROP_CONSOLE, ""); //$NON-NLS-1$
found = true;
} if (args[i].equalsIgnoreCase(NOEXIT)) {
FrameworkProperties.setProperty(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
found = true;
} if (found) {
configArgs[configArgIndex++] = i;
continue;
}
// check for args with parameters. If we are at the last argument or if the next one
// has a '-' as the first character, then we can't have an arg with a parm so continue.
if (i == args.length - 1 || args[i + 1].startsWith("-")) { //$NON-NLS-1$
continue;
}
String arg = args[++i]; // look for the console and port.
if (args[i - 1].equalsIgnoreCase(CONSOLE)) {
FrameworkProperties.setProperty(PROP_CONSOLE, arg);
found = true;
} // look for the configuration location .
if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
FrameworkProperties.setProperty(LocationManager.PROP_CONFIG_AREA, arg);
found = true;
} // look for the data location for this instance.
if (args[i - 1].equalsIgnoreCase(DATA)) {
FrameworkProperties.setProperty(LocationManager.PROP_INSTANCE_AREA, arg);
found = true;
} // look for the user location for this instance.
if (args[i - 1].equalsIgnoreCase(USER)) {
FrameworkProperties.setProperty(LocationManager.PROP_USER_AREA, arg);
found = true;
} // look for the launcher location
if (args[i - 1].equalsIgnoreCase(LAUNCHER)) {
FrameworkProperties.setProperty(LocationManager.PROP_LAUNCHER, arg);
found = true;
}
// look for the development mode and class path entries.
if (args[i - 1].equalsIgnoreCase(DEV)) {
FrameworkProperties.setProperty(PROP_DEV, arg);
found = true;
} // look for the debug mode and option file location.
if (args[i - 1].equalsIgnoreCase(DEBUG)) {
FrameworkProperties.setProperty(PROP_DEBUG, arg);
debug = true;
found = true;
} // look for the window system.
if (args[i - 1].equalsIgnoreCase(WS)) {
FrameworkProperties.setProperty(PROP_WS, arg);
found = true;
} // look for the operating system
if (args[i - 1].equalsIgnoreCase(OS)) {
FrameworkProperties.setProperty(PROP_OS, arg);
found = true;
} // look for the system architecture
if (args[i - 1].equalsIgnoreCase(ARCH)) {
FrameworkProperties.setProperty(PROP_ARCH, arg);
found = true;
} // look for the nationality/language
if (args[i - 1].equalsIgnoreCase(NL)) {
FrameworkProperties.setProperty(PROP_NL, arg);
found = true;
} // look for the locale extensions
if (args[i - 1].equalsIgnoreCase(NL_EXTENSIONS)) {
FrameworkProperties.setProperty(PROP_NL_EXTENSIONS, arg);
found = true;
} // done checking for args. Remember where an arg was found
if (found) {
configArgs[configArgIndex++] = i - 1;
configArgs[configArgIndex++] = i;
}
} // remove all the arguments consumed by this argument parsing
if (configArgIndex == 0) {
EclipseEnvironmentInfo.setFrameworkArgs(new String[0]);
EclipseEnvironmentInfo.setAppArgs(args);
return args;
}
String[] appArgs = new String[args.length - configArgIndex];
String[] frameworkArgs = new String[configArgIndex];
configArgIndex = 0;
int j = 0;
int k = 0;
for (int i = 0; i < args.length; i++) {
if (i == configArgs[configArgIndex]) {
frameworkArgs[k++] = args[i];
configArgIndex++;
} else
appArgs[j++] = args[i];
}
EclipseEnvironmentInfo.setFrameworkArgs(frameworkArgs);
EclipseEnvironmentInfo.setAppArgs(appArgs);
return appArgs;
}- LocationManager
/*******************************************************************************
* Copyright (c) 2004, 2011 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.core.runtime.adaptor; import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Properties;
import org.eclipse.core.runtime.internal.adaptor.*;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.internal.baseadaptor.AdaptorUtil;
import org.eclipse.osgi.service.datalocation.Location; /**
* This class is used to manage the various Locations for Eclipse.
* <p>
* Clients may not extend this class.
* </p>
* @since 3.1
* @noextend This class is not intended to be subclassed by clients.
*/
public class LocationManager {
private static Location installLocation = null;
private static Location configurationLocation = null;
private static Location userLocation = null;
private static Location instanceLocation = null;
private static Location eclipseHomeLocation = null; public static final String READ_ONLY_AREA_SUFFIX = ".readOnly"; //$NON-NLS-1$
public static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
public static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$
public static final String PROP_CONFIG_AREA_DEFAULT = "osgi.configuration.area.default"; //$NON-NLS-1$
public static final String PROP_SHARED_CONFIG_AREA = "osgi.sharedConfiguration.area"; //$NON-NLS-1$
public static final String PROP_INSTANCE_AREA = "osgi.instance.area"; //$NON-NLS-1$
public static final String PROP_INSTANCE_AREA_DEFAULT = "osgi.instance.area.default"; //$NON-NLS-1$
public static final String PROP_USER_AREA = "osgi.user.area"; //$NON-NLS-1$
public static final String PROP_USER_AREA_DEFAULT = "osgi.user.area.default"; //$NON-NLS-1$
public static final String PROP_MANIFEST_CACHE = "osgi.manifest.cache"; //$NON-NLS-1$
public static final String PROP_USER_HOME = "user.home"; //$NON-NLS-1$
public static final String PROP_USER_DIR = "user.dir"; //$NON-NLS-1$
public static final String PROP_HOME_LOCATION_AREA = "eclipse.home.location"; //$NON-NLS-1$
static final String PROP_LAUNCHER = "eclipse.launcher"; //$NON-NLS-1$ // configuration area file/dir names
public static final String BUNDLES_DIR = "bundles"; //$NON-NLS-1$
public static final String STATE_FILE = ".state"; //$NON-NLS-1$
public static final String LAZY_FILE = ".lazy"; //$NON-NLS-1$
public static final String BUNDLE_DATA_FILE = ".bundledata"; //$NON-NLS-1$
public static final String MANIFESTS_DIR = "manifests"; //$NON-NLS-1$
public static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$
public static final String ECLIPSE_PROPERTIES = "eclipse.properties"; //$NON-NLS-1$ // Constants for configuration location discovery
private static final String ECLIPSE = "eclipse"; //$NON-NLS-1$
private static final String PRODUCT_SITE_MARKER = ".eclipseproduct"; //$NON-NLS-1$
private static final String PRODUCT_SITE_ID = "id"; //$NON-NLS-1$
private static final String PRODUCT_SITE_VERSION = "version"; //$NON-NLS-1$ private static final String CONFIG_DIR = "configuration"; //$NON-NLS-1$ // Data mode constants for user, configuration and data locations.
private static final String NONE = "@none"; //$NON-NLS-1$
private static final String NO_DEFAULT = "@noDefault"; //$NON-NLS-1$
private static final String USER_HOME = "@user.home"; //$NON-NLS-1$
private static final String USER_DIR = "@user.dir"; //$NON-NLS-1$
// Placeholder for hashcode of installation directory
private static final String INSTALL_HASH_PLACEHOLDER = "@install.hash"; //$NON-NLS-1$ private static final String INSTANCE_DATA_AREA_PREFIX = ".metadata/.plugins/"; //$NON-NLS-1$ /**
* Builds a URL with the given specification
* @param spec the URL specification
* @param trailingSlash flag to indicate a trailing slash on the spec
* @return a URL
*/
public static URL buildURL(String spec, boolean trailingSlash) {
return LocationHelper.buildURL(spec, trailingSlash);
} private static void mungeConfigurationLocation() {
// if the config property was set, munge it for backwards compatibility.
String location = FrameworkProperties.getProperty(PROP_CONFIG_AREA);
if (location != null) {
if (location.endsWith(".cfg")) { //$NON-NLS-1$
int index = location.lastIndexOf('/');
if (index < 0)
index = location.lastIndexOf('\\');
location = location.substring(0, index + 1);
FrameworkProperties.setProperty(PROP_CONFIG_AREA, location);
}
}
} /**
* Initializes the Location objects for the LocationManager.
*/
public static void initializeLocations() {
// set the osgi storage area if it exists
String osgiStorage = FrameworkProperties.getProperty(Constants.FRAMEWORK_STORAGE);
if (osgiStorage != null)
FrameworkProperties.setProperty(PROP_CONFIG_AREA, osgiStorage);
// do install location initialization first since others may depend on it
// assumes that the property is already set
installLocation = buildLocation(PROP_INSTALL_AREA, null, "", true, false, null); //$NON-NLS-1$ // TODO not sure what the data area prefix should be here for the user area
Location temp = buildLocation(PROP_USER_AREA_DEFAULT, null, "", false, false, null); //$NON-NLS-1$
URL defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
defaultLocation = buildURL(new File(FrameworkProperties.getProperty(PROP_USER_HOME), "user").getAbsolutePath(), true); //$NON-NLS-1$
userLocation = buildLocation(PROP_USER_AREA, defaultLocation, "", false, false, null); //$NON-NLS-1$ temp = buildLocation(PROP_INSTANCE_AREA_DEFAULT, null, "", false, false, INSTANCE_DATA_AREA_PREFIX); //$NON-NLS-1$
defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null)
defaultLocation = buildURL(new File(FrameworkProperties.getProperty(PROP_USER_DIR), "workspace").getAbsolutePath(), true); //$NON-NLS-1$
instanceLocation = buildLocation(PROP_INSTANCE_AREA, defaultLocation, "", false, false, INSTANCE_DATA_AREA_PREFIX); //$NON-NLS-1$ mungeConfigurationLocation();
// compute a default but it is very unlikely to be used since main will have computed everything
temp = buildLocation(PROP_CONFIG_AREA_DEFAULT, null, "", false, false, null); //$NON-NLS-1$
defaultLocation = temp == null ? null : temp.getURL();
if (defaultLocation == null && FrameworkProperties.getProperty(PROP_CONFIG_AREA) == null)
// only compute the default if the configuration area property is not set
defaultLocation = buildURL(computeDefaultConfigurationLocation(), true);
configurationLocation = buildLocation(PROP_CONFIG_AREA, defaultLocation, "", false, false, null); //$NON-NLS-1$
// get the parent location based on the system property. This will have been set on the
// way in either by the caller/user or by main. There will be no parent location if we are not
// cascaded.
URL parentLocation = computeSharedConfigurationLocation();
if (parentLocation != null && !parentLocation.equals(configurationLocation.getURL())) {
Location parent = new BasicLocation(null, parentLocation, true, null);
((BasicLocation) configurationLocation).setParent(parent);
}
initializeDerivedConfigurationLocations(); if (FrameworkProperties.getProperty(PROP_HOME_LOCATION_AREA) == null) {
String eclipseLauncher = FrameworkProperties.getProperty(PROP_LAUNCHER);
String eclipseHomeLocationPath = getEclipseHomeLocation(eclipseLauncher);
if (eclipseHomeLocationPath != null)
FrameworkProperties.setProperty(PROP_HOME_LOCATION_AREA, eclipseHomeLocationPath);
}
// if eclipse.home.location is not set then default to osgi.install.area
if (FrameworkProperties.getProperty(PROP_HOME_LOCATION_AREA) == null && FrameworkProperties.getProperty(PROP_INSTALL_AREA) != null)
FrameworkProperties.setProperty(PROP_HOME_LOCATION_AREA, FrameworkProperties.getProperty(PROP_INSTALL_AREA));
eclipseHomeLocation = buildLocation(PROP_HOME_LOCATION_AREA, null, "", true, true, null); //$NON-NLS-1$
} private static String getEclipseHomeLocation(String launcher) {
if (launcher == null)
return null;
File launcherFile = new File(launcher);
if (launcherFile.getParent() == null)
return null;
File launcherDir = new File(launcherFile.getParent());
// check for mac os; the os check is copied from EclipseEnvironmentInfo.
String macosx = org.eclipse.osgi.service.environment.Constants.OS_MACOSX;
if (macosx.equals(EclipseEnvironmentInfo.getDefault().getOS()))
launcherDir = getMacOSEclipsoeHomeLocation(launcherDir);
return (launcherDir.exists() && launcherDir.isDirectory()) ? launcherDir.getAbsolutePath() : null;
} private static File getMacOSEclipsoeHomeLocation(File launcherDir) {
// TODO for now we go up three directories from the launcher dir as long as the parent dir is named MacOS; is this always the case?
// TODO not sure if case is important
if (!launcherDir.getName().equalsIgnoreCase("macos")) //$NON-NLS-1$
return launcherDir; // don't do the up three stuff if not in macos directory
String launcherParent = launcherDir.getParent();
if (launcherParent != null)
launcherParent = new File(launcherParent).getParent();
if (launcherParent != null)
launcherParent = new File(launcherParent).getParent();
return launcherParent == null ? null : new File(launcherParent);
} @SuppressWarnings("deprecation")
private static Location buildLocation(String property, URL defaultLocation, String userDefaultAppendage, boolean readOnlyDefault, boolean computeReadOnly, String dataAreaPrefix) {
String location = FrameworkProperties.clearProperty(property);
// the user/product may specify a non-default readOnly setting
String userReadOnlySetting = FrameworkProperties.getProperty(property + READ_ONLY_AREA_SUFFIX);
boolean readOnly = (userReadOnlySetting == null ? readOnlyDefault : Boolean.valueOf(userReadOnlySetting).booleanValue());
// if the instance location is not set, predict where the workspace will be and
// put the instance area inside the workspace meta area.
if (location == null)
return new BasicLocation(property, defaultLocation, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(defaultLocation), dataAreaPrefix);
String trimmedLocation = location.trim();
if (trimmedLocation.equalsIgnoreCase(NONE))
return null;
if (trimmedLocation.equalsIgnoreCase(NO_DEFAULT))
return new BasicLocation(property, null, readOnly, dataAreaPrefix);
if (trimmedLocation.startsWith(USER_HOME)) {
String base = substituteVar(location, USER_HOME, PROP_USER_HOME);
location = new File(base, userDefaultAppendage).getAbsolutePath();
} else if (trimmedLocation.startsWith(USER_DIR)) {
String base = substituteVar(location, USER_DIR, PROP_USER_DIR);
location = new File(base, userDefaultAppendage).getAbsolutePath();
}
int idx = location.indexOf(INSTALL_HASH_PLACEHOLDER);
if (idx == 0) {
throw new RuntimeException("The location cannot start with '" + INSTALL_HASH_PLACEHOLDER + "': " + location); //$NON-NLS-1$ //$NON-NLS-2$
} else if (idx > 0) {
location = location.substring(0, idx) + getInstallDirHash() + location.substring(idx + INSTALL_HASH_PLACEHOLDER.length());
}
URL url = buildURL(location, true);
BasicLocation result = null;
if (url != null) {
result = new BasicLocation(property, null, userReadOnlySetting != null || !computeReadOnly ? readOnly : !canWrite(url), dataAreaPrefix);
result.setURL(url, false);
}
return result;
} private static String substituteVar(String source, String var, String prop) {
String value = FrameworkProperties.getProperty(prop, ""); //$NON-NLS-1$
return value + source.substring(var.length());
} private static void initializeDerivedConfigurationLocations() {
if (FrameworkProperties.getProperty(PROP_MANIFEST_CACHE) == null)
FrameworkProperties.setProperty(PROP_MANIFEST_CACHE, getConfigurationFile(MANIFESTS_DIR).getAbsolutePath());
} private static URL computeInstallConfigurationLocation() {
String property = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
if (property != null)
return LocationHelper.buildURL(property, true);
return null;
} private static URL computeSharedConfigurationLocation() {
String property = FrameworkProperties.getProperty(PROP_SHARED_CONFIG_AREA);
if (property == null)
return null;
try {
URL sharedConfigurationURL = LocationHelper.buildURL(property, true);
if (sharedConfigurationURL == null)
return null;
if (sharedConfigurationURL.getPath().startsWith("/")) //$NON-NLS-1$
// absolute
return sharedConfigurationURL;
URL installURL = installLocation.getURL();
if (!sharedConfigurationURL.getProtocol().equals(installURL.getProtocol()))
// different protocol
return sharedConfigurationURL;
sharedConfigurationURL = new URL(installURL, sharedConfigurationURL.getPath());
FrameworkProperties.setProperty(PROP_SHARED_CONFIG_AREA, sharedConfigurationURL.toExternalForm());
} catch (MalformedURLException e) {
// do nothing here since it is basically impossible to get a bogus url
}
return null;
} private static String computeDefaultConfigurationLocation() {
// 1) We store the config state relative to the 'eclipse' directory if possible
// 2) If this directory is read-only
// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
// is unique for each local user, and <application-id> is the one
// defined in .eclipseproduct marker file. If .eclipseproduct does not
// exist, use "eclipse" as the application-id. URL installURL = computeInstallConfigurationLocation();
if (installURL != null && "file".equals(installURL.getProtocol())) { //$NON-NLS-1$
File installDir = new File(installURL.getFile());
File defaultConfigDir = new File(installDir, CONFIG_DIR);
if (!defaultConfigDir.exists())
defaultConfigDir.mkdirs();
if (defaultConfigDir.exists() && AdaptorUtil.canWrite(defaultConfigDir))
return defaultConfigDir.getAbsolutePath();
}
// We can't write in the eclipse install dir so try for some place in the user's home dir
return computeDefaultUserAreaLocation(CONFIG_DIR);
} private static boolean canWrite(URL location) {
if (location != null && "file".equals(location.getProtocol())) { //$NON-NLS-1$
File locationDir = new File(location.getFile());
if (!locationDir.exists())
locationDir.mkdirs();
if (locationDir.exists() && AdaptorUtil.canWrite(locationDir))
return true;
}
return false;
} private static String computeDefaultUserAreaLocation(String pathAppendage) {
// we store the state in <user.home>/.eclipse/<application-id>_<version> where <user.home>
// is unique for each local user, and <application-id> is the one
// defined in .eclipseproduct marker file. If .eclipseproduct does not
// exist, use "eclipse" as the application-id.
String installProperty = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return null;
File installDir = new File(installURL.getFile());
String installDirHash = getInstallDirHash(); String appName = "." + ECLIPSE; //$NON-NLS-1$
File eclipseProduct = new File(installDir, PRODUCT_SITE_MARKER);
if (eclipseProduct.exists()) {
Properties props = new Properties();
try {
props.load(new FileInputStream(eclipseProduct));
String appId = props.getProperty(PRODUCT_SITE_ID);
if (appId == null || appId.trim().length() == 0)
appId = ECLIPSE;
String appVersion = props.getProperty(PRODUCT_SITE_VERSION);
if (appVersion == null || appVersion.trim().length() == 0)
appVersion = ""; //$NON-NLS-1$
appName += File.separator + appId + "_" + appVersion + "_" + installDirHash; //$NON-NLS-1$ //$NON-NLS-2$
} catch (IOException e) {
// Do nothing if we get an exception. We will default to a standard location
// in the user's home dir.
// add the hash to help prevent collisions
appName += File.separator + installDirHash;
}
} else {
// add the hash to help prevent collisions
appName += File.separator + installDirHash;
}
String userHome = FrameworkProperties.getProperty(PROP_USER_HOME);
return new File(userHome, appName + "/" + pathAppendage).getAbsolutePath(); //$NON-NLS-1$
} /**
* Return hash code identifying an absolute installation path
* @return hash code as String
*/
private static String getInstallDirHash() {
// compute an install dir hash to prevent configuration area collisions with other eclipse installs
String installProperty = FrameworkProperties.getProperty(PROP_INSTALL_AREA);
URL installURL = buildURL(installProperty, true);
if (installURL == null)
return ""; //$NON-NLS-1$
File installDir = new File(installURL.getFile());
int hashCode;
try {
hashCode = installDir.getCanonicalPath().hashCode();
} catch (IOException ioe) {
// fall back to absolute path
hashCode = installDir.getAbsolutePath().hashCode();
}
if (hashCode < 0)
hashCode = -(hashCode);
String installDirHash = String.valueOf(hashCode);
return installDirHash;
} /**
* Returns the user Location object
* @return the user Location object
*/
public static Location getUserLocation() {
return userLocation;
} /**
* Returns the configuration Location object
* @return the configuration Location object
*/
public static Location getConfigurationLocation() {
return configurationLocation;
} /**
* Returns the install Location object
* @return the install Location object
*/
public static Location getInstallLocation() {
return installLocation;
} /**
* Returns the instance Location object
* @return the instance Location object
*/
public static Location getInstanceLocation() {
return instanceLocation;
} public static Location getEclipseHomeLocation() {
return eclipseHomeLocation;
} /**
* Returns the File object under the configuration location used for the OSGi configuration
* @return the OSGi configuration directory
*/
public static File getOSGiConfigurationDir() {
// TODO assumes the URL is a file: url
return new File(configurationLocation.getURL().getFile(), FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME);
} /**
* Returns a file from the configuration area that can be used by the framework
* @param filename the filename
* @return a file from the configuration area
*/
public static File getConfigurationFile(String filename) {
File dir = getOSGiConfigurationDir();
if (!dir.exists())
dir.mkdirs();
return new File(dir, filename);
}
}LocationManager
- createAdaptor
DEFAULT_ADAPTER_CLASS = org.eclipse.osgi.baseadaptor.BaseAdaptor
/*******************************************************************************
* Copyright (c) 2005, 2011 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.osgi.baseadaptor; import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.util.*;
import org.eclipse.core.runtime.adaptor.LocationManager;
import org.eclipse.osgi.baseadaptor.bundlefile.BundleFile;
import org.eclipse.osgi.baseadaptor.hooks.*;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.internal.core.*;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.baseadaptor.*;
import org.eclipse.osgi.service.resolver.PlatformAdmin;
import org.eclipse.osgi.service.resolver.State;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.framework.wiring.BundleWiring; /**
* A Framework adaptor implementation that allows additional functionality to be
* hooked in. Hooks are configured using {@link HookConfigurator}
* objects. A framework extension may add hook configurators which can be used
* to add hooks to the {@link HookRegistry}.
* @see HookConfigurator
* @see HookRegistry
* @see AdaptorHook
* @since 3.2
*/
public class BaseAdaptor implements FrameworkAdaptor {
// System property used to set the parent classloader type (boot is the default)
private static final String PROP_PARENT_CLASSLOADER = "osgi.parentClassloader"; //$NON-NLS-1$
// A parent classloader type that specifies the application classloader
private static final String PARENT_CLASSLOADER_APP = "app"; //$NON-NLS-1$
// A parent classloader type that specifies the extension classlaoder
private static final String PARENT_CLASSLOADER_EXT = "ext"; //$NON-NLS-1$
// A parent classloader type that specifies the boot classlaoder
private static final String PARENT_CLASSLOADER_BOOT = "boot"; //$NON-NLS-1$
// A parent classloader type that specifies the framework classlaoder
private static final String PARENT_CLASSLOADER_FWK = "fwk"; //$NON-NLS-1$
// The BundleClassLoader parent to use when creating BundleClassLoaders.
private static ClassLoader bundleClassLoaderParent;
static {
// check property for specified parent
// check the osgi defined property first
String type = FrameworkProperties.getProperty(Constants.FRAMEWORK_BUNDLE_PARENT);
if (type != null) {
if (Constants.FRAMEWORK_BUNDLE_PARENT_FRAMEWORK.equals(type))
type = PARENT_CLASSLOADER_FWK;
} else {
type = FrameworkProperties.getProperty(BaseAdaptor.PROP_PARENT_CLASSLOADER, BaseAdaptor.PARENT_CLASSLOADER_BOOT);
} if (BaseAdaptor.PARENT_CLASSLOADER_FWK.equalsIgnoreCase(type))
bundleClassLoaderParent = FrameworkAdaptor.class.getClassLoader();
else if (BaseAdaptor.PARENT_CLASSLOADER_APP.equalsIgnoreCase(type))
bundleClassLoaderParent = ClassLoader.getSystemClassLoader();
else if (BaseAdaptor.PARENT_CLASSLOADER_EXT.equalsIgnoreCase(type)) {
ClassLoader appCL = ClassLoader.getSystemClassLoader();
if (appCL != null)
bundleClassLoaderParent = appCL.getParent();
}
// default to boot classloader
if (bundleClassLoaderParent == null)
bundleClassLoaderParent = new ClassLoader(Object.class.getClassLoader()) {/* boot class loader*/};
} private Framework eventPublisher;
private boolean stopping;
private HookRegistry hookRegistry;
private FrameworkLog log;
private BundleContext context;
private BaseStorage storage;
private BundleWatcher bundleWatcher; /**
* Constructs a BaseAdaptor.
* @param args arguments passed to the adaptor by the framework.
*/
public BaseAdaptor(String[] args) {
if (LocationManager.getConfigurationLocation() == null)
LocationManager.initializeLocations();
hookRegistry = new HookRegistry(this);
FrameworkLogEntry[] errors = hookRegistry.initialize();
if (errors.length > 0)
for (int i = 0; i < errors.length; i++)
getFrameworkLog().log(errors[i]);
// get the storage after the registry has been initialized
storage = getStorage();
// TODO consider passing args to BaseAdaptorHooks
} /**
* This method will call all configured adaptor hooks {@link AdaptorHook#initialize(BaseAdaptor)} method.
* @see FrameworkAdaptor#initialize(EventPublisher)
*/
public void initialize(EventPublisher publisher) {
this.eventPublisher = (Framework) publisher;
// set the adaptor for the adaptor hooks
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].initialize(this);
} /**
* @see FrameworkAdaptor#initializeStorage()
*/
public void initializeStorage() throws IOException {
storage.initialize(this);
} /**
* @throws IOException
* @see FrameworkAdaptor#compactStorage()
*/
public void compactStorage() throws IOException {
storage.compact();
} /**
* This method will call all the configured adaptor hook {@link AdaptorHook#addProperties(Properties)} methods.
* @see FrameworkAdaptor#getProperties()
*/
public Properties getProperties() {
Properties props = new Properties();
String resource = FrameworkProperties.getProperty(Constants.OSGI_PROPERTIES, Constants.DEFAULT_OSGI_PROPERTIES);
try {
InputStream in = null;
File file = new File(resource);
if (file.exists())
in = new FileInputStream(file);
if (in == null)
in = getClass().getResourceAsStream(resource);
if (in != null) {
try {
props.load(new BufferedInputStream(in));
} finally {
try {
in.close();
} catch (IOException ee) {
// nothing to do
}
}
} else {
if (Debug.DEBUG_GENERAL)
Debug.println("Skipping osgi.properties: " + resource); //$NON-NLS-1$
}
} catch (IOException e) {
if (Debug.DEBUG_GENERAL)
Debug.println("Unable to load osgi.properties: " + e.getMessage()); //$NON-NLS-1$
}
// add the storage properties
storage.addProperties(props);
// add the properties from each adaptor hook
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].addProperties(props);
return props;
} /**
* @see FrameworkAdaptor#getInstalledBundles()
*/
public BundleData[] getInstalledBundles() {
return storage.getInstalledBundles();
} /**
* This method will call each configured adaptor hook {@link AdaptorHook#mapLocationToURLConnection(String)} method
* until one returns a non-null value. If none of the adaptor hooks return a non-null value then the
* string is used to construct a new URL object to open a new url connection.
*
* @see FrameworkAdaptor#mapLocationToURLConnection(String)
*/
public URLConnection mapLocationToURLConnection(String location) throws BundleException {
try {
URLConnection result = null;
// try the adaptor hooks first;
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++) {
result = adaptorHooks[i].mapLocationToURLConnection(location);
if (result != null)
return result;
}
// just do the default
return (new URL(location).openConnection());
} catch (IOException e) {
throw new BundleException(NLS.bind(AdaptorMsg.ADAPTOR_URL_CREATE_EXCEPTION, location), e);
}
} /**
* @see FrameworkAdaptor#installBundle(String, URLConnection)
*/
public BundleOperation installBundle(String location, URLConnection source) {
return storage.installBundle(location, source);
} /**
* @see FrameworkAdaptor#updateBundle(BundleData, URLConnection)
*/
public BundleOperation updateBundle(BundleData bundledata, URLConnection source) {
return storage.updateBundle((BaseData) bundledata, source);
} /**
* @see FrameworkAdaptor#uninstallBundle(BundleData)
*/
public BundleOperation uninstallBundle(BundleData bundledata) {
return storage.uninstallBundle((BaseData) bundledata);
} /**
* @see FrameworkAdaptor#getTotalFreeSpace()
*/
public long getTotalFreeSpace() throws IOException {
return storage.getFreeSpace();
} /**
* @throws IOException
* @see FrameworkAdaptor#getPermissionStorage()
*/
public PermissionStorage getPermissionStorage() throws IOException {
return storage.getPermissionStorage();
} /**
* This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStart(BundleContext)} methods.
* @see FrameworkAdaptor#frameworkStart(BundleContext)
*/
public void frameworkStart(BundleContext fwContext) throws BundleException {
this.context = fwContext;
stopping = false;
// always start the storage first
storage.frameworkStart(fwContext);
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].frameworkStart(fwContext);
} /**
* This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStop(BundleContext)} methods.
* @see FrameworkAdaptor#frameworkStop(BundleContext)
*/
public void frameworkStop(BundleContext fwContext) throws BundleException {
// first inform all configured adaptor hooks
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].frameworkStop(fwContext);
// stop the storage last
storage.frameworkStop(fwContext);
} /**
* This method calls all the configured adaptor hook {@link AdaptorHook#frameworkStopping(BundleContext)} methods.
* @see FrameworkAdaptor#frameworkStopping(BundleContext)
*/
public void frameworkStopping(BundleContext fwContext) {
stopping = true;
// always tell storage of stopping first
storage.frameworkStopping(fwContext);
// inform all configured adaptor hooks last
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].frameworkStopping(fwContext);
} /**
* @see FrameworkAdaptor#getInitialBundleStartLevel()
*/
public int getInitialBundleStartLevel() {
return storage.getInitialBundleStartLevel();
} /**
* @see FrameworkAdaptor#setInitialBundleStartLevel(int)
*/
public void setInitialBundleStartLevel(int value) {
storage.setInitialBundleStartLevel(value);
} /**
* This method calls all configured adaptor hook {@link AdaptorHook#createFrameworkLog()} methods
* until the first one returns a non-null value. If none of the adaptor hooks return a non-null
* value then a framework log implementation which does nothing is returned.
* @see FrameworkAdaptor#getFrameworkLog()
*/
public FrameworkLog getFrameworkLog() {
if (log != null)
return log;
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++) {
log = adaptorHooks[i].createFrameworkLog();
if (log != null)
return log;
}
log = new FrameworkLog() {
public void log(FrameworkEvent frameworkEvent) {
log(new FrameworkLogEntry(frameworkEvent.getBundle().getSymbolicName() == null ? frameworkEvent.getBundle().getLocation() : frameworkEvent.getBundle().getSymbolicName(), FrameworkLogEntry.ERROR, 0, "FrameworkEvent.ERROR", 0, frameworkEvent.getThrowable(), null)); //$NON-NLS-1$
} public void log(FrameworkLogEntry logEntry) {
System.err.print(logEntry.getEntry() + " "); //$NON-NLS-1$
System.err.println(logEntry.getMessage());
if (logEntry.getThrowable() != null)
logEntry.getThrowable().printStackTrace(System.err);
} public void setWriter(Writer newWriter, boolean append) {
// do nothing
} /**
* @throws IOException
*/
public void setFile(File newFile, boolean append) throws IOException {
// do nothing
} public File getFile() {
// do nothing
return null;
} public void setConsoleLog(boolean consoleLog) {
// do nothing
} public void close() {
// do nothing
}
};
return log;
} /**
* @see FrameworkAdaptor#createSystemBundleData()
*/
public BundleData createSystemBundleData() throws BundleException {
return new SystemBundleData(this);
} /**
* @see FrameworkAdaptor#getBundleWatcher()
*/
public BundleWatcher getBundleWatcher() {
if (bundleWatcher != null)
return bundleWatcher;
final BundleWatcher[] watchers = hookRegistry.getWatchers();
if (watchers.length == 0)
return null;
bundleWatcher = new BundleWatcher() {
public void watchBundle(Bundle bundle, int type) {
for (int i = 0; i < watchers.length; i++)
watchers[i].watchBundle(bundle, type);
}
};
return bundleWatcher;
} /**
* @see FrameworkAdaptor#getPlatformAdmin()
*/
public PlatformAdmin getPlatformAdmin() {
return storage.getStateManager();
} /**
* @see FrameworkAdaptor#getState()
*/
public State getState() {
return storage.getStateManager().getSystemState();
} /**
* This method calls all the configured classloading hooks {@link ClassLoadingHook#getBundleClassLoaderParent()} methods
* until one returns a non-null value.
* @see FrameworkAdaptor#getBundleClassLoaderParent()
*/
public ClassLoader getBundleClassLoaderParent() {
// ask the configured adaptor hooks first
ClassLoader result = null;
ClassLoadingHook[] cpManagerHooks = getHookRegistry().getClassLoadingHooks();
for (int i = 0; i < cpManagerHooks.length; i++) {
result = cpManagerHooks[i].getBundleClassLoaderParent();
if (result != null)
return result;
}
// none of the configured adaptor hooks gave use a parent loader; use the default
return bundleClassLoaderParent;
} /**
* This method calls all the configured adaptor hooks {@link AdaptorHook#handleRuntimeError(Throwable)} methods.
* @see FrameworkAdaptor#handleRuntimeError(Throwable)
*/
public void handleRuntimeError(Throwable error) {
AdaptorHook[] adaptorHooks = getHookRegistry().getAdaptorHooks();
for (int i = 0; i < adaptorHooks.length; i++)
adaptorHooks[i].handleRuntimeError(error);
} /**
* Returns true if the {@link #frameworkStopping(BundleContext)} method has been called
* @return true if the framework is stopping
*/
public boolean isStopping() {
return stopping;
} /**
* Returns the event publisher for this BaseAdaptor
* @return the event publisher for this BaseAdaptor
*/
public EventPublisher getEventPublisher() {
return eventPublisher;
} /**
* Returns the <code>HookRegistry</code> object for this adaptor.
* @return the <code>HookRegistry</code> object for this adaptor.
*/
public HookRegistry getHookRegistry() {
return hookRegistry;
} /**
* Returns the system bundle's context
* @return the system bundle's context
*/
public BundleContext getContext() {
return context;
} /**
* Returns the bundle with the specified identifier. This method
* does not invoke and bundle find hooks and therefore does not
* allow bundle find hooks to hide a bundle from the caller.
*
* @param id The identifier of the bundle to retrieve.
* @return A {@code Bundle} object or {@code null} if the identifier does
* not match any installed bundle.
*/
public Bundle getBundle(long id) {
return eventPublisher.getBundle(id);
} /**
* Creates a bundle file object for the given content and base data.
* This method must delegate to each configured bundle file factory
* {@link BundleFileFactoryHook#createBundleFile(Object, BaseData, boolean)} method until one
* factory returns a non-null value. If no bundle file factory returns a non-null value
* then the the default behavior will be performed.
* <p>
* If the specified content is <code>null</code> then the base content of the specified
* bundledata must be found before calling any bundle file factories.
* </p>
* <p>
* After the bundle file has been created each configured bundle file wrapper factory
* {@link BundleFileWrapperFactoryHook#wrapBundleFile(BundleFile, Object, BaseData, boolean)}
* method is called to wrap the bundle file.
* </p>
* @param content The object which contains the content of a bundle file. A value of
* <code>null</code> indicates that the storage must find the base content for the
* specified BaseData.
* @param data The BaseData associated with the content
* @return a BundleFile object.
* @throws IOException if an error occured while creating the BundleFile
*/
public BundleFile createBundleFile(Object content, BaseData data) throws IOException {
return storage.createBundleFile(content, data);
} /**
* Returns true if the persistent storage is read-only
* @return true if the persistent storage is read-only
*/
public boolean isReadOnly() {
return storage.isReadOnly();
} /*
* This is an experimental method to allow adaptors to replace the storage implementation by
* extending BaseAdaptor and overriding this method. This method is experimental.
* @return a base storage object.
*/
protected BaseStorage getStorage() {
if (storage != null)
return storage;
// this bit of code assumes the registry is initialized with a BaseStorageHook
// we want to make sure we are using the same BaseStorage instance as the BaseStorageHook
StorageHook[] hooks = hookRegistry.getStorageHooks();
for (int i = 0; i < hooks.length && storage == null; i++)
if (hooks[i] instanceof BaseStorageHook)
storage = ((BaseStorageHook) hooks[i]).getStorage();
return storage;
} /**
* @see FrameworkAdaptor#findEntries(List, String, String, int)
*/
public Enumeration<URL> findEntries(List<BundleData> datas, String path, String filePattern, int options) {
List<BundleFile> bundleFiles = new ArrayList<BundleFile>(datas.size());
for (BundleData data : datas)
bundleFiles.add(((BaseData) data).getBundleFile());
// search all the bundle files
List<String> pathList = listEntryPaths(bundleFiles, path, filePattern, options);
// return null if no entries found
if (pathList.size() == 0)
return null;
// create an enumeration to enumerate the pathList
final String[] pathArray = pathList.toArray(new String[pathList.size()]);
final BundleData[] dataArray = datas.toArray(new BundleData[datas.size()]);
return new Enumeration<URL>() {
private int curPathIndex = 0;
private int curDataIndex = 0;
private URL nextElement = null; public boolean hasMoreElements() {
if (nextElement != null)
return true;
getNextElement();
return nextElement != null;
} public URL nextElement() {
if (!hasMoreElements())
throw new NoSuchElementException();
URL result = nextElement;
// force the next element search
getNextElement();
return result;
} private void getNextElement() {
nextElement = null;
if (curPathIndex >= pathArray.length)
// reached the end of the pathArray; no more elements
return;
while (nextElement == null && curPathIndex < pathArray.length) {
String curPath = pathArray[curPathIndex];
// search the datas until we have searched them all
while (nextElement == null && curDataIndex < dataArray.length)
nextElement = dataArray[curDataIndex++].getEntry(curPath);
// we have searched all datas then advance to the next path
if (curDataIndex >= dataArray.length) {
curPathIndex++;
curDataIndex = 0;
}
}
}
};
} /**
* Returns the names of resources available from a list of bundle files.
* No duplicate resource names are returned, each name is unique.
* @param bundleFiles the list of bundle files to search in
* @param path The path name in which to look.
* @param filePattern The file name pattern for selecting resource names in
* the specified path.
* @param options The options for listing resource names.
* @return a list of resource names. If no resources are found then
* the empty list is returned.
* @see BundleWiring#listResources(String, String, int)
*/
public List<String> listEntryPaths(List<BundleFile> bundleFiles, String path, String filePattern, int options) {
// a list used to store the results of the search
List<String> pathList = new ArrayList<String>();
Filter patternFilter = null;
Hashtable<String, String> patternProps = null;
if (filePattern != null) {
// Optimization: If the file pattern does not include a wildcard or escape char then it must represent a single file.
// Avoid pattern matching and use BundleFile.getEntry() if recursion was not requested.
if ((options & BundleWiring.FINDENTRIES_RECURSE) == 0 && filePattern.indexOf('*') == -1 && filePattern.indexOf('\\') == -1) {
if (path.length() == 0)
path = filePattern;
else
path += path.charAt(path.length() - 1) == '/' ? filePattern : '/' + filePattern;
for (BundleFile bundleFile : bundleFiles) {
if (bundleFile.getEntry(path) != null && !pathList.contains(path))
pathList.add(path);
}
return pathList;
}
// For when the file pattern includes a wildcard.
try {
// create a file pattern filter with 'filename' as the key
patternFilter = FilterImpl.newInstance("(filename=" + sanitizeFilterInput(filePattern) + ")"); //$NON-NLS-1$ //$NON-NLS-2$
// create a single hashtable to be shared during the recursive search
patternProps = new Hashtable<String, String>(2);
} catch (InvalidSyntaxException e) {
// something unexpected happened; log error and return nothing
Bundle b = context == null ? null : context.getBundle();
eventPublisher.publishFrameworkEvent(FrameworkEvent.ERROR, b, e);
return pathList;
}
}
// find the entry paths for the datas
for (BundleFile bundleFile : bundleFiles) {
listEntryPaths(bundleFile, path, patternFilter, patternProps, options, pathList);
}
return pathList;
} private String sanitizeFilterInput(String filePattern) throws InvalidSyntaxException {
StringBuffer buffer = null;
boolean foundEscape = false;
for (int i = 0; i < filePattern.length(); i++) {
char c = filePattern.charAt(i);
switch (c) {
case '\\' :
// we either used the escape found or found a new escape.
foundEscape = foundEscape ? false : true;
if (buffer != null)
buffer.append(c);
break;
case '(' :
case ')' :
if (!foundEscape) {
if (buffer == null) {
buffer = new StringBuffer(filePattern.length() + 16);
buffer.append(filePattern.substring(0, i));
}
// must escape with '\'
buffer.append('\\');
} else {
foundEscape = false; // used the escape found
}
if (buffer != null)
buffer.append(c);
break;
default :
// if we found an escape it has been used
foundEscape = false;
if (buffer != null)
buffer.append(c);
break;
}
}
if (foundEscape)
throw new InvalidSyntaxException("Trailing escape characters must be escaped.", filePattern); //$NON-NLS-1$
return buffer == null ? filePattern : buffer.toString();
} private List<String> listEntryPaths(BundleFile bundleFile, String path, Filter patternFilter, Hashtable<String, String> patternProps, int options, List<String> pathList) {
if (pathList == null)
pathList = new ArrayList<String>();
Enumeration<String> entryPaths = bundleFile.getEntryPaths(path);
if (entryPaths == null)
return pathList;
while (entryPaths.hasMoreElements()) {
String entry = entryPaths.nextElement();
int lastSlash = entry.lastIndexOf('/');
if (patternProps != null) {
int secondToLastSlash = entry.lastIndexOf('/', lastSlash - 1);
int fileStart;
int fileEnd = entry.length();
if (lastSlash < 0)
fileStart = 0;
else if (lastSlash != entry.length() - 1)
fileStart = lastSlash + 1;
else {
fileEnd = lastSlash; // leave the lastSlash out
if (secondToLastSlash < 0)
fileStart = 0;
else
fileStart = secondToLastSlash + 1;
}
String fileName = entry.substring(fileStart, fileEnd);
// set the filename to the current entry
patternProps.put("filename", fileName); //$NON-NLS-1$
}
// prevent duplicates and match on the patternFilter
if (!pathList.contains(entry) && (patternFilter == null || patternFilter.matchCase(patternProps)))
pathList.add(entry);
// recurse only into entries that are directories
if (((options & BundleWiring.FINDENTRIES_RECURSE) != 0) && !entry.equals(path) && entry.length() > 0 && lastSlash == (entry.length() - 1))
listEntryPaths(bundleFile, entry, patternFilter, patternProps, options, pathList);
}
return pathList;
} }
BaseAdaptor
private static FrameworkAdaptor createAdaptor() throws Exception {
String adaptorClassName = FrameworkProperties.getProperty(PROP_ADAPTOR, DEFAULT_ADAPTOR_CLASS);
Class<?> adaptorClass = Class.forName(adaptorClassName);
Class<?>[] constructorArgs = new Class[] {String[].class};
Constructor<?> constructor = adaptorClass.getConstructor(constructorArgs);
return (FrameworkAdaptor) constructor.newInstance(new Object[] {new String[0]});
}- Create a new Framework
framework = new Framework(adaptor);
/*******************************************************************************
* Copyright (c) 2003, 2012 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.osgi.framework.internal.core; import java.io.*;
import java.lang.reflect.*;
import java.net.*;
import java.security.*;
import java.util.*;
import org.eclipse.core.runtime.internal.adaptor.ContextFinder;
import org.eclipse.osgi.baseadaptor.BaseAdaptor;
import org.eclipse.osgi.framework.adaptor.*;
import org.eclipse.osgi.framework.debug.Debug;
import org.eclipse.osgi.framework.eventmgr.*;
import org.eclipse.osgi.framework.internal.protocol.ContentHandlerFactory;
import org.eclipse.osgi.framework.internal.protocol.StreamHandlerFactory;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.SecureAction;
import org.eclipse.osgi.internal.loader.*;
import org.eclipse.osgi.internal.permadmin.EquinoxSecurityManager;
import org.eclipse.osgi.internal.permadmin.SecurityAdmin;
import org.eclipse.osgi.internal.profile.Profile;
import org.eclipse.osgi.internal.serviceregistry.*;
import org.eclipse.osgi.signedcontent.SignedContentFactory;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.framework.hooks.bundle.*;
import org.osgi.util.tracker.ServiceTracker; /**
* Core OSGi Framework class.
*/
public class Framework implements EventPublisher, Runnable {
// System property used to set the context classloader parent classloader type (ccl is the default)
private static final String PROP_CONTEXTCLASSLOADER_PARENT = "osgi.contextClassLoaderParent"; //$NON-NLS-1$
private static final String CONTEXTCLASSLOADER_PARENT_APP = "app"; //$NON-NLS-1$
private static final String CONTEXTCLASSLOADER_PARENT_EXT = "ext"; //$NON-NLS-1$
private static final String CONTEXTCLASSLOADER_PARENT_BOOT = "boot"; //$NON-NLS-1$
private static final String CONTEXTCLASSLOADER_PARENT_FWK = "fwk"; //$NON-NLS-1$ public static final String PROP_FRAMEWORK_THREAD = "osgi.framework.activeThreadType"; //$NON-NLS-1$
public static final String THREAD_NORMAL = "normal"; //$NON-NLS-1$
public static final String PROP_EQUINOX_SECURITY = "eclipse.security"; //$NON-NLS-1$
public static final String SECURITY_OSGI = "osgi"; //$NON-NLS-1$ private static String J2SE = "J2SE-"; //$NON-NLS-1$
private static String JAVASE = "JavaSE-"; //$NON-NLS-1$
private static String PROFILE_EXT = ".profile"; //$NON-NLS-1$
/** FrameworkAdaptor specific functions. */
protected FrameworkAdaptor adaptor;
/** Framework properties object. A reference to the
* System.getProperies() object. The properties from
* the adaptor will be merged into these properties.
*/
protected Properties properties;
/** Has the framework been started */
protected boolean active;
/** Event indicating the reason for shutdown*/
private FrameworkEvent[] shutdownEvent;
/** The bundles installed in the framework */
protected BundleRepository bundles;
/** Package Admin object. This object manages the exported packages. */
protected PackageAdminImpl packageAdmin;
/** PermissionAdmin and ConditionalPermissionAdmin impl. This object manages the bundle permissions. */
protected SecurityAdmin securityAdmin;
/** Startlevel object. This object manages the framework and bundle startlevels */
protected StartLevelManager startLevelManager;
/** The ServiceRegistry */
private ServiceRegistry serviceRegistry;
private final int BSN_VERSION;
private static final int BSN_VERSION_SINGLE = 1;
private static final int BSN_VERSION_MULTIPLE = 2;
private static final int BSN_VERSION_MANAGED = 3; /*
* The following maps objects keep track of event listeners
* by BundleContext. Each element is a Map that is the set
* of event listeners for a particular BundleContext. The max number of
* elements each of the following maps will have is the number of bundles
* installed in the Framework.
*/
// Map of BundleContexts for bundle's BundleListeners.
private final Map<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> allBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>>();
protected static final int BUNDLEEVENT = 1;
// Map of BundleContexts for bundle's SynchronousBundleListeners.
private final Map<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> allSyncBundleListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>>();
protected static final int BUNDLEEVENTSYNC = 2;
/* SERVICEEVENT(3) is now handled by ServiceRegistry */
// Map of BundleContexts for bundle's FrameworkListeners.
private final Map<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> allFrameworkListeners = new HashMap<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>>();
protected static final int FRAMEWORKEVENT = 4;
protected static final int BATCHEVENT_BEGIN = Integer.MIN_VALUE + 1;
protected static final int BATCHEVENT_END = Integer.MIN_VALUE;
static final String eventHookName = EventHook.class.getName();
static final String findHookName = FindHook.class.getName();
static final String collisionHookName = CollisionHook.class.getName();
/** EventManager for event delivery. */
protected EventManager eventManager;
/* Reservation object for install synchronization */
private Map<String, Thread> installLock;
/** System Bundle object */
protected InternalSystemBundle systemBundle;
private String[] bootDelegation;
private String[] bootDelegationStems;
private boolean bootDelegateAll = false;
public final boolean contextBootDelegation = "true".equals(FrameworkProperties.getProperty("osgi.context.bootdelegation", "true")); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
public final boolean compatibiltyBootDelegation = "true".equals(FrameworkProperties.getProperty(Constants.OSGI_COMPATIBILITY_BOOTDELEGATION, "true")); //$NON-NLS-1$ //$NON-NLS-2$
private final boolean allowRefreshDuplicateBSN = Boolean.TRUE.toString().equals(FrameworkProperties.getProperty(Constants.REFRESH_DUPLICATE_BSN, "true")); //$NON-NLS-1$
ClassLoaderDelegateHook[] delegateHooks;
private volatile boolean forcedRestart = false;
/**
* The AliasMapper used to alias OS Names.
*/
protected static AliasMapper aliasMapper = new AliasMapper();
SecureAction secureAction = AccessController.doPrivileged(SecureAction.createSecureAction());
// cache of AdminPermissions keyed by Bundle ID
private final Map<Long, Map<String, AdminPermission>> adminPermissions = new HashMap<Long, Map<String, AdminPermission>>(); // we need to hold these so that we can unregister them at shutdown
private StreamHandlerFactory streamHandlerFactory;
private ContentHandlerFactory contentHandlerFactory; private volatile ServiceTracker<SignedContentFactory, SignedContentFactory> signedContentFactory;
private volatile ContextFinder contextFinder; /*
* We need to make sure that the GetDataFileAction class loads early to prevent a ClassCircularityError when checking permissions.
* see bug 161561
*/
static {
Class<?> c;
c = GetDataFileAction.class;
c.getName(); // to prevent compiler warnings
} static class GetDataFileAction implements PrivilegedAction<File> {
private AbstractBundle bundle;
private String filename; public GetDataFileAction(AbstractBundle bundle, String filename) {
this.bundle = bundle;
this.filename = filename;
} public File run() {
return bundle.getBundleData().getDataFile(filename);
}
} /**
* Constructor for the Framework instance. This method initializes the
* framework to an unlaunched state.
*
*/
public Framework(FrameworkAdaptor adaptor) {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("Framework.initialze()", null); //$NON-NLS-1$
String bsnVersion = FrameworkProperties.getProperty(Constants.FRAMEWORK_BSNVERSION);
if (Constants.FRAMEWORK_BSNVERSION_SINGLE.equals(bsnVersion)) {
BSN_VERSION = BSN_VERSION_SINGLE;
} else if (Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(bsnVersion)) {
BSN_VERSION = BSN_VERSION_MULTIPLE;
} else {
BSN_VERSION = BSN_VERSION_MANAGED;
}
long start = System.currentTimeMillis();
this.adaptor = adaptor;
delegateHooks = adaptor instanceof BaseAdaptor ? ((BaseAdaptor) adaptor).getHookRegistry().getClassLoaderDelegateHooks() : null;
active = false;
installSecurityManager();
if (Debug.DEBUG_SECURITY) {
Debug.println("SecurityManager: " + System.getSecurityManager()); //$NON-NLS-1$
Debug.println("ProtectionDomain of Framework.class: \n" + this.getClass().getProtectionDomain()); //$NON-NLS-1$
}
setNLSFrameworkLog();
// initialize ContextFinder
initializeContextFinder();
/* initialize the adaptor */
adaptor.initialize(this);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "adapter initialized"); //$NON-NLS-1$//$NON-NLS-2$
try {
adaptor.initializeStorage();
} catch (IOException e) /* fatal error */{
throw new RuntimeException(e.getMessage(), e);
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "adapter storage initialized"); //$NON-NLS-1$//$NON-NLS-2$
/*
* This must be done before calling any of the framework getProperty
* methods.
*/
initializeProperties(adaptor.getProperties());
/* initialize admin objects */
packageAdmin = new PackageAdminImpl(this);
try {
// always create security admin even with security off
securityAdmin = new SecurityAdmin(null, this, adaptor.getPermissionStorage());
} catch (IOException e) /* fatal error */{
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done init props & new PermissionAdminImpl"); //$NON-NLS-1$//$NON-NLS-2$
startLevelManager = new StartLevelManager(this);
/* create the event manager and top level event dispatchers */
eventManager = new EventManager("Framework Event Dispatcher"); //$NON-NLS-1$
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done new EventManager"); //$NON-NLS-1$ //$NON-NLS-2$
/* create the service registry */
serviceRegistry = new ServiceRegistry(this);
// Initialize the installLock; there is no way of knowing
// what the initial size should be, at most it will be the number
// of threads trying to install a bundle (probably a very low number).
installLock = new HashMap<String, Thread>(10);
/* create the system bundle */
createSystemBundle();
loadVMProfile(); // load VM profile after the system bundle has been created
setBootDelegation(); //set boot delegation property after system exports have been set
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done createSystemBundle"); //$NON-NLS-1$ //$NON-NLS-2$
/* install URLStreamHandlerFactory */
installURLStreamHandlerFactory(systemBundle.context, adaptor);
/* install ContentHandlerFactory for OSGi URLStreamHandler support */
installContentHandlerFactory(systemBundle.context, adaptor);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done new URLStream/Content HandlerFactory"); //$NON-NLS-1$//$NON-NLS-2$
/* create bundle objects for all installed bundles. */
BundleData[] bundleDatas = adaptor.getInstalledBundles();
bundles = new BundleRepository(bundleDatas == null ? 10 : bundleDatas.length + 1);
/* add the system bundle to the Bundle Repository */
bundles.add(systemBundle);
if (bundleDatas != null) {
for (int i = 0; i < bundleDatas.length; i++) {
try {
AbstractBundle bundle = AbstractBundle.createBundle(bundleDatas[i], this, true);
bundles.add(bundle);
} catch (BundleException be) {
// This is not a fatal error. Publish the framework event.
publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, be);
}
}
}
if (Debug.DEBUG_GENERAL)
System.out.println("Initialize the framework: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("Framework.initialize()"); //$NON-NLS-1$
} public FrameworkAdaptor getAdaptor() {
return adaptor;
} public ClassLoaderDelegateHook[] getDelegateHooks() {
return delegateHooks;
} public ServiceRegistry getServiceRegistry() {
return serviceRegistry;
} private void setNLSFrameworkLog() {
try {
Field frameworkLogField = NLS.class.getDeclaredField("frameworkLog"); //$NON-NLS-1$
frameworkLogField.setAccessible(true);
frameworkLogField.set(null, adaptor.getFrameworkLog());
} catch (Exception e) {
adaptor.getFrameworkLog().log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
}
} private void createSystemBundle() {
try {
systemBundle = new InternalSystemBundle(this);
systemBundle.getBundleData().setBundle(systemBundle);
} catch (BundleException e) { // fatal error
e.printStackTrace();
throw new RuntimeException(NLS.bind(Msg.OSGI_SYSTEMBUNDLE_CREATE_EXCEPTION, e.getMessage()), e);
}
} /**
* Initialize the System properties by copying properties from the adaptor
* properties object. This method is called by the initialize method.
*
*/
protected void initializeProperties(Properties adaptorProperties) {
properties = FrameworkProperties.getProperties();
Enumeration<?> enumKeys = adaptorProperties.propertyNames();
while (enumKeys.hasMoreElements()) {
String key = (String) enumKeys.nextElement();
if (properties.getProperty(key) == null) {
properties.put(key, adaptorProperties.getProperty(key));
}
}
properties.put(Constants.FRAMEWORK_VENDOR, Constants.OSGI_FRAMEWORK_VENDOR);
properties.put(Constants.FRAMEWORK_VERSION, Constants.OSGI_FRAMEWORK_VERSION);
String value = properties.getProperty(Constants.FRAMEWORK_PROCESSOR);
if (value == null) {
value = properties.getProperty(Constants.JVM_OS_ARCH);
if (value != null) {
properties.put(Constants.FRAMEWORK_PROCESSOR, aliasMapper.aliasProcessor(value));
}
}
value = properties.getProperty(Constants.FRAMEWORK_OS_NAME);
if (value == null) {
value = properties.getProperty(Constants.JVM_OS_NAME);
try {
String canonicalValue = (String) aliasMapper.aliasOSName(value);
if (canonicalValue != null) {
value = canonicalValue;
}
} catch (ClassCastException ex) {
//A vector was returned from the alias mapper.
//The alias mapped to more than one canonical value
//such as "win32" for example
}
if (value != null) {
properties.put(Constants.FRAMEWORK_OS_NAME, value);
}
}
value = properties.getProperty(Constants.FRAMEWORK_OS_VERSION);
if (value == null) {
value = properties.getProperty(Constants.JVM_OS_VERSION);
if (value != null) {
// only use the value upto the first space
int space = value.indexOf(' ');
if (space > 0) {
value = value.substring(0, space);
}
// fix up cases where the os version does not make a valid Version string.
int major = 0, minor = 0, micro = 0;
String qualifier = ""; //$NON-NLS-1$
try {
StringTokenizer st = new StringTokenizer(value, ".", true); //$NON-NLS-1$
major = parseVersionInt(st.nextToken()); if (st.hasMoreTokens()) {
st.nextToken(); // consume delimiter
minor = parseVersionInt(st.nextToken()); if (st.hasMoreTokens()) {
st.nextToken(); // consume delimiter
micro = parseVersionInt(st.nextToken()); if (st.hasMoreTokens()) {
st.nextToken(); // consume delimiter
qualifier = st.nextToken();
}
}
}
} catch (NoSuchElementException e) {
// ignore, use the values parsed so far
}
try {
value = new Version(major, minor, micro, qualifier).toString();
} catch (IllegalArgumentException e) {
// must be an invalid qualifier; just ignore it
value = new Version(major, minor, micro).toString();
}
properties.put(Constants.FRAMEWORK_OS_VERSION, value);
}
}
value = properties.getProperty(Constants.FRAMEWORK_LANGUAGE);
if (value == null)
// set the value of the framework language property
properties.put(Constants.FRAMEWORK_LANGUAGE, Locale.getDefault().getLanguage());
// set the support properties for fragments and require-bundle (bug 173090)
properties.put(Constants.SUPPORTS_FRAMEWORK_FRAGMENT, "true"); //$NON-NLS-1$
properties.put(Constants.SUPPORTS_FRAMEWORK_REQUIREBUNDLE, "true"); //$NON-NLS-1$
properties.put(Constants.FRAMEWORK_UUID, new UniversalUniqueIdentifier().toString());
} private int parseVersionInt(String value) {
try {
return Integer.parseInt(value);
} catch (NumberFormatException e) {
// try up to the first non-number char
StringBuffer sb = new StringBuffer(value.length());
char[] chars = value.toCharArray();
for (int i = 0; i < chars.length; i++) {
if (!Character.isDigit(chars[i]))
break;
sb.append(chars[i]);
}
if (sb.length() > 0)
return Integer.parseInt(sb.toString());
return 0;
}
} private void setBootDelegation() {
// set the boot delegation according to the osgi boot delegation property
String bootDelegationProp = properties.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
if (bootDelegationProp == null)
return;
if (bootDelegationProp.trim().length() == 0)
return;
String[] bootPackages = ManifestElement.getArrayFromList(bootDelegationProp);
List<String> exactMatch = new ArrayList<String>(bootPackages.length);
List<String> stemMatch = new ArrayList<String>(bootPackages.length);
for (int i = 0; i < bootPackages.length; i++) {
if (bootPackages[i].equals("*")) { //$NON-NLS-1$
bootDelegateAll = true;
return;
} else if (bootPackages[i].endsWith("*")) { //$NON-NLS-1$
if (bootPackages[i].length() > 2 && bootPackages[i].endsWith(".*")) //$NON-NLS-1$
stemMatch.add(bootPackages[i].substring(0, bootPackages[i].length() - 1));
} else {
exactMatch.add(bootPackages[i]);
}
}
if (!exactMatch.isEmpty())
bootDelegation = exactMatch.toArray(new String[exactMatch.size()]);
if (!stemMatch.isEmpty())
bootDelegationStems = stemMatch.toArray(new String[stemMatch.size()]);
} @SuppressWarnings("deprecation")
private void loadVMProfile() {
Properties profileProps = findVMProfile();
String systemExports = properties.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
// set the system exports property using the vm profile; only if the property is not already set
if (systemExports == null) {
systemExports = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMPACKAGES);
if (systemExports != null)
properties.put(Constants.FRAMEWORK_SYSTEMPACKAGES, systemExports);
}
// set the org.osgi.framework.bootdelegation property according to the java profile
String type = properties.getProperty(Constants.OSGI_JAVA_PROFILE_BOOTDELEGATION); // a null value means ignore
String profileBootDelegation = profileProps.getProperty(Constants.FRAMEWORK_BOOTDELEGATION);
if (Constants.OSGI_BOOTDELEGATION_OVERRIDE.equals(type)) {
if (profileBootDelegation == null)
properties.remove(Constants.FRAMEWORK_BOOTDELEGATION); // override with a null value
else
properties.put(Constants.FRAMEWORK_BOOTDELEGATION, profileBootDelegation); // override with the profile value
} else if (Constants.OSGI_BOOTDELEGATION_NONE.equals(type))
properties.remove(Constants.FRAMEWORK_BOOTDELEGATION); // remove the bootdelegation property in case it was set
// set the org.osgi.framework.executionenvironment property according to the java profile
if (properties.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT) == null) {
// get the ee from the java profile; if no ee is defined then try the java profile name
String ee = profileProps.getProperty(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, profileProps.getProperty(Constants.OSGI_JAVA_PROFILE_NAME));
if (ee != null)
properties.put(Constants.FRAMEWORK_EXECUTIONENVIRONMENT, ee);
}
// set the org.osgi.framework.system.capabilities property according to the java profile
if (properties.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES) == null) {
String systemCapabilities = profileProps.getProperty(Constants.FRAMEWORK_SYSTEMCAPABILITIES);
if (systemCapabilities != null)
properties.put(Constants.FRAMEWORK_SYSTEMCAPABILITIES, systemCapabilities);
}
} private Properties findVMProfile() {
Properties result = new Properties();
// Find the VM profile name using J2ME properties
String j2meConfig = properties.getProperty(Constants.J2ME_MICROEDITION_CONFIGURATION);
String j2meProfiles = properties.getProperty(Constants.J2ME_MICROEDITION_PROFILES);
String vmProfile = null;
String javaEdition = null;
Version javaVersion = null;
if (j2meConfig != null && j2meConfig.length() > 0 && j2meProfiles != null && j2meProfiles.length() > 0) {
// save the vmProfile based off of the config and profile
// use the last profile; assuming that is the highest one
String[] j2meProfileList = ManifestElement.getArrayFromList(j2meProfiles, " "); //$NON-NLS-1$
if (j2meProfileList != null && j2meProfileList.length > 0)
vmProfile = j2meConfig + '_' + j2meProfileList[j2meProfileList.length - 1];
} else {
// No J2ME properties; use J2SE properties
// Note that the CDC spec appears not to require VM implementations to set the
// javax.microedition properties!! So we will try to fall back to the
// java.specification.name property, but this is pretty ridiculous!!
String javaSpecVersion = properties.getProperty("java.specification.version"); //$NON-NLS-1$
// set the profile and EE based off of the java.specification.version
// TODO We assume J2ME Foundation and J2SE here. need to support other profiles J2EE ...
if (javaSpecVersion != null) {
StringTokenizer st = new StringTokenizer(javaSpecVersion, " _-"); //$NON-NLS-1$
javaSpecVersion = st.nextToken();
String javaSpecName = properties.getProperty("java.specification.name"); //$NON-NLS-1$
// See bug 291269 we check for Foundation Specification and Foundation Profile Specification
if (javaSpecName != null && (javaSpecName.indexOf("Foundation Specification") >= 0 || javaSpecName.indexOf("Foundation Profile Specification") >= 0)) //$NON-NLS-1$ //$NON-NLS-2$
vmProfile = "CDC-" + javaSpecVersion + "_Foundation-" + javaSpecVersion; //$NON-NLS-1$ //$NON-NLS-2$
else {
// look for JavaSE if 1.6 or greater; otherwise look for J2SE
Version v16 = new Version("1.6"); //$NON-NLS-1$
javaEdition = J2SE;
try {
javaVersion = new Version(javaSpecVersion);
if (v16.compareTo(javaVersion) <= 0)
javaEdition = JAVASE;
} catch (IllegalArgumentException e) {
// do nothing
}
vmProfile = javaEdition + javaSpecVersion;
}
}
}
URL url = null;
// check for the java profile property for a url
String propJavaProfile = FrameworkProperties.getProperty(Constants.OSGI_JAVA_PROFILE);
if (propJavaProfile != null)
try {
// we assume a URL
url = new URL(propJavaProfile);
} catch (MalformedURLException e1) {
// try using a relative path in the system bundle
url = findInSystemBundle(propJavaProfile);
}
if (url == null && vmProfile != null) {
// look for a profile in the system bundle based on the vm profile
String javaProfile = vmProfile + PROFILE_EXT;
url = findInSystemBundle(javaProfile);
if (url == null)
url = getNextBestProfile(javaEdition, javaVersion);
}
if (url == null)
// the profile url is still null then use the osgi min profile in OSGi by default
url = findInSystemBundle("OSGi_Minimum-1.2.profile"); //$NON-NLS-1$
if (url != null) {
InputStream in = null;
try {
in = url.openStream();
result.load(new BufferedInputStream(in));
} catch (IOException e) {
// TODO consider logging ...
} finally {
if (in != null)
try {
in.close();
} catch (IOException ee) {
// do nothing
}
}
}
// set the profile name if it does not provide one
if (result.getProperty(Constants.OSGI_JAVA_PROFILE_NAME) == null)
if (vmProfile != null)
result.put(Constants.OSGI_JAVA_PROFILE_NAME, vmProfile.replace('_', '/'));
else
// last resort; default to the absolute minimum profile name for the framework
result.put(Constants.OSGI_JAVA_PROFILE_NAME, "OSGi/Minimum-1.2"); //$NON-NLS-1$
return result;
} private URL getNextBestProfile(String javaEdition, Version javaVersion) {
if (javaVersion == null || (javaEdition != J2SE && javaEdition != JAVASE))
return null; // we cannot automatically choose the next best profile unless this is a J2SE or JavaSE vm
URL bestProfile = findNextBestProfile(javaEdition, javaVersion);
if (bestProfile == null && javaEdition == JAVASE)
// if this is a JavaSE VM then search for a lower J2SE profile
bestProfile = findNextBestProfile(J2SE, javaVersion);
return bestProfile;
} private URL findNextBestProfile(String javaEdition, Version javaVersion) {
URL result = null;
int minor = javaVersion.getMinor();
do {
result = findInSystemBundle(javaEdition + javaVersion.getMajor() + "." + minor + PROFILE_EXT); //$NON-NLS-1$
minor = minor - 1;
} while (result == null && minor > 0);
return result;
} private URL findInSystemBundle(String entry) {
URL result = systemBundle.getEntry0(entry);
if (result == null) {
// Check the ClassLoader in case we're launched off the Java boot classpath
ClassLoader loader = getClass().getClassLoader();
result = loader == null ? ClassLoader.getSystemResource(entry) : loader.getResource(entry);
}
return result;
} /**
* This method return the state of the framework.
*
*/
protected boolean isActive() {
return (active);
} /**
* This method is called to destory the framework instance.
*
*/
public synchronized void close() {
if (adaptor == null)
return;
if (active)
shutdown(FrameworkEvent.STOPPED); synchronized (bundles) {
List<AbstractBundle> allBundles = bundles.getBundles();
int size = allBundles.size();
for (int i = 0; i < size; i++) {
AbstractBundle bundle = allBundles.get(i);
bundle.close();
}
bundles.removeAllBundles();
}
serviceRegistry = null;
allBundleListeners.clear();
allSyncBundleListeners.clear();
allFrameworkListeners.clear();
if (eventManager != null) {
eventManager.close();
eventManager = null;
}
secureAction = null;
packageAdmin = null;
adaptor = null;
uninstallURLStreamHandlerFactory();
uninstallContentHandlerFactory();
if (System.getSecurityManager() instanceof EquinoxSecurityManager)
System.setSecurityManager(null);
} /**
* Start the framework.
*
* When the framework is started. The following actions occur: 1. Event
* handling is enabled. Events can now be delivered to listeners. 2. All
* bundles which are recorded as started are started as described in the
* Bundle.start() method. These bundles are the bundles that were started
* when the framework was last stopped. Reports any exceptions that occur
* during startup using FrameworkEvents. 3. A FrameworkEvent of type
* FrameworkEvent.STARTED is broadcast.
*
*/
public synchronized void launch() {
/* Return if framework already started */
if (active) {
return;
}
/* mark framework as started */
active = true;
shutdownEvent = new FrameworkEvent[1];
if (THREAD_NORMAL.equals(FrameworkProperties.getProperty(PROP_FRAMEWORK_THREAD, THREAD_NORMAL))) {
Thread fwkThread = new Thread(this, "Framework Active Thread"); //$NON-NLS-1$
fwkThread.setDaemon(false);
fwkThread.start();
}
/* Resume systembundle */
if (Debug.DEBUG_GENERAL) {
Debug.println("Trying to launch framework"); //$NON-NLS-1$
}
systemBundle.resume();
signedContentFactory = new ServiceTracker<SignedContentFactory, SignedContentFactory>(systemBundle.getBundleContext(), SignedContentFactory.class.getName(), null);
signedContentFactory.open();
} /**
* Stop the framework.
*
* When the framework is stopped. The following actions occur: 1. Suspend
* all started bundles as described in the Bundle.stop method except that
* the bundle is recorded as started. These bundles will be restarted when
* the framework is next started. Reports any exceptions that occur during
* stopping using FrameworkEvents. 2. Event handling is disabled.
*
*/
public synchronized void shutdown(int eventType) {
/* Return if framework already stopped */
if (!active)
return;
this.shutdownEvent[0] = new FrameworkEvent(eventType, systemBundle, null);
/*
* set the state of the System Bundle to STOPPING.
* this must be done first according to section 4.19.2 from the OSGi R3 spec.
*/
systemBundle.state = Bundle.STOPPING;
publishBundleEvent(BundleEvent.STOPPING, systemBundle); // need to send system bundle stopping event
/* call the FrameworkAdaptor.frameworkStopping method first */
try {
adaptor.frameworkStopping(systemBundle.getContext());
} catch (Throwable t) {
publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, t);
}
/* Suspend systembundle */
if (Debug.DEBUG_GENERAL) {
Debug.println("Trying to shutdown Framework"); //$NON-NLS-1$
}
systemBundle.suspend();
try {
adaptor.compactStorage();
} catch (IOException e) {
publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, e);
}
if (signedContentFactory != null)
signedContentFactory.close();
/* mark framework as stopped */
active = false;
notifyAll();
} /**
* Create a new Bundle object.
* @param bundledata the BundleData of the Bundle to create
*/
AbstractBundle createAndVerifyBundle(int operationType, Bundle target, BundleData bundledata, boolean setBundle) throws BundleException {
// Check for a bundle already installed with the same symbolic name and version.
if (BSN_VERSION != BSN_VERSION_MULTIPLE && bundledata.getSymbolicName() != null) {
List<AbstractBundle> installedBundles = getBundleBySymbolicName(bundledata.getSymbolicName(), bundledata.getVersion());
if (operationType == CollisionHook.UPDATING) {
installedBundles.remove(target);
}
if (BSN_VERSION == BSN_VERSION_MANAGED && !installedBundles.isEmpty()) {
notifyCollisionHooks(operationType, target, installedBundles);
}
if (!installedBundles.isEmpty()) {
Bundle installedBundle = installedBundles.iterator().next();
String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {installedBundle.getSymbolicName(), installedBundle.getVersion().toString(), installedBundle.getLocation()});
throw new DuplicateBundleException(msg, installedBundle);
}
}
return AbstractBundle.createBundle(bundledata, this, setBundle);
} private class DuplicateBundleException extends BundleException implements StatusException {
private static final long serialVersionUID = 135669822846323624L;
private transient Bundle duplicate; public DuplicateBundleException(String msg, Bundle duplicate) {
super(msg, BundleException.DUPLICATE_BUNDLE_ERROR);
this.duplicate = duplicate;
} public Object getStatus() {
return duplicate;
} public int getStatusCode() {
return StatusException.CODE_OK;
} } /**
* Retrieve the value of the named environment property. Values are
* provided for the following properties:
* <dl>
* <dt><code>org.osgi.framework.version</code>
* <dd>The version of the framework.
* <dt><code>org.osgi.framework.vendor</code>
* <dd>The vendor of this framework implementation.
* <dt><code>org.osgi.framework.language</code>
* <dd>The language being used. See ISO 639 for possible values.
* <dt><code>org.osgi.framework.os.name</code>
* <dd>The name of the operating system of the hosting computer.
* <dt><code>org.osgi.framework.os.version</code>
* <dd>The version number of the operating system of the hosting computer.
* <dt><code>org.osgi.framework.processor</code>
* <dd>The name of the processor of the hosting computer.
* </dl>
*
* <p>
* Note: These last four properties are used by the <code>Bundle-NativeCode</code>
* manifest header's matching algorithm for selecting native code.
*
* @param key
* The name of the requested property.
* @return The value of the requested property, or <code>null</code> if
* the property is undefined.
*/
public String getProperty(String key) {
return properties.getProperty(key);
} /**
* Retrieve the value of the named environment property. Values are
* provided for the following properties:
* <dl>
* <dt><code>org.osgi.framework.version</code>
* <dd>The version of the framework.
* <dt><code>org.osgi.framework.vendor</code>
* <dd>The vendor of this framework implementation.
* <dt><code>org.osgi.framework.language</code>
* <dd>The language being used. See ISO 639 for possible values.
* <dt><code>org.osgi.framework.os.name</code>
* <dd>The name of the operating system of the hosting computer.
* <dt><code>org.osgi.framework.os.version</code>
* <dd>The version number of the operating system of the hosting computer.
* <dt><code>org.osgi.framework.processor</code>
* <dd>The name of the processor of the hosting computer.
* </dl>
*
* <p>
* Note: These last four properties are used by the <code>Bundle-NativeCode</code>
* manifest header's matching algorithm for selecting native code.
*
* @param key
* The name of the requested property.
* @param def
* A default value is the requested property is not present.
* @return The value of the requested property, or the default value if the
* property is undefined.
*/
protected String getProperty(String key, String def) {
return properties.getProperty(key, def);
} /**
* Set a system property.
*
* @param key
* The name of the property to set.
* @param value
* The value to set.
* @return The previous value of the property or null if the property was
* not previously set.
*/
protected Object setProperty(String key, String value) {
return properties.put(key, value);
} /**
* Install a bundle from an InputStream.
*
* @param location
* The location identifier of the bundle to install.
* @param in
* The InputStream from which the bundle will be read. If null
* then the location is used to get the bundle content.
* @return The Bundle of the installed bundle.
*/
AbstractBundle installBundle(final String location, final InputStream in, final BundleContextImpl origin) throws BundleException {
if (Debug.DEBUG_GENERAL) {
Debug.println("install from inputstream: " + location + ", " + in); //$NON-NLS-1$ //$NON-NLS-2$
}
final AccessControlContext callerContext = AccessController.getContext();
return installWorker(location, new PrivilegedExceptionAction<AbstractBundle>() {
public AbstractBundle run() throws BundleException {
/* Map the InputStream or location to a URLConnection */
URLConnection source = in != null ? new BundleSource(in) : adaptor.mapLocationToURLConnection(location);
/* call the worker to install the bundle */
return installWorkerPrivileged(location, source, callerContext, origin);
}
}, origin);
} /**
* Worker method to install a bundle. It obtains the reservation for the
* location and calls the specified action.
*
* @param location
* The location identifier of the bundle to install.
* @param action
* A PrivilegedExceptionAction which calls the real worker.
* @return The {@link AbstractBundle}of the installed bundle.
* @exception BundleException
* If the action throws an error.
*/
protected AbstractBundle installWorker(String location, PrivilegedExceptionAction<AbstractBundle> action, BundleContext origin) throws BundleException {
synchronized (installLock) {
while (true) {
/* Check that the bundle is not already installed. */
AbstractBundle bundle = getBundleByLocation(location);
/* If already installed, return bundle object */
if (bundle != null) {
Bundle visible = origin.getBundle(bundle.getBundleId());
if (visible == null) {
BundleData data = bundle.getBundleData();
String msg = NLS.bind(Msg.BUNDLE_INSTALL_SAME_UNIQUEID, new Object[] {data.getSymbolicName(), data.getVersion().toString(), data.getLocation()});
throw new BundleException(msg, BundleException.REJECTED_BY_HOOK);
}
return bundle;
}
Thread current = Thread.currentThread();
/* Check for and make reservation */
Thread reservation = installLock.put(location, current);
/* if the location is not already reserved */
if (reservation == null) {
/* we have made the reservation and can continue */
break;
}
/* the location was already reserved */
/*
* If the reservation is held by the current thread, we have
* recursed to install the same bundle!
*/
if (current.equals(reservation)) {
throw new BundleException(Msg.BUNDLE_INSTALL_RECURSION_EXCEPTION, BundleException.STATECHANGE_ERROR);
}
try {
/* wait for the reservation to be released */
installLock.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
throw new BundleException("Thread has been interrupted while waiting for the location lock.", e); //$NON-NLS-1$
}
}
}
/* Don't call adaptor while holding the install lock */
try {
AbstractBundle bundle = AccessController.doPrivileged(action);
publishBundleEvent(new BundleEvent(BundleEvent.INSTALLED, bundle, origin.getBundle()));
return bundle;
} catch (PrivilegedActionException e) {
if (e.getException() instanceof RuntimeException)
throw (RuntimeException) e.getException();
throw (BundleException) e.getException();
} finally {
synchronized (installLock) {
/* release reservation */
installLock.remove(location);
/* wake up all waiters */
installLock.notifyAll();
}
}
} /**
* Worker method to install a bundle. It calls the FrameworkAdaptor object
* to install the bundle in persistent storage.
*
* @param location
* The location identifier of the bundle to install.
* @param source
* The URLConnection from which the bundle will be read.
* @param callerContext
* The caller access control context
* @param origin
* The origin bundle context that is installing the the bundle
* @return The {@link AbstractBundle}of the installed bundle.
* @exception BundleException
* If the provided stream cannot be read.
*/
protected AbstractBundle installWorkerPrivileged(String location, URLConnection source, AccessControlContext callerContext, BundleContextImpl origin) throws BundleException {
BundleOperation storage = adaptor.installBundle(location, source);
final AbstractBundle bundle;
try {
BundleData bundledata = storage.begin();
bundle = createAndVerifyBundle(CollisionHook.INSTALLING, origin.getBundle(), bundledata, true); BundleWatcher bundleStats = adaptor.getBundleWatcher();
if (bundleStats != null)
bundleStats.watchBundle(bundle, BundleWatcher.START_INSTALLING); try {
bundle.load();
if (System.getSecurityManager() != null) {
final boolean extension = (bundledata.getType() & (BundleData.TYPE_BOOTCLASSPATH_EXTENSION | BundleData.TYPE_FRAMEWORK_EXTENSION | BundleData.TYPE_EXTCLASSPATH_EXTENSION)) != 0;
// must check for AllPermission before allow a bundle extension to be installed
if (extension && !bundle.hasPermission(new AllPermission()))
throw new BundleException(Msg.BUNDLE_EXTENSION_PERMISSION, BundleException.SECURITY_ERROR, new SecurityException(Msg.BUNDLE_EXTENSION_PERMISSION));
try {
AccessController.doPrivileged(new PrivilegedExceptionAction<Object>() {
public Object run() throws Exception {
checkAdminPermission(bundle, AdminPermission.LIFECYCLE);
if (extension) // need special permission to install extension bundles
checkAdminPermission(bundle, AdminPermission.EXTENSIONLIFECYCLE);
return null;
}
}, callerContext);
} catch (PrivilegedActionException e) {
throw e.getException();
}
}
// must add the bundle before committing (bug 330905)
bundles.add(bundle);
storage.commit(false);
} catch (Throwable error) {
bundles.remove(bundle);
synchronized (bundles) {
bundle.unload();
}
bundle.close();
throw error;
} finally {
if (bundleStats != null)
bundleStats.watchBundle(bundle, BundleWatcher.END_INSTALLING);
} } catch (Throwable t) {
try {
storage.undo();
} catch (BundleException ee) {
publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, ee);
}
if (t instanceof SecurityException)
throw (SecurityException) t;
if (t instanceof BundleException)
throw (BundleException) t;
throw new BundleException(t.getMessage(), t);
}
return bundle;
} /**
* Retrieve the bundle that has the given unique identifier.
*
* @param id
* The identifier of the bundle to retrieve.
* @return A {@link AbstractBundle}object, or <code>null</code> if the
* identifier doesn't match any installed bundle.
*/
// changed visibility to gain access through the adaptor
public AbstractBundle getBundle(long id) {
synchronized (bundles) {
return bundles.getBundle(id);
}
} AbstractBundle getBundle(final BundleContextImpl context, long id) {
AbstractBundle bundle = getBundle(id);
// TODO we make the system bundle special because there are lots of places
// where we assume the system bundle can get all bundles
if (bundle == null || context.getBundle().getBundleId() == 0)
return bundle;
List<AbstractBundle> single = new ArrayList<AbstractBundle>(1);
single.add(bundle);
notifyFindHooks(context, single);
return single.size() == 0 ? null : bundle;
} public BundleContextImpl getSystemBundleContext() {
if (systemBundle == null)
return null;
return systemBundle.context;
} public PackageAdminImpl getPackageAdmin() {
return packageAdmin;
} /**
* Retrieve the bundles that has the given symbolic name and version.
*
* @param symbolicName
* The symbolic name of the bundle to retrieve
* @param version The version of the bundle to retrieve
* @return A collection of {@link AbstractBundle} that match the symbolic name and version
*/
public List<AbstractBundle> getBundleBySymbolicName(String symbolicName, Version version) {
synchronized (bundles) {
return bundles.getBundles(symbolicName, version);
}
} /**
* Retrieve the BundleRepository of all installed bundles. The list is
* valid at the time of the call to getBundles, but the framework is a very
* dynamic environment and bundles can be installed or uninstalled at
* anytime.
*
* @return The BundleRepository.
*/
protected BundleRepository getBundles() {
return (bundles);
} /**
* Retrieve a list of all installed bundles. The list is valid at the time
* of the call to getBundleAlls, but the framework is a very dynamic
* environment and bundles can be installed or uninstalled at anytime.
*
* @return An Array of {@link AbstractBundle}objects, one object per installed
* bundle.
*/
protected AbstractBundle[] getAllBundles() {
synchronized (bundles) {
List<AbstractBundle> allBundles = bundles.getBundles();
int size = allBundles.size();
if (size == 0) {
return (null);
}
AbstractBundle[] bundlelist = new AbstractBundle[size];
allBundles.toArray(bundlelist);
return (bundlelist);
}
} AbstractBundle[] getBundles(final BundleContextImpl context) {
List<AbstractBundle> allBundles;
synchronized (bundles) {
allBundles = new ArrayList<AbstractBundle>(bundles.getBundles());
}
notifyFindHooks(context, allBundles);
return allBundles.toArray(new AbstractBundle[allBundles.size()]);
} private void notifyFindHooks(final BundleContextImpl context, List<AbstractBundle> allBundles) {
final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(allBundles);
if (System.getSecurityManager() == null) {
notifyFindHooksPriviledged(context, shrinkable);
} else {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
notifyFindHooksPriviledged(context, shrinkable);
return null;
}
});
}
} void notifyFindHooksPriviledged(final BundleContextImpl context, final Collection<Bundle> allBundles) {
if (Debug.DEBUG_HOOKS) {
Debug.println("notifyBundleFindHooks(" + allBundles + ")"); //$NON-NLS-1$ //$NON-NLS-2$
}
getServiceRegistry().notifyHooksPrivileged(new HookContext() {
public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
if (hook instanceof FindHook) {
((FindHook) hook).find(context, allBundles);
}
} public String getHookClassName() {
return findHookName;
} public String getHookMethodName() {
return "find"; //$NON-NLS-1$
}
});
} private void notifyCollisionHooks(final int operationType, final Bundle target, List<AbstractBundle> collisionCandidates) {
final Collection<Bundle> shrinkable = new ShrinkableCollection<Bundle>(collisionCandidates);
if (System.getSecurityManager() == null) {
notifyCollisionHooksPriviledged(operationType, target, shrinkable);
} else {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
notifyCollisionHooksPriviledged(operationType, target, shrinkable);
return null;
}
});
}
} void notifyCollisionHooksPriviledged(final int operationType, final Bundle target, final Collection<Bundle> collisionCandidates) {
if (Debug.DEBUG_HOOKS) {
Debug.println("notifyCollisionHooks(" + operationType + ", " + target + ", " + collisionCandidates + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
}
getServiceRegistry().notifyHooksPrivileged(new HookContext() {
public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
if (hook instanceof CollisionHook) {
((CollisionHook) hook).filterCollisions(operationType, target, collisionCandidates);
}
} public String getHookClassName() {
return collisionHookName;
} public String getHookMethodName() {
return "filterCollisions"; //$NON-NLS-1$
}
});
} /**
* Resume a bundle.
*
* @param bundle
* Bundle to resume.
*/
protected void resumeBundle(AbstractBundle bundle) {
if (bundle.isActive()) {
// if bundle is active.
return;
}
try {
if (Debug.DEBUG_GENERAL) {
Debug.println("Trying to resume bundle " + bundle); //$NON-NLS-1$
}
bundle.resume();
} catch (BundleException be) {
if (Debug.DEBUG_GENERAL) {
Debug.println("Bundle resume exception: " + be.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
}
publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
}
} /**
* Suspend a bundle.
*
* @param bundle
* Bundle to suspend.
* @param lock
* true if state change lock should be held when returning from
* this method.
* @return true if bundle was active and is now suspended.
*/
protected boolean suspendBundle(AbstractBundle bundle, boolean lock) {
boolean changed = false;
if (!bundle.isActive() || bundle.isFragment()) {
// if bundle is not active or is a fragment then do nothing.
return changed;
}
try {
if (Debug.DEBUG_GENERAL) {
Debug.println("Trying to suspend bundle " + bundle); //$NON-NLS-1$
}
bundle.suspend(lock);
} catch (BundleException be) {
if (Debug.DEBUG_GENERAL) {
Debug.println("Bundle suspend exception: " + be.getMessage()); //$NON-NLS-1$
Debug.printStackTrace(be.getNestedException() == null ? be : be.getNestedException());
}
publishFrameworkEvent(FrameworkEvent.ERROR, bundle, be);
}
if (!bundle.isActive()) {
changed = true;
}
return (changed);
} /**
* Locate an installed bundle with a given identity.
*
* @param location
* string for the bundle
* @return Bundle object for bundle with the specified location or null if
* no bundle is installed with the specified location.
*/
protected AbstractBundle getBundleByLocation(String location) {
synchronized (bundles) {
// this is not optimized; do not think it will get called
// that much.
final String finalLocation = location; //Bundle.getLocation requires AdminPermission (metadata)
return AccessController.doPrivileged(new PrivilegedAction<AbstractBundle>() {
public AbstractBundle run() {
List<AbstractBundle> allBundles = bundles.getBundles();
int size = allBundles.size();
for (int i = 0; i < size; i++) {
AbstractBundle bundle = allBundles.get(i);
if (finalLocation.equals(bundle.getLocation())) {
return bundle;
}
}
return null;
}
});
}
} /**
* Locate an installed bundle with a given symbolic name
*
* @param symbolicName
* The symbolic name for the bundle
* @return Bundle object for bundle with the specified Unique or null if no
* bundle is installed with the specified symbolicName.
*/
protected AbstractBundle[] getBundleBySymbolicName(String symbolicName) {
synchronized (bundles) {
return bundles.getBundles(symbolicName);
}
} /**
* Creates a <code>File</code> object for a file in the persistent
* storage area provided for the bundle by the framework. If the adaptor
* does not have file system support, this method will return <code>null</code>.
*
* <p>
* A <code>File</code> object for the base directory of the persistent
* storage area provided for the context bundle by the framework can be
* obtained by calling this method with the empty string ("") as the
* parameter.
*/
protected File getDataFile(final AbstractBundle bundle, final String filename) {
return AccessController.doPrivileged(new GetDataFileAction(bundle, filename));
} /**
* Check for specific AdminPermission (RFC 73)
*/
protected void checkAdminPermission(Bundle bundle, String action) {
SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(getAdminPermission(bundle, action));
} // gets AdminPermission objects from a cache to reduce the number of AdminPermission
// objects that are created.
private AdminPermission getAdminPermission(Bundle bundle, String action) {
synchronized (adminPermissions) {
Long ID = new Long(bundle.getBundleId());
Map<String, AdminPermission> bundlePermissions = adminPermissions.get(ID);
if (bundlePermissions == null) {
bundlePermissions = new HashMap<String, AdminPermission>();
adminPermissions.put(ID, bundlePermissions);
}
AdminPermission result = bundlePermissions.get(action);
if (result == null) {
result = new AdminPermission(bundle, action);
bundlePermissions.put(action, result);
}
return result;
}
} /**
* This is necessary for running from a JXE, otherwise the SecurityManager
* is set much later than we would like!
*/
protected void installSecurityManager() {
String securityManager = FrameworkProperties.getProperty(Constants.FRAMEWORK_SECURITY, FrameworkProperties.getProperty(PROP_EQUINOX_SECURITY, FrameworkProperties.getProperty("java.security.manager")));
if (securityManager != null) {
SecurityManager sm = System.getSecurityManager();
if (sm == null) {
if (securityManager.length() == 0)
sm = new SecurityManager(); // use the default one from java
else if (securityManager.equals(SECURITY_OSGI))
sm = new EquinoxSecurityManager(); // use an OSGi enabled manager that understands postponed conditions
else {
// try to use a specific classloader by classname
try {
Class<?> clazz = Class.forName(securityManager);
sm = (SecurityManager) clazz.newInstance();
} catch (ClassNotFoundException e) {
// do nothing
} catch (ClassCastException e) {
// do nothing
} catch (InstantiationException e) {
// do nothing
} catch (IllegalAccessException e) {
// do nothing
}
}
if (sm == null)
throw new NoClassDefFoundError(securityManager);
if (Debug.DEBUG_SECURITY)
Debug.println("Setting SecurityManager to: " + sm); //$NON-NLS-1$
System.setSecurityManager(sm);
return;
}
}
} void addFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
synchronized (allFrameworkListeners) {
CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
if (listeners == null) {
listeners = new CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>();
allFrameworkListeners.put(context, listeners);
}
listeners.put(listener, listener);
}
} void removeFrameworkListener(FrameworkListener listener, BundleContextImpl context) {
synchronized (allFrameworkListeners) {
CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = allFrameworkListeners.get(context);
if (listeners != null)
listeners.remove(listener);
}
} void removeAllListeners(BundleContextImpl context) {
synchronized (allBundleListeners) {
allBundleListeners.remove(context);
}
synchronized (allSyncBundleListeners) {
allSyncBundleListeners.remove(context);
}
synchronized (allFrameworkListeners) {
allFrameworkListeners.remove(context);
}
} /**
* Deliver a FrameworkEvent.
*
* @param type
* FrameworkEvent type.
* @param bundle
* Affected bundle or null for system bundle.
* @param throwable
* Related exception or null.
*/
public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable) {
publishFrameworkEvent(type, bundle, throwable, (FrameworkListener[]) null);
} public void publishFrameworkEvent(int type, Bundle bundle, Throwable throwable, final FrameworkListener... listeners) {
if (bundle == null)
bundle = systemBundle;
final FrameworkEvent event = new FrameworkEvent(type, bundle, throwable);
if (System.getSecurityManager() == null) {
publishFrameworkEventPrivileged(event, listeners);
} else {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
publishFrameworkEventPrivileged(event, listeners);
return null;
}
});
}
} public void publishFrameworkEventPrivileged(FrameworkEvent event, FrameworkListener... callerListeners) {
// Build the listener snapshot
Map<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> listenerSnapshot;
synchronized (allFrameworkListeners) {
listenerSnapshot = new HashMap<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>>(allFrameworkListeners.size());
for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener>> entry : allFrameworkListeners.entrySet()) {
CopyOnWriteIdentityMap<FrameworkListener, FrameworkListener> listeners = entry.getValue();
if (!listeners.isEmpty()) {
listenerSnapshot.put(entry.getKey(), listeners.entrySet());
}
}
}
// If framework event hook were defined they would be called here // deliver the event to the snapshot
ListenerQueue<FrameworkListener, FrameworkListener, FrameworkEvent> queue = newListenerQueue(); // add the listeners specified by the caller first
if (callerListeners != null && callerListeners.length > 0) {
Map<FrameworkListener, FrameworkListener> listeners = new HashMap<FrameworkListener, FrameworkListener>();
for (FrameworkListener listener : callerListeners) {
if (listener != null)
listeners.put(listener, listener);
}
// We use the system bundle context as the dispatcher
if (listeners.size() > 0) {
@SuppressWarnings({"rawtypes", "unchecked"})
EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) getSystemBundleContext();
queue.queueListeners(listeners.entrySet(), dispatcher);
}
} for (Map.Entry<BundleContextImpl, Set<Map.Entry<FrameworkListener, FrameworkListener>>> entry : listenerSnapshot.entrySet()) {
@SuppressWarnings({"rawtypes", "unchecked"})
EventDispatcher<FrameworkListener, FrameworkListener, FrameworkEvent> dispatcher = (EventDispatcher) entry.getKey();
Set<Map.Entry<FrameworkListener, FrameworkListener>> listeners = entry.getValue();
queue.queueListeners(listeners, dispatcher);
} queue.dispatchEventAsynchronous(FRAMEWORKEVENT, event);
} void addBundleListener(BundleListener listener, BundleContextImpl context) {
if (listener instanceof SynchronousBundleListener) {
checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
synchronized (allSyncBundleListeners) {
CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
if (listeners == null) {
listeners = new CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>();
allSyncBundleListeners.put(context, listeners);
}
listeners.put((SynchronousBundleListener) listener, (SynchronousBundleListener) listener);
}
} else {
synchronized (allBundleListeners) {
CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
if (listeners == null) {
listeners = new CopyOnWriteIdentityMap<BundleListener, BundleListener>();
allBundleListeners.put(context, listeners);
}
listeners.put(listener, listener);
}
}
} void removeBundleListener(BundleListener listener, BundleContextImpl context) {
if (listener instanceof SynchronousBundleListener) {
checkAdminPermission(context.getBundle(), AdminPermission.LISTENER);
synchronized (allSyncBundleListeners) {
CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = allSyncBundleListeners.get(context);
if (listeners != null)
listeners.remove(listener);
}
} else {
synchronized (allBundleListeners) {
CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = allBundleListeners.get(context);
if (listeners != null)
listeners.remove(listener);
}
}
} /**
* Deliver a BundleEvent to SynchronousBundleListeners (synchronous). and
* BundleListeners (asynchronous).
*
* @param type
* BundleEvent type.
* @param bundle
* Affected bundle or null.
*/
public void publishBundleEvent(int type, Bundle bundle) {
publishBundleEvent(new BundleEvent(type, bundle));
} private void publishBundleEvent(final BundleEvent event) {
if (System.getSecurityManager() == null) {
publishBundleEventPrivileged(event);
} else {
AccessController.doPrivileged(new PrivilegedAction<Object>() {
public Object run() {
publishBundleEventPrivileged(event);
return null;
}
});
}
} public void publishBundleEventPrivileged(BundleEvent event) {
/*
* We must collect the snapshots of the sync and async listeners
* BEFORE we dispatch the event.
*/
/* Collect snapshot of SynchronousBundleListeners */
/* Build the listener snapshot */
Map<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> listenersSync;
synchronized (allSyncBundleListeners) {
listenersSync = new HashMap<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>>(allSyncBundleListeners.size());
for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener>> entry : allSyncBundleListeners.entrySet()) {
CopyOnWriteIdentityMap<SynchronousBundleListener, SynchronousBundleListener> listeners = entry.getValue();
if (!listeners.isEmpty()) {
listenersSync.put(entry.getKey(), listeners.entrySet());
}
}
}
/* Collect snapshot of BundleListeners; only if the event is NOT STARTING or STOPPING or LAZY_ACTIVATION */
Map<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> listenersAsync = null;
if ((event.getType() & (BundleEvent.STARTING | BundleEvent.STOPPING | BundleEvent.LAZY_ACTIVATION)) == 0) {
synchronized (allBundleListeners) {
listenersAsync = new HashMap<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>>(allBundleListeners.size());
for (Map.Entry<BundleContextImpl, CopyOnWriteIdentityMap<BundleListener, BundleListener>> entry : allBundleListeners.entrySet()) {
CopyOnWriteIdentityMap<BundleListener, BundleListener> listeners = entry.getValue();
if (!listeners.isEmpty()) {
listenersAsync.put(entry.getKey(), listeners.entrySet());
}
}
}
} /* shrink the snapshot.
* keySet returns a Collection which cannot be added to and
* removals from that collection will result in removals of the
* entry from the snapshot.
*/
Collection<BundleContext> shrinkable;
if (listenersAsync == null) {
shrinkable = asBundleContexts(listenersSync.keySet());
} else {
shrinkable = new ShrinkableCollection<BundleContext>(asBundleContexts(listenersSync.keySet()), asBundleContexts(listenersAsync.keySet()));
}
notifyEventHooksPrivileged(event, shrinkable); /* Dispatch the event to the snapshot for sync listeners */
if (!listenersSync.isEmpty()) {
ListenerQueue<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> queue = newListenerQueue();
for (Map.Entry<BundleContextImpl, Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>>> entry : listenersSync.entrySet()) {
@SuppressWarnings({"rawtypes", "unchecked"})
EventDispatcher<SynchronousBundleListener, SynchronousBundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
Set<Map.Entry<SynchronousBundleListener, SynchronousBundleListener>> listeners = entry.getValue();
queue.queueListeners(listeners, dispatcher);
}
queue.dispatchEventSynchronous(BUNDLEEVENTSYNC, event);
} /* Dispatch the event to the snapshot for async listeners */
if ((listenersAsync != null) && !listenersAsync.isEmpty()) {
ListenerQueue<BundleListener, BundleListener, BundleEvent> queue = newListenerQueue();
for (Map.Entry<BundleContextImpl, Set<Map.Entry<BundleListener, BundleListener>>> entry : listenersAsync.entrySet()) {
@SuppressWarnings({"rawtypes", "unchecked"})
EventDispatcher<BundleListener, BundleListener, BundleEvent> dispatcher = (EventDispatcher) entry.getKey();
Set<Map.Entry<BundleListener, BundleListener>> listeners = entry.getValue();
queue.queueListeners(listeners, dispatcher);
}
queue.dispatchEventAsynchronous(BUNDLEEVENT, event);
}
} /**
* Coerce the generic type of a collection from Collection<BundleContextImpl>
* to Collection<BundleContext>
* @param c Collection to be coerced.
* @return c coerced to Collection<BundleContext>
*/
@SuppressWarnings("unchecked")
public static Collection<BundleContext> asBundleContexts(Collection<? extends BundleContext> c) {
return (Collection<BundleContext>) c;
} private void notifyEventHooksPrivileged(final BundleEvent event, final Collection<BundleContext> result) {
if (event.getType() == Framework.BATCHEVENT_BEGIN || event.getType() == Framework.BATCHEVENT_END)
return; // we don't need to send this event; it is used to book case special listeners
if (Debug.DEBUG_HOOKS) {
Debug.println("notifyBundleEventHooks(" + event.getType() + ":" + event.getBundle() + ", " + result + " )"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
} getServiceRegistry().notifyHooksPrivileged(new HookContext() {
public void call(Object hook, ServiceRegistration<?> hookRegistration) throws Exception {
if (hook instanceof EventHook) {
((EventHook) hook).event(event, result);
}
} public String getHookClassName() {
return eventHookName;
} public String getHookMethodName() {
return "event"; //$NON-NLS-1$
}
});
} public <K, V, E> ListenerQueue<K, V, E> newListenerQueue() {
return new ListenerQueue<K, V, E>(eventManager);
} private void initializeContextFinder() {
Thread current = Thread.currentThread();
try {
ClassLoader parent = null;
// check property for specified parent
String type = FrameworkProperties.getProperty(PROP_CONTEXTCLASSLOADER_PARENT);
if (CONTEXTCLASSLOADER_PARENT_APP.equals(type))
parent = ClassLoader.getSystemClassLoader();
else if (CONTEXTCLASSLOADER_PARENT_BOOT.equals(type))
parent = null;
else if (CONTEXTCLASSLOADER_PARENT_FWK.equals(type))
parent = Framework.class.getClassLoader();
else if (CONTEXTCLASSLOADER_PARENT_EXT.equals(type)) {
ClassLoader appCL = ClassLoader.getSystemClassLoader();
if (appCL != null)
parent = appCL.getParent();
} else { // default is ccl (null or any other value will use ccl)
parent = current.getContextClassLoader();
}
contextFinder = new ContextFinder(parent);
current.setContextClassLoader(contextFinder);
return;
} catch (Exception e) {
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.INFO, 0, NLS.bind(Msg.CANNOT_SET_CONTEXTFINDER, null), 0, e, null);
adaptor.getFrameworkLog().log(entry);
} } public static Field getField(Class<?> clazz, Class<?> type, boolean instance) {
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
boolean isStatic = Modifier.isStatic(fields[i].getModifiers());
if (instance != isStatic && fields[i].getType().equals(type)) {
fields[i].setAccessible(true);
return fields[i];
}
}
return null;
} private void installContentHandlerFactory(BundleContext context, FrameworkAdaptor frameworkAdaptor) {
ContentHandlerFactory chf = new ContentHandlerFactory(context, frameworkAdaptor);
try {
// first try the standard way
URLConnection.setContentHandlerFactory(chf);
} catch (Error err) {
// ok we failed now use more drastic means to set the factory
try {
forceContentHandlerFactory(chf);
} catch (Exception ex) {
// this is unexpected, log the exception and throw the original error
adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), ex));
throw err;
}
}
contentHandlerFactory = chf;
} private static void forceContentHandlerFactory(ContentHandlerFactory chf) throws Exception {
Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
if (factoryField == null)
throw new Exception("Could not find ContentHandlerFactory field"); //$NON-NLS-1$
synchronized (URLConnection.class) {
java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null);
// doing a null check here just in case, but it would be really strange if it was null,
// because we failed to set the factory normally!! if (factory != null) {
try {
factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
register.invoke(factory, new Object[] {chf});
} catch (NoSuchMethodException e) {
// current factory does not support multiplexing, ok we'll wrap it
chf.setParentFactory(factory);
factory = chf;
}
}
// null out the field so that we can successfully call setContentHandlerFactory
factoryField.set(null, null);
// always attempt to clear the handlers cache
// This allows an optomization for the single framework use-case
resetContentHandlers();
URLConnection.setContentHandlerFactory(factory);
}
} private void uninstallContentHandlerFactory() {
try {
Field factoryField = getField(URLConnection.class, java.net.ContentHandlerFactory.class, false);
if (factoryField == null)
return; // oh well, we tried.
synchronized (URLConnection.class) {
java.net.ContentHandlerFactory factory = (java.net.ContentHandlerFactory) factoryField.get(null); if (factory == contentHandlerFactory) {
factory = (java.net.ContentHandlerFactory) contentHandlerFactory.designateSuccessor();
} else {
Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
unregister.invoke(factory, new Object[] {contentHandlerFactory});
}
// null out the field so that we can successfully call setContentHandlerFactory
factoryField.set(null, null);
// always attempt to clear the handlers cache
// This allows an optomization for the single framework use-case
// Note that the call to setContentHandlerFactory below may clear this cache
// but we want to be sure to clear it here just incase the parent is null.
// In this case the call below would not occur.
// Also it appears most java libraries actually do not clear the cache
// when setContentHandlerFactory is called, go figure!!
resetContentHandlers();
if (factory != null)
URLConnection.setContentHandlerFactory(factory);
}
} catch (Exception e) {
// ignore and continue closing the framework
}
} private static void resetContentHandlers() throws IllegalAccessException {
Field handlersField = getField(URLConnection.class, Hashtable.class, false);
if (handlersField != null) {
@SuppressWarnings("rawtypes")
Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
if (handlers != null)
handlers.clear();
}
} private void installURLStreamHandlerFactory(BundleContext context, FrameworkAdaptor frameworkAdaptor) {
StreamHandlerFactory shf = new StreamHandlerFactory(context, frameworkAdaptor);
try {
// first try the standard way
URL.setURLStreamHandlerFactory(shf);
} catch (Error err) {
try {
// ok we failed now use more drastic means to set the factory
forceURLStreamHandlerFactory(shf);
} catch (Exception ex) {
adaptor.getFrameworkLog().log(new FrameworkEvent(FrameworkEvent.ERROR, context.getBundle(), ex));
throw err;
}
}
streamHandlerFactory = shf;
} private static void forceURLStreamHandlerFactory(StreamHandlerFactory shf) throws Exception {
Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
if (factoryField == null)
throw new Exception("Could not find URLStreamHandlerFactory field"); //$NON-NLS-1$
// look for a lock to synchronize on
Object lock = getURLStreamHandlerFactoryLock();
synchronized (lock) {
URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
// doing a null check here just in case, but it would be really strange if it was null,
// because we failed to set the factory normally!!
if (factory != null) {
try {
factory.getClass().getMethod("isMultiplexing", (Class[]) null); //$NON-NLS-1$
Method register = factory.getClass().getMethod("register", new Class[] {Object.class}); //$NON-NLS-1$
register.invoke(factory, new Object[] {shf});
} catch (NoSuchMethodException e) {
// current factory does not support multiplexing, ok we'll wrap it
shf.setParentFactory(factory);
factory = shf;
}
}
factoryField.set(null, null);
// always attempt to clear the handlers cache
// This allows an optomization for the single framework use-case
resetURLStreamHandlers();
URL.setURLStreamHandlerFactory(factory);
}
} private void uninstallURLStreamHandlerFactory() {
try {
Field factoryField = getField(URL.class, URLStreamHandlerFactory.class, false);
if (factoryField == null)
return; // oh well, we tried
Object lock = getURLStreamHandlerFactoryLock();
synchronized (lock) {
URLStreamHandlerFactory factory = (URLStreamHandlerFactory) factoryField.get(null);
if (factory == streamHandlerFactory) {
factory = (URLStreamHandlerFactory) streamHandlerFactory.designateSuccessor();
} else {
Method unregister = factory.getClass().getMethod("unregister", new Class[] {Object.class}); //$NON-NLS-1$
unregister.invoke(factory, new Object[] {streamHandlerFactory});
}
factoryField.set(null, null);
// always attempt to clear the handlers cache
// This allows an optomization for the single framework use-case
// Note that the call to setURLStreamHandlerFactory below may clear this cache
// but we want to be sure to clear it here just in case the parent is null.
// In this case the call below would not occur.
resetURLStreamHandlers();
if (factory != null)
URL.setURLStreamHandlerFactory(factory);
}
} catch (Exception e) {
// ignore and continue closing the framework
}
} private static Object getURLStreamHandlerFactoryLock() throws IllegalAccessException {
Object lock;
try {
Field streamHandlerLockField = URL.class.getDeclaredField("streamHandlerLock"); //$NON-NLS-1$
streamHandlerLockField.setAccessible(true);
lock = streamHandlerLockField.get(null);
} catch (NoSuchFieldException noField) {
// could not find the lock, lets sync on the class object
lock = URL.class;
}
return lock;
} private static void resetURLStreamHandlers() throws IllegalAccessException {
Field handlersField = getField(URL.class, Hashtable.class, false);
if (handlersField != null) {
@SuppressWarnings("rawtypes")
Hashtable<?, ?> handlers = (Hashtable) handlersField.get(null);
if (handlers != null)
handlers.clear();
}
} /*
* (non-Javadoc)
* @see java.lang.Runnable#run()
* This thread monitors the framework active status and terminates when the framework is
* shutdown. This is needed to ensure the VM does not exist because of the lack of a
* non-daemon thread (bug 215730)
*/
public void run() {
synchronized (this) {
while (active)
try {
this.wait(1000);
} catch (InterruptedException e) {
// do nothing
}
}
} void setForcedRestart(boolean forcedRestart) {
this.forcedRestart = forcedRestart;
} boolean isForcedRestart() {
return forcedRestart;
} public FrameworkEvent waitForStop(long timeout) throws InterruptedException {
boolean waitForEver = timeout == 0;
long start = System.currentTimeMillis();
long timeLeft = timeout;
synchronized (this) {
FrameworkEvent[] event = shutdownEvent;
while (event != null && event[0] == null) {
this.wait(timeLeft);
if (!waitForEver) {
timeLeft = start + timeout - System.currentTimeMillis();
// break if we are passed the timeout
if (timeLeft <= 0)
break;
}
}
if (event == null || event[0] == null)
return new FrameworkEvent(FrameworkEvent.WAIT_TIMEDOUT, systemBundle, null);
return event[0];
}
} /**
* Used by ServiceReferenceImpl for isAssignableTo
* @param registrant Bundle registering service
* @param client Bundle desiring to use service
* @param className class name to use
* @param serviceClass class of original service object
* @return true if assignable given package wiring
*/
public boolean isServiceAssignableTo(Bundle registrant, Bundle client, String className, Class<?> serviceClass) {
// always return false for fragments
AbstractBundle consumer = (AbstractBundle) client;
if (consumer.isFragment())
return false;
// 1) if the registrant == consumer always return true
AbstractBundle producer = (AbstractBundle) registrant;
if (consumer == producer)
return true;
// 2) get the package name from the specified className
String pkgName = BundleLoader.getPackageName(className);
if (pkgName.startsWith("java.")) //$NON-NLS-1$
return true;
BundleLoader producerBL = producer.getBundleLoader();
if (producerBL == null)
return false;
BundleLoader consumerBL = consumer.getBundleLoader();
if (consumerBL == null)
return false;
// 3) for the specified bundle, find the wiring for the package. If no wiring is found return true
PackageSource consumerSource = consumerBL.getPackageSource(pkgName);
if (consumerSource == null)
return true;
// work around the issue when the package is in the EE and we delegate to boot for that package
if (isBootDelegationPackage(pkgName)) {
SystemBundleLoader systemLoader = (SystemBundleLoader) systemBundle.getBundleLoader();
if (systemLoader.isEEPackage(pkgName))
return true; // in this case we have a common source from the EE
}
// 4) For the registrant bundle, find the wiring for the package.
PackageSource producerSource = producerBL.getPackageSource(pkgName);
if (producerSource == null) {
if (serviceClass != null && ServiceFactory.class.isAssignableFrom(serviceClass)) {
Bundle bundle = packageAdmin.getBundle(serviceClass);
if (bundle != null && bundle != registrant)
// in this case we have a wacky ServiceFactory that is doing something we cannot
// verify if it is correct. Instead of failing we allow the assignment and hope for the best
// bug 326918
return true;
}
// 5) If no wiring is found for the registrant bundle then find the wiring for the classloader of the service object. If no wiring is found return false.
producerSource = getPackageSource(serviceClass, pkgName);
if (producerSource == null)
return false;
}
// 6) If the two wirings found are equal then return true; otherwise return false.
return producerSource.hasCommonSource(consumerSource);
} private PackageSource getPackageSource(Class<?> serviceClass, String pkgName) {
if (serviceClass == null)
return null;
AbstractBundle serviceBundle = (AbstractBundle) packageAdmin.getBundle(serviceClass);
if (serviceBundle == null)
return null;
BundleLoader producerBL = serviceBundle.getBundleLoader();
if (producerBL == null)
return null;
PackageSource producerSource = producerBL.getPackageSource(pkgName);
if (producerSource != null)
return producerSource;
// try the interfaces
Class<?>[] interfaces = serviceClass.getInterfaces();
// note that getInterfaces never returns null
for (int i = 0; i < interfaces.length; i++) {
producerSource = getPackageSource(interfaces[i], pkgName);
if (producerSource != null)
return producerSource;
}
// try super class
return getPackageSource(serviceClass.getSuperclass(), pkgName);
} public boolean isBootDelegationPackage(String name) {
if (bootDelegateAll)
return true;
if (bootDelegation != null)
for (int i = 0; i < bootDelegation.length; i++)
if (name.equals(bootDelegation[i]))
return true;
if (bootDelegationStems != null)
for (int i = 0; i < bootDelegationStems.length; i++)
if (name.startsWith(bootDelegationStems[i]))
return true;
return false;
} SignedContentFactory getSignedContentFactory() {
ServiceTracker<SignedContentFactory, SignedContentFactory> currentTracker = signedContentFactory;
return (currentTracker == null ? null : currentTracker.getService());
} ContextFinder getContextFinder() {
return contextFinder;
} public boolean isRefreshDuplicateBSNAllowed() {
return allowRefreshDuplicateBSN;
} }Framework
public Framework(FrameworkAdaptor adaptor) {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("Framework.initialze()", null); //$NON-NLS-1$
String bsnVersion = FrameworkProperties.getProperty(Constants.FRAMEWORK_BSNVERSION);
if (Constants.FRAMEWORK_BSNVERSION_SINGLE.equals(bsnVersion)) {
BSN_VERSION = BSN_VERSION_SINGLE;
} else if (Constants.FRAMEWORK_BSNVERSION_MULTIPLE.equals(bsnVersion)) {
BSN_VERSION = BSN_VERSION_MULTIPLE;
} else {
BSN_VERSION = BSN_VERSION_MANAGED;
}
long start = System.currentTimeMillis();
this.adaptor = adaptor;
delegateHooks = adaptor instanceof BaseAdaptor ? ((BaseAdaptor) adaptor).getHookRegistry().getClassLoaderDelegateHooks() : null;
active = false;
installSecurityManager();
if (Debug.DEBUG_SECURITY) {
Debug.println("SecurityManager: " + System.getSecurityManager()); //$NON-NLS-1$
Debug.println("ProtectionDomain of Framework.class: \n" + this.getClass().getProtectionDomain()); //$NON-NLS-1$
}
setNLSFrameworkLog();
// initialize ContextFinder
initializeContextFinder();
/* initialize the adaptor */
adaptor.initialize(this);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "adapter initialized"); //$NON-NLS-1$//$NON-NLS-2$
try {
adaptor.initializeStorage();
} catch (IOException e) /* fatal error */{
throw new RuntimeException(e.getMessage(), e);
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "adapter storage initialized"); //$NON-NLS-1$//$NON-NLS-2$
/*
* This must be done before calling any of the framework getProperty
* methods.
*/
initializeProperties(adaptor.getProperties());
/* initialize admin objects */
packageAdmin = new PackageAdminImpl(this);
try {
// always create security admin even with security off
securityAdmin = new SecurityAdmin(null, this, adaptor.getPermissionStorage());
} catch (IOException e) /* fatal error */{
e.printStackTrace();
throw new RuntimeException(e.getMessage(), e);
}
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done init props & new PermissionAdminImpl"); //$NON-NLS-1$//$NON-NLS-2$
startLevelManager = new StartLevelManager(this);
/* create the event manager and top level event dispatchers */
eventManager = new EventManager("Framework Event Dispatcher"); //$NON-NLS-1$
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done new EventManager"); //$NON-NLS-1$ //$NON-NLS-2$
/* create the service registry */
serviceRegistry = new ServiceRegistry(this);
// Initialize the installLock; there is no way of knowing
// what the initial size should be, at most it will be the number
// of threads trying to install a bundle (probably a very low number).
installLock = new HashMap<String, Thread>(10);
/* create the system bundle */
createSystemBundle();
loadVMProfile(); // load VM profile after the system bundle has been created
setBootDelegation(); //set boot delegation property after system exports have been set
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done createSystemBundle"); //$NON-NLS-1$ //$NON-NLS-2$
/* install URLStreamHandlerFactory */
installURLStreamHandlerFactory(systemBundle.context, adaptor);
/* install ContentHandlerFactory for OSGi URLStreamHandler support */
installContentHandlerFactory(systemBundle.context, adaptor);
if (Profile.PROFILE && Profile.STARTUP)
Profile.logTime("Framework.initialze()", "done new URLStream/Content HandlerFactory"); //$NON-NLS-1$//$NON-NLS-2$
/* create bundle objects for all installed bundles. */
BundleData[] bundleDatas = adaptor.getInstalledBundles();
bundles = new BundleRepository(bundleDatas == null ? 10 : bundleDatas.length + 1);
/* add the system bundle to the Bundle Repository */
bundles.add(systemBundle);
if (bundleDatas != null) {
for (int i = 0; i < bundleDatas.length; i++) {
try {
AbstractBundle bundle = AbstractBundle.createBundle(bundleDatas[i], this, true);
bundles.add(bundle);
} catch (BundleException be) {
// This is not a fatal error. Publish the framework event.
publishFrameworkEvent(FrameworkEvent.ERROR, systemBundle, be);
}
}
}
if (Debug.DEBUG_GENERAL)
System.out.println("Initialize the framework: " + (System.currentTimeMillis() - start)); //$NON-NLS-1$
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("Framework.initialize()"); //$NON-NLS-1$
}
framework.luanch()
public synchronized void launch() {
/* Return if framework already started */
if (active) {
return;
}
/* mark framework as started */
active = true;
shutdownEvent = new FrameworkEvent[1];
if (THREAD_NORMAL.equals(FrameworkProperties.getProperty(PROP_FRAMEWORK_THREAD, THREAD_NORMAL))) {
Thread fwkThread = new Thread(this, "Framework Active Thread"); //$NON-NLS-1$
fwkThread.setDaemon(false);
fwkThread.start();
}
/* Resume systembundle */
if (Debug.DEBUG_GENERAL) {
Debug.println("Trying to launch framework"); //$NON-NLS-1$
}
systemBundle.resume();
signedContentFactory = new ServiceTracker<SignedContentFactory, SignedContentFactory>(systemBundle.getBundleContext(), SignedContentFactory.class.getName(), null);
signedContentFactory.open();
}
/*
* (non-Javadoc)
* @see java.lang.Runnable#run()
* This thread monitors the framework active status and terminates when the framework is
* shutdown. This is needed to ensure the VM does not exist because of the lack of a
* non-daemon thread (bug 215730)
*/
public void run() {
synchronized (this) {
while (active)
try {
this.wait(1000);
} catch (InterruptedException e) {
// do nothing
}
}
}
- load basic bundles
Bundle[] startBundles = loadBasicBundles();
private static Bundle[] loadBasicBundles() {
long startTime = System.currentTimeMillis();
String osgiBundles = FrameworkProperties.getProperty(PROP_BUNDLES);
String osgiExtensions = FrameworkProperties.getProperty(PROP_EXTENSIONS);
if (osgiExtensions != null && osgiExtensions.length() > 0) {
osgiBundles = osgiExtensions + ',' + osgiBundles;
FrameworkProperties.setProperty(PROP_BUNDLES, osgiBundles);
}
String[] installEntries = getArrayFromList(osgiBundles, ","); //$NON-NLS-1$
// get the initial bundle list from the installEntries
InitialBundle[] initialBundles = getInitialBundles(installEntries);
// get the list of currently installed initial bundles from the framework
Bundle[] curInitBundles = getCurrentBundles(true); // list of bundles to be refreshed
List<Bundle> toRefresh = new ArrayList<Bundle>(curInitBundles.length);
// uninstall any of the currently installed bundles that do not exist in the
// initial bundle list from installEntries.
uninstallBundles(curInitBundles, initialBundles, toRefresh); // install the initialBundles that are not already installed.
List<Bundle> startBundles = new ArrayList<Bundle>(installEntries.length);
List<Bundle> lazyActivationBundles = new ArrayList<Bundle>(installEntries.length);
installBundles(initialBundles, curInitBundles, startBundles, lazyActivationBundles, toRefresh); // If we installed/uninstalled something, force a refresh of all installed/uninstalled bundles
if (!toRefresh.isEmpty() && refreshPackages(toRefresh.toArray(new Bundle[toRefresh.size()])))
return null; // cannot continue; refreshPackages shutdown the framework // schedule all basic bundles to be started
Bundle[] startInitBundles = startBundles.toArray(new Bundle[startBundles.size()]);
Bundle[] lazyInitBundles = lazyActivationBundles.toArray(new Bundle[lazyActivationBundles.size()]);
startBundles(startInitBundles, lazyInitBundles); if (debug)
System.out.println("Time to load bundles: " + (System.currentTimeMillis() - startTime)); //$NON-NLS-1$
return startInitBundles;
}startBundles() in which our Activator' s start method will be executed.
private static void startBundles(Bundle[] startBundles, Bundle[] lazyBundles) {
for (int i = 0; i < startBundles.length; i++)
startBundle(startBundles[i], 0);
for (int i = 0; i < lazyBundles.length; i++)
startBundle(lazyBundles[i], Bundle.START_ACTIVATION_POLICY);
} private static void startBundle(Bundle bundle, int options) {
try {
bundle.start(options);
} catch (BundleException e) {
if ((bundle.getState() & Bundle.RESOLVED) != 0) {
// only log errors if the bundle is resolved
FrameworkLogEntry entry = new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, NLS.bind(EclipseAdaptorMsg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
log.log(entry);
}
}
}config.ini
#This configuration file was written by: org.eclipse.equinox.internal.frameworkadmin.equinox.EquinoxFwConfigFileParser
#Thu Sep 05 17:05:01 CST 2013
org.eclipse.update.reconcile=false
eclipse.p2.profile=SDKProfile
osgi.instance.area.default=@user.home/workspace
osgi.framework=file\:plugins/org.eclipse.osgi_3.8.0.v20120529-1548.jar
equinox.use.ds=true
eclipse.buildId=I20120608-1400
osgi.bundles=reference\:file\:org.eclipse.equinox.simpleconfigurator_1.0.300.v20110815-1744.jar@1\:start
org.eclipse.equinox.simpleconfigurator.configUrl=file\:org.eclipse.equinox.simpleconfigurator/bundles.info
eclipse.product=org.eclipse.sdk.ide
osgi.splashPath=platform\:/base/plugins/org.eclipse.platform
osgi.framework.extensions=
osgi.bundles.defaultStartLevel=4
eclipse.p2.data.area=@config.dir/../p2/
eclipse.application=org.eclipse.ui.ide.workbench- When clicking eclipse.exe which is a windows program, it will execute to startup JVM and set some enviroment variables, read elipse.ini
Eclipse Launcher Description
Eclipse contains a native executable launcher that is used to start Eclipse. There is more to the launcher than just the eclipse executable in the root of the install. The launcher and its shared library
The launcher executable comes in 2 pieces: the executable (eclipse.exe), and a shared library (eclipse_1017.dll). The executable lives in the root of the eclipse install. The shared library is in a platform specific fragment, org.eclipse.equinox.launcher.[config], in the plugins directory. Having the majority of the launcher code in a shared library that lives in a fragment means that that portion of the launch code can now be updated from an update site. Also, when starting from java, the shared library can be loaded via JNI in order to display the splash screen. The launcher bundle
Previous versions of Eclipse had a startup.jar JAR file in the root of the install. In 3.3, this code has been moved to a plug-in org.eclipse.equinox.launcher in the plugins directory. Eclipse can still be started directly with java using, for example: java -jar plugins/org.eclipse.equinox.launcher_1.0.0.v20070606.jar
Launching Eclipse involves 3 main pieces: the native executable, the launcher platform specific fragment and the launcher jar. In the example below, notice that the launcher fragment is in folder form, this is necessary so that the native eclipse.exe can load the shared library: eclipse/ eclipse.exe plugins/ org.eclipse.equinox.launcher_1.0.0.v20070606.jar org.eclipse.equinox.launcher.win32.win32.x86_1.0.0.v20070523/ eclipse_1017a.dll
The version numbers above are for illustration purposes only (e.g. 1.0.0.v20070606). The actual version numbers may vary depending on the version of Eclipse you are using. Finding a VM and using the JNI Invocation API
The Eclipse launcher is capable of loading the Java VM in the eclipse process using the Java Native Interface Invocation API. The launcher is still capable of starting the Java VM in a separate process the same as previous version of Eclipse did. Which method is used depends on how the VM was found. No -vm specified
When no -vm is specified, the launcher looks for a virtual machine first in a jre directory in the root of eclipse and then on the search path. If java is found in either location, then the launcher looks for a jvm shared library (jvm.dll on Windows, libjvm.so on *nix platforms) relative to that java executable. If a jvm shared library is found the launcher loads it and uses the JNI invocation API to start the vm.
If no jvm shared library is found, the launcher executes the java launcher to start the vm in a new process.
-vm specified on the command line or in eclipse.ini
Eclipse can be started with "-vm <location>" to indicate a virtual machine to use. There are several possibilities for the value of <location>: directory: <location> is a directory. We look in that directory for: (1) a java launcher or (2) the jvm shared library. If we find the jvm shared library, we use JNI invocation. If we find a launcher, we attempt to find a jvm library in known locations relative to the launcher. If we find one, we use JNI invocation. If no jvm library is found, we exec java in a new process. java.exe/javaw.exe: <location> is a path to a java launcher. We exec that java launcher to start the vm in a new process.
jvm dll or so: <location> is a path to a jvm shared library. We attempt to load that library and use the JNI Invocation API to start the vm in the current process.
Exceptions
linux.ppc, linux.x86_64, aix.ppc: The launcher is not able to load some older vms using the JNI invocation API. By default on these platforms the launcher will prefer to execute java in a separate process. To force the launcher to load the vm using JNI, specify a -vm option pointing directly to the vm's shared library (libjvm.so).
MacOSX: The launcher uses the system JavaVM framework and will always load the vm in-process using the JNI invocation API.Eclipse Launcher
1 -startup
2 plugins/org.eclipse.equinox.launcher_1.3.0.v20120522-1813.jar
3 --launcher.library
4 plugins/org.eclipse.equinox.launcher.win32.win32.x86_1.1.200.v20120522-1813
5 -showsplash
6 org.eclipse.platform
7 --launcher.XXMaxPermSize
8 256m
9 --launcher.defaultAction
10 openFile
11 -vmargs
12 -Xms40m
13 -Xmx512morg.eclipse.equinox.launcher.Main.main(Main.java:1414)
org.eclipse.equinox.launcher.Main.run(Main.java:1438)
org.eclipse.equinox.launcher.Main.basicRun(Main.java:584)
org.eclipse.equinox.launcher.Main.invokeFramework(Main.java:629)
java.lang.reflect.Method.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:180)
org.eclipse.core.runtime.adaptor.EclipseStarter.run(EclipseStarter.java:353)- run()
public static Object run(Object argument) throws Exception {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logEnter("EclipseStarter.run(Object)()", null); //$NON-NLS-1$
if (!running)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_NOT_RUNNING);
// if we are just initializing, do not run the application just return.
if (initialize)
return new Integer(0);
try {
if (appLauncher == null) {
boolean launchDefault = Boolean.valueOf(FrameworkProperties.getProperty(PROP_APPLICATION_LAUNCHDEFAULT, "true")).booleanValue(); //$NON-NLS-1$
// create the ApplicationLauncher and register it as a service
appLauncher = new EclipseAppLauncher(context, Boolean.valueOf(FrameworkProperties.getProperty(PROP_ALLOW_APPRELAUNCH)).booleanValue(), launchDefault, log);
appLauncherRegistration = context.registerService(ApplicationLauncher.class.getName(), appLauncher, null);
// must start the launcher AFTER service restration because this method
// blocks and runs the application on the current thread. This method
// will return only after the application has stopped.
return appLauncher.start(argument);
}
return appLauncher.reStart(argument);
} catch (Exception e) {
if (log != null && context != null) // context can be null if OSGi failed to launch (bug 151413)
logUnresolvedBundles(context.getBundles());
throw e;
}
}- EclipseAppLauncher
/*******************************************************************************
* Copyright (c) 2005, 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.core.runtime.internal.adaptor; import java.lang.reflect.Method;
import java.util.Map;
import org.eclipse.core.runtime.adaptor.EclipseStarter;
import org.eclipse.osgi.framework.adaptor.FrameworkAdaptor;
import org.eclipse.osgi.framework.internal.core.Constants;
import org.eclipse.osgi.framework.internal.core.FrameworkProperties;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.internal.profile.Profile;
import org.eclipse.osgi.service.runnable.*;
import org.osgi.framework.*; public class EclipseAppLauncher implements ApplicationLauncher {
volatile private ParameterizedRunnable runnable = null;
private Object appContext = null;
private Semaphore runningLock = new Semaphore(1);
private Semaphore waitForAppLock = new Semaphore(0);
private BundleContext context;
private boolean relaunch = false;
private boolean failOnNoDefault = false;
private FrameworkLog log; public EclipseAppLauncher(BundleContext context, boolean relaunch, boolean failOnNoDefault, FrameworkLog log) {
this.context = context;
this.relaunch = relaunch;
this.failOnNoDefault = failOnNoDefault;
this.log = log;
findRunnableService();
} /*
* Used for backwards compatibility with < 3.2 runtime
*/
private void findRunnableService() {
// look for a ParameterizedRunnable registered as a service by runtimes (3.0, 3.1)
String appClass = ParameterizedRunnable.class.getName();
ServiceReference<?>[] runRefs = null;
try {
runRefs = context.getServiceReferences(ParameterizedRunnable.class.getName(), "(&(objectClass=" + appClass + ")(eclipse.application=*))"); //$NON-NLS-1$//$NON-NLS-2$
} catch (InvalidSyntaxException e) {
// ignore this. It should never happen as we have tested the above format.
}
if (runRefs != null && runRefs.length > 0) {
// found the service use it as the application.
runnable = (ParameterizedRunnable) context.getService(runRefs[0]);
// we will never be able to relaunch with a pre 3.2 runtime
relaunch = false;
waitForAppLock.release();
}
} /*
* Starts this application launcher on the current thread. This method
* should be called by the main thread to ensure that applications are
* launched in the main thread.
*/
public Object start(Object defaultContext) throws Exception {
// here we assume that launch has been called by runtime before we started
// TODO this may be a bad assumption but it works for now because we register the app launcher as a service and runtime synchronously calls launch on the service
if (failOnNoDefault && runnable == null)
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_NO_APPLICATION);
Object result = null;
boolean doRelaunch;
do {
try {
result = runApplication(defaultContext);
} catch (Exception e) {
if (!relaunch || (context.getBundle().getState() & Bundle.ACTIVE) == 0)
throw e;
if (log != null)
log.log(new FrameworkLogEntry(FrameworkAdaptor.FRAMEWORK_SYMBOLICNAME, FrameworkLogEntry.ERROR, 0, EclipseAdaptorMsg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null));
}
doRelaunch = (relaunch && (context.getBundle().getState() & Bundle.ACTIVE) != 0) || FrameworkProperties.getProperty(Constants.PROP_OSGI_RELAUNCH) != null;
} while (doRelaunch);
return result;
} /*
* Waits for an application to be launched and the runs the application on the
* current thread (main).
*/
private Object runApplication(Object defaultContext) throws Exception {
// wait for an application to be launched.
waitForAppLock.acquire();
// an application is ready; acquire the running lock.
// this must happen after we have acquired an application (by acquiring waitForAppLock above).
runningLock.acquire();
if (EclipseStarter.debug) {
String timeString = FrameworkProperties.getProperty("eclipse.startTime"); //$NON-NLS-1$
long time = timeString == null ? 0L : Long.parseLong(timeString);
System.out.println("Starting application: " + (System.currentTimeMillis() - time)); //$NON-NLS-1$
}
if (Profile.PROFILE && (Profile.STARTUP || Profile.BENCHMARK))
Profile.logTime("EclipseStarter.run(Object)()", "framework initialized! starting application..."); //$NON-NLS-1$ //$NON-NLS-2$
try {
// run the actual application on the current thread (main).
return runnable.run(appContext != null ? appContext : defaultContext);
} finally {
if (Profile.PROFILE && Profile.STARTUP)
Profile.logExit("EclipseStarter.run(Object)()"); //$NON-NLS-1$
// free the runnable application and release the lock to allow another app to be launched.
runnable = null;
appContext = null;
runningLock.release();
}
} public void launch(ParameterizedRunnable app, Object applicationContext) {
waitForAppLock.acquire(-1); // clear out any pending apps notifications
if (!runningLock.acquire(-1)) // check to see if an application is currently running
throw new IllegalStateException("An application is aready running."); //$NON-NLS-1$
this.runnable = app;
this.appContext = applicationContext;
waitForAppLock.release(); // notify the main thread to launch an application.
runningLock.release(); // release the running lock
} public void shutdown() {
// this method will aquire and keep the runningLock to prevent
// all future application launches.
if (runningLock.acquire(-1))
return; // no application is currently running.
ParameterizedRunnable currentRunnable = runnable;
if (currentRunnable instanceof ApplicationRunnable) {
((ApplicationRunnable) currentRunnable).stop();
runningLock.acquire(60000); // timeout after 1 minute.
}
} /*
* Similar to the start method this method will restart the default method on current thread.
* This method assumes that the default application was launched at least once and that an ApplicationDescriptor
* exists that can be used to relaunch the default application.
*/
public Object reStart(Object argument) throws Exception {
ServiceReference<?> ref[] = null;
ref = context.getServiceReferences("org.osgi.service.application.ApplicationDescriptor", "(eclipse.application.default=true)"); //$NON-NLS-1$//$NON-NLS-2$
if (ref != null && ref.length > 0) {
Object defaultApp = context.getService(ref[0]);
Method launch = defaultApp.getClass().getMethod("launch", new Class[] {Map.class}); //$NON-NLS-1$
launch.invoke(defaultApp, new Object[] {null});
return start(argument);
}
throw new IllegalStateException(EclipseAdaptorMsg.ECLIPSE_STARTUP_ERROR_NO_APPLICATION);
}
}EclipseAppLaunch
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.start(EclipseAppLauncher.java:79)
at org.eclipse.core.runtime.internal.adaptor.EclipseAppLauncher.runApplication(EclipseAppLauncher.java:110)
at org.eclipse.equinox.internal.app.EclipseAppHandle.run(EclipseAppHandle.java:196)
at org.eclipse.ui.internal.ide.application.IDEApplication.start(IDEApplication.java:124)
at org.eclipse.ui.PlatformUI.createAndRunWorkbench(PlatformUI.java:149)
at org.eclipse.ui.internal.Workbench.createAndRunWorkbench(Workbench.java:540)
at org.eclipse.ui.internal.Workbench$5.run(Workbench.java:585)
at org.eclipse.e4.ui.internal.workbench.E4Workbench.createAndRunUI(E4Workbench.java:86)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine.run(PartRenderingEngine.java:916)
at org.eclipse.core.databinding.observable.Realm.runWithDefault(Realm.java:332)
at org.eclipse.e4.ui.internal.workbench.swt.PartRenderingEngine$9.run(PartRenderingEngine.java:1022)
at org.eclipse.swt.widgets.Display.readAndDispatch(Display.java:3756)
at org.eclipse.swt.internal.win32.OS.DispatchMessage(OS.java:2546)
at org.eclipse.swt.internal.win32.OS.DispatchMessageW(Native Method)
at org.eclipse.swt.widgets.Display.windowProc(Display.java:4976)
at org.eclipse.swt.widgets.Control.windowProc(Control.java:4528)
at org.eclipse.swt.widgets.Control.WM_CHAR(Control.java:4640)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1062)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1077)
at org.eclipse.swt.widgets.Widget.sendEvent(Widget.java:1052)
at org.eclipse.swt.widgets.Widget.wmChar(Widget.java:1521)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1100)
at org.eclipse.swt.widgets.Widget.sendKeyEvent(Widget.java:1104)
at org.eclipse.swt.widgets.Display.filterEvent(Display.java:1262)
at org.eclipse.swt.widgets.EventTable.sendEvent(EventTable.java:84)
Eclipse Startup的更多相关文章
- The Eclipse runtime options
Version 3.6 - Last revised August 5, 2009 The Eclipse platform is highly configurable. Configuration ...
- eclipse.ini 文件使用说明
http://wiki.eclipse.org/Eclipse.ini Overview Eclipse startup is controlled by the options in $ECLIPS ...
- eclipse性能调优的一次记录
最近因为学习原因,eclipse中插件越来越多,造成eclipse一次次假死,着实很影响工作效率和心情,有时正是兴起,但是造成短片很令人生气,如果eclipse卡顿或者假死,在电脑配置较不错的情况下, ...
- Android开发中Eclispe相关问题及相应解决(持续更新)
1.Eclipse项目中的Android Private Libraries没有自动生成. 一般而言,在Android开发中,项目中引用到的jar包会放到项目目录中的libs中,引入库会放到Andro ...
- MyEclipse 死掉,JVM terminated. Exit code=1073807364
刚入手的新成员,刚开始使用myeclipse,是不是会有一大堆的问题,然后没有目标的走,这里有个小技巧,那就是如果做项目出现问题,一定要自己现在网络搜寻答案,网络时代.技术时代走到现在,一定有他的道理 ...
- MyEclipse CI 2018.8.0正式发布(附下载)
MyEclipse线上特惠,在线立享专属折扣!火热开启中>> MyEclipse 2018最终版日前正式发布,新版本通过构建Eclipse Photo.支持Java 10和Java EE ...
- Java转C#,非常不错(转)
http://www.cnblogs.com/cnwebman/archive/2012/07/21/2602436.html 最近正在研究将一个纯java工程如何转换成C#工程,代码量还比较大,于是 ...
- eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错? java.lang.ClassNotFoundException: com.branchitech.app.startup.AppStartupContextListener java.lang.ClassN
eclipse java项目中明明引入了jar包 为什么项目启动的时候不能找到jar包 项目中已经 引入了 com.branchitech.app 包 ,但时tomcat启动的时候还是报错?java. ...
- Eclipse plug-in startup
Plug-in Startup !SESSION 2013-09-02 16:28:29.546 -----------------------------------------------ecli ...
随机推荐
- [JSOI2009]计数问题 二维树状数组BZOJ 1452
题目描述 一个n*m的方格,初始时每个格子有一个整数权值.接下来每次有2种操作: 改变一个格子的权值: 求一个子矩阵中某种特定权值出现的个数. 输入输出格式 输入格式: 第一行有两个数N,M. 接下来 ...
- sed的基本用法
了解sed的基本参数 sed匹配的方法: '//'p, 此符号与grep的引号类似,但sed是一定加此符号的,且还要加上-n的参数,匹配起来相当麻烦.sed匹配的方法: '//'pI 加上I的参数是指 ...
- 【算法笔记】B1032 挖掘机技术哪家强
1032 挖掘机技术哪家强 (20 分) 为了用事实说明挖掘机技术到底哪家强,PAT 组织了一场挖掘机技能大赛.现请你根据比赛结果统计出技术最强的那个学校. 输入格式: 输入在第 1 行给出不超过 1 ...
- 2.16 关于python/numpy
- HibernateUtil hibernate4.0以上
package com.test.bbs.util; import org.hibernate.Session; import org.hibernate.SessionFactory; import ...
- UVa 253
UVa 253 #include <iostream> #include <cstdio> #include <string> #include <cstri ...
- mysql远程连接详细配置
2018-11-06 CentOS 配置MySQL允许远程登录 Mysql为了安全性,在默认情况下用户只允许在本地登录,可是在有此情况下,还是需要使用用户进行远程连接,因此为了使其可以远程需要进行如下 ...
- V1-Team Scrum Meeting 博客汇总
V1-Team Scrum Meeting 博客汇总 计划文档 功能规格说明书 技术规格说明书 项目分解 贡献分配规则 一.Alpha阶段 第一次 Scrum Meeting 第二次 Scrum Me ...
- Percona Mysql备份
介绍 Percona是唯一一款开源.免费的mysql热备份工具,实现了对InnoDB数据库的非阻塞式的备份.有如下优势:1.完整.快速.可靠的备份2.备份期间不打断事务执行(innodb引擎)3.备份 ...
- vue中promise的使用
vue中promise的使用 promise是处理异步的利器,在之前的文章<ES6之promise>中,我详细介绍了promise的使用, 在文章<js动画实现&&回 ...