package org.eclipse.core.runtime.adaptor;
import java.io.*;
import java.lang.reflect.Method;
import java.net.*;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.*;
import java.util.concurrent.Semaphore;
import java.util.concurrent.TimeUnit;
import org.eclipse.core.runtime.internal.adaptor.*;
import org.eclipse.osgi.container.Module;
import org.eclipse.osgi.container.ModuleRevision;
import org.eclipse.osgi.container.namespaces.EquinoxModuleDataNamespace;
import org.eclipse.osgi.framework.log.FrameworkLog;
import org.eclipse.osgi.framework.log.FrameworkLogEntry;
import org.eclipse.osgi.framework.util.FilePath;
import org.eclipse.osgi.internal.debug.Debug;
import org.eclipse.osgi.internal.framework.EquinoxConfiguration;
import org.eclipse.osgi.internal.framework.EquinoxContainer;
import org.eclipse.osgi.internal.location.EquinoxLocations;
import org.eclipse.osgi.internal.location.LocationHelper;
import org.eclipse.osgi.internal.messages.Msg;
import org.eclipse.osgi.launch.Equinox;
import org.eclipse.osgi.report.resolution.ResolutionReport;
import org.eclipse.osgi.service.datalocation.Location;
import org.eclipse.osgi.service.environment.EnvironmentInfo;
import org.eclipse.osgi.service.runnable.ApplicationLauncher;
import org.eclipse.osgi.service.runnable.StartupMonitor;
import org.eclipse.osgi.storage.url.reference.Handler;
import org.eclipse.osgi.util.ManifestElement;
import org.eclipse.osgi.util.NLS;
import org.osgi.framework.*;
import org.osgi.framework.launch.Framework;
import org.osgi.framework.startlevel.BundleStartLevel;
import org.osgi.framework.startlevel.FrameworkStartLevel;
import org.osgi.framework.wiring.FrameworkWiring;
import org.osgi.resource.Resource;
import org.osgi.util.tracker.ServiceTracker;
public class EclipseStarter {
private static BundleContext context;
private static boolean initialize = false;
public static boolean debug = false;
private static boolean running = false;
private static ServiceRegistration<?> defaultMonitorRegistration = null;
private static ServiceRegistration<?> appLauncherRegistration = null;
private static ServiceRegistration<?> splashStreamRegistration = null;
private static final String CLEAN = "-clean";
private static final String CONSOLE = "-console";
private static final String CONSOLE_LOG = "-consoleLog";
private static final String DEBUG = "-debug";
private static final String INITIALIZE = "-initialize";
private static final String DEV = "-dev";
private static final String WS = "-ws";
private static final String OS = "-os";
private static final String ARCH = "-arch";
private static final String NL = "-nl";
private static final String NL_EXTENSIONS = "-nlExtensions";
private static final String CONFIGURATION = "-configuration";
private static final String USER = "-user";
private static final String NOEXIT = "-noExit";
private static final String LAUNCHER = "-launcher";
private static final String DATA = "-data";
public static final String PROP_BUNDLES = "osgi.bundles";
public static final String PROP_BUNDLES_STARTLEVEL = "osgi.bundles.defaultStartLevel";
public static final String PROP_EXTENSIONS = "osgi.framework.extensions";
public static final String PROP_INITIAL_STARTLEVEL = "osgi.startLevel";
public static final String PROP_DEBUG = "osgi.debug";
public static final String PROP_DEV = "osgi.dev";
public static final String PROP_CLEAN = "osgi.clean";
public static final String PROP_CONSOLE = "osgi.console";
public static final String PROP_CONSOLE_CLASS = "osgi.consoleClass";
public static final String PROP_CHECK_CONFIG = "osgi.checkConfiguration";
public static final String PROP_OS = "osgi.os";
public static final String PROP_WS = "osgi.ws";
public static final String PROP_NL = "osgi.nl";
private static final String PROP_NL_EXTENSIONS = "osgi.nl.extensions";
public static final String PROP_ARCH = "osgi.arch";
public static final String PROP_ADAPTOR = "osgi.adaptor";
public static final String PROP_SYSPATH = "osgi.syspath";
public static final String PROP_LOGFILE = "osgi.logfile";
public static final String PROP_FRAMEWORK = "osgi.framework";
public static final String PROP_INSTALL_AREA = "osgi.install.area";
public static final String PROP_FRAMEWORK_SHAPE = "osgi.framework.shape";
public static final String PROP_NOSHUTDOWN = "osgi.noShutdown";
public static final String PROP_EXITCODE = "eclipse.exitcode";
public static final String PROP_EXITDATA = "eclipse.exitdata";
public static final String PROP_CONSOLE_LOG = "eclipse.consoleLog";
public static final String PROP_IGNOREAPP = "eclipse.ignoreApp";
public static final String PROP_REFRESH_BUNDLES = "eclipse.refreshBundles";
private static final String PROP_ALLOW_APPRELAUNCH = "eclipse.allowAppRelaunch";
private static final String PROP_APPLICATION_LAUNCHDEFAULT = "eclipse.application.launchDefault";
private static final String FILE_SCHEME = "file:";
private static final String REFERENCE_SCHEME = "reference:";
private static final String REFERENCE_PROTOCOL = "reference";
private static final String INITIAL_LOCATION = "initial@";
private static final int DEFAULT_INITIAL_STARTLEVEL = 6;
private static final String DEFAULT_BUNDLES_STARTLEVEL = "4";
private static FrameworkLog log;
private static Map<String, String[]> searchCandidates = new HashMap<>(4);
private static EclipseAppLauncher appLauncher;
private static List<Runnable> shutdownHandlers;
private static ConsoleManager consoleMgr = null;
private static Map<String, String> configuration = null;
private static Framework framework = null;
private static EquinoxConfiguration equinoxConfig;
private static String[] allArgs = null;
private static String[] frameworkArgs = null;
private static String[] appArgs = null;
private synchronized static String getProperty(String key) {
if (equinoxConfig != null) {
return equinoxConfig.getConfiguration(key);
}
return getConfiguration().get(key);
}
private synchronized static String getProperty(String key, String dft) {
if (equinoxConfig != null) {
return equinoxConfig.getConfiguration(key, dft);
}
String result = getConfiguration().get(key);
return result == null ? dft : result;
}
private synchronized static Object setProperty(String key, String value) {
if (equinoxConfig != null) {
return equinoxConfig.setProperty(key, value);
}
if ("true".equals(getConfiguration().get(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES))) {
System.setProperty(key, value);
}
return getConfiguration().put(key, value);
}
private synchronized static Object clearProperty(String key) {
if (equinoxConfig != null) {
return equinoxConfig.clearConfiguration(key);
}
return getConfiguration().remove(key);
}
private synchronized static Map<String, String> getConfiguration() {
if (configuration == null) {
configuration = new HashMap<>();
configuration.put(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, System.getProperty(EquinoxConfiguration.PROP_USE_SYSTEM_PROPERTIES, "true"));
String systemCompatibilityBoot = System.getProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION);
if (systemCompatibilityBoot != null) {
configuration.put(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, systemCompatibilityBoot);
} else {
configuration.put(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION + EquinoxConfiguration.PROP_DEFAULT_SUFFIX, "true");
}
String dsDelayedKeepInstances = System.getProperty(EquinoxConfiguration.PROP_DS_DELAYED_KEEPINSTANCES);
if (dsDelayedKeepInstances != null) {
configuration.put(EquinoxConfiguration.PROP_DS_DELAYED_KEEPINSTANCES, dsDelayedKeepInstances);
} else {
configuration.put(EquinoxConfiguration.PROP_DS_DELAYED_KEEPINSTANCES + EquinoxConfiguration.PROP_DEFAULT_SUFFIX, "true");
}
}
return configuration;
}
public static void main(String[] args) throws Exception {
if (getProperty("eclipse.startTime") == null)
setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis()));
if (getProperty(PROP_NOSHUTDOWN) == null)
setProperty(PROP_NOSHUTDOWN, "true");
if (getProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION) == null)
setProperty(EquinoxConfiguration.PROP_COMPATIBILITY_BOOTDELEGATION, "false");
Object result = run(args, null);
if (result instanceof Integer && !Boolean.valueOf(getProperty(PROP_NOSHUTDOWN)).booleanValue())
System.exit(((Integer) result).intValue());
}
public static Object run(String[] args, Runnable endSplashHandler) throws Exception {
if (running)
throw new IllegalStateException(Msg.ECLIPSE_STARTUP_ALREADY_RUNNING);
boolean startupFailed = true;
try {
startup(args, endSplashHandler);
startupFailed = false;
if (Boolean.valueOf(getProperty(PROP_IGNOREAPP)).booleanValue() || isForcedRestart())
return null;
return run(null);
} catch (Throwable e) {
if (endSplashHandler != null)
endSplashHandler.run();
FrameworkLogEntry logEntry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, startupFailed ? Msg.ECLIPSE_STARTUP_STARTUP_ERROR : Msg.ECLIPSE_STARTUP_APP_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
e.printStackTrace();
} finally {
try {
if (isForcedRestart())
setProperty(PROP_EXITCODE, "23");
if (!Boolean.valueOf(getProperty(PROP_NOSHUTDOWN)).booleanValue())
shutdown();
} catch (Throwable e) {
FrameworkLogEntry logEntry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, Msg.ECLIPSE_STARTUP_SHUTDOWN_ERROR, 1, e, null);
if (log != null)
log.log(logEntry);
else
e.printStackTrace();
}
}
if (getProperty(PROP_EXITCODE) == null) {
setProperty(PROP_EXITCODE, "13");
setProperty(PROP_EXITDATA, NLS.bind(Msg.ECLIPSE_STARTUP_ERROR_CHECK_LOG, log == null ? null : log.getFile().getPath()));
}
return null;
}
public static boolean isRunning() {
return running;
}
public static BundleContext startup(String[] args, Runnable endSplashHandler) throws Exception {
if (running)
throw new IllegalStateException(Msg.ECLIPSE_STARTUP_ALREADY_RUNNING);
processCommandLine(args);
framework = new Equinox(getConfiguration());
framework.init();
context = framework.getBundleContext();
ServiceReference<FrameworkLog> logRef = context.getServiceReference(FrameworkLog.class);
log = context.getService(logRef);
ServiceReference<EnvironmentInfo> configRef = context.getServiceReference(EnvironmentInfo.class);
equinoxConfig = (EquinoxConfiguration) context.getService(configRef);
equinoxConfig.setAllArgs(allArgs);
equinoxConfig.setFrameworkArgs(frameworkArgs);
equinoxConfig.setAppArgs(appArgs);
registerFrameworkShutdownHandlers();
publishSplashScreen(endSplashHandler);
consoleMgr = ConsoleManager.startConsole(context, equinoxConfig);
Bundle[] startBundles = loadBasicBundles();
if (startBundles == null || ("true".equals(getProperty(PROP_REFRESH_BUNDLES)) && refreshPackages(getCurrentBundles(false)))) {
waitForShutdown();
return context;
}
framework.start();
if (isForcedRestart()) {
return context;
}
setStartLevel(getStartLevel());
ensureBundlesActive(startBundles);
try {
consoleMgr.checkForConsoleBundle();
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null);
log.log(entry);
}
running = true;
return context;
}
private static int getStartLevel() {
String level = getProperty(PROP_INITIAL_STARTLEVEL);
if (level != null)
try {
return Integer.parseInt(level);
} catch (NumberFormatException e) {
if (debug)
Debug.println("Start level = " + level + " parsed. Using hardcoded default: 6");
}
return DEFAULT_INITIAL_STARTLEVEL;
}
public static Object run(Object argument) throws Exception {
if (!running)
throw new IllegalStateException(Msg.ECLIPSE_STARTUP_NOT_RUNNING);
if (initialize)
return Integer.valueOf(0);
try {
if (appLauncher == null) {
boolean launchDefault = Boolean.parseBoolean(getProperty(PROP_APPLICATION_LAUNCHDEFAULT, "true"));
appLauncher = new EclipseAppLauncher(context, Boolean.parseBoolean(getProperty(PROP_ALLOW_APPRELAUNCH)), launchDefault, log, equinoxConfig);
appLauncherRegistration = context.registerService(ApplicationLauncher.class.getName(), appLauncher, null);
return appLauncher.start(argument);
}
return appLauncher.reStart(argument);
} catch (Exception e) {
if (log != null && context != null) {
ResolutionReport report = context.getBundle().adapt(Module.class).getContainer().resolve(null, false);
for (Resource unresolved : report.getEntries().keySet()) {
String bsn = ((ModuleRevision) unresolved).getSymbolicName();
FrameworkLogEntry logEntry = new FrameworkLogEntry(bsn != null ? bsn : EquinoxContainer.NAME, FrameworkLogEntry.WARNING, 0, Msg.Module_ResolveError + report.getResolutionReportMessage(unresolved), 1, null, null);
log.log(logEntry);
}
}
throw e;
}
}
public static void shutdown() throws Exception {
if (!running || framework == null)
return;
if (framework.getState() == Bundle.ACTIVE) {
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;
}
if (framework.getState() == Bundle.ACTIVE) {
framework.stop();
framework.waitForStop(0);
framework = null;
}
configuration = null;
equinoxConfig = null;
context = null;
running = false;
}
private static void ensureBundlesActive(Bundle[] bundles) {
for (Bundle bundle : bundles) {
if (bundle.getState() != Bundle.ACTIVE) {
if (bundle.getState() == Bundle.INSTALLED) {
log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_RESOLVED, bundle.getLocation()), 0, null, null));
continue;
}
FrameworkStartLevel fwStartLevel = context.getBundle().adapt(FrameworkStartLevel.class);
BundleStartLevel bundleStartLevel = bundle.adapt(BundleStartLevel.class);
if (fwStartLevel != null && (bundleStartLevel.getStartLevel() <= fwStartLevel.getStartLevel())) {
log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_ERROR_BUNDLE_NOT_ACTIVE, bundle), 0, null, null));
}
}
}
}
private static void publishSplashScreen(final Runnable endSplashHandler) {
if (endSplashHandler == null)
return;
try {
Method method = endSplashHandler.getClass().getMethod("getOutputStream", new Class[0]);
Object outputStream = method.invoke(endSplashHandler, new Object[0]);
if (outputStream instanceof OutputStream) {
Dictionary<String, Object> osProperties = new Hashtable<>();
osProperties.put("name", "splashstream");
splashStreamRegistration = context.registerService(OutputStream.class.getName(), outputStream, osProperties);
}
} catch (Exception ex) {
}
try {
Dictionary<String, Object> monitorProps = new Hashtable<>();
monitorProps.put(Constants.SERVICE_RANKING, Integer.valueOf(Integer.MIN_VALUE));
defaultMonitorRegistration = context.registerService(StartupMonitor.class.getName(), new DefaultStartupMonitor(endSplashHandler, equinoxConfig), monitorProps);
} catch (IllegalStateException e) {
}
}
@SuppressWarnings("deprecation")
private static URL searchForBundle(String name, String parent) throws MalformedURLException {
URL url = null;
File fileLocation = null;
boolean reference = false;
try {
createURL(name);
url = createURL(new File(parent).toURL(), name);
} catch (MalformedURLException e) {
File child = new File(name);
fileLocation = child.isAbsolute() ? child : new File(parent, name);
url = createURL(REFERENCE_PROTOCOL, null, fileLocation.toURL().toExternalForm());
reference = true;
}
if (!reference) {
URL baseURL = url;
if (url.getProtocol().equals(REFERENCE_PROTOCOL)) {
reference = true;
String baseSpec = url.getPath();
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 = createURL(baseSpec);
}
fileLocation = new File(baseURL.getPath());
if (!fileLocation.isAbsolute())
fileLocation = new File(parent, fileLocation.toString());
}
if (reference) {
String result = searchFor(fileLocation.getName(), new File(fileLocation.getParent()).getAbsolutePath());
if (result != null)
url = createURL(REFERENCE_PROTOCOL, null, FILE_SCHEME + result);
else
return null;
}
try {
URLConnection result = LocationHelper.getConnection(url);
result.connect();
return url;
} catch (IOException e) {
return null;
}
}
private static Bundle[] loadBasicBundles() throws InterruptedException {
long startTime = System.currentTimeMillis();
String osgiBundles = getProperty(PROP_BUNDLES);
String osgiExtensions = getProperty(PROP_EXTENSIONS);
if (osgiExtensions != null && osgiExtensions.length() > 0) {
osgiBundles = osgiExtensions + ',' + osgiBundles;
setProperty(PROP_BUNDLES, osgiBundles);
}
String[] installEntries = getArrayFromList(osgiBundles, ",");
InitialBundle[] initialBundles = getInitialBundles(installEntries);
Bundle[] curInitBundles = getCurrentBundles(true);
List<Bundle> toRefresh = new ArrayList<>(curInitBundles.length);
uninstallBundles(curInitBundles, initialBundles, toRefresh);
List<Bundle> startBundles = new ArrayList<>(installEntries.length);
List<Bundle> lazyActivationBundles = new ArrayList<>(installEntries.length);
installBundles(initialBundles, curInitBundles, startBundles, lazyActivationBundles, toRefresh);
if (!toRefresh.isEmpty() && refreshPackages(toRefresh.toArray(new Bundle[toRefresh.size()])))
return null;
Bundle[] startInitBundles = startBundles.toArray(new Bundle[startBundles.size()]);
Bundle[] lazyInitBundles = lazyActivationBundles.toArray(new Bundle[lazyActivationBundles.size()]);
startBundles(startInitBundles, lazyInitBundles);
if (debug)
Debug.println("Time to load bundles: " + (System.currentTimeMillis() - startTime));
return startInitBundles;
}
private static InitialBundle[] getInitialBundles(String[] installEntries) {
searchCandidates.clear();
List<InitialBundle> result = new ArrayList<>(installEntries.length);
int defaultStartLevel = Integer.parseInt(getProperty(PROP_BUNDLES_STARTLEVEL, DEFAULT_BUNDLES_STARTLEVEL));
String syspath = getSysPath();
try {
syspath = new File(syspath).getCanonicalPath();
} catch (IOException ioe) {
}
Collection<ServiceReference<Location>> installLocRef;
try {
installLocRef = context.getServiceReferences(Location.class, Location.INSTALL_FILTER);
} catch (InvalidSyntaxException e) {
throw new RuntimeException(e);
}
Location installLocation = installLocRef == null ? null : context.getService(installLocRef.iterator().next());
if (installLocation == null) {
throw new IllegalStateException(Msg.EclipseStarter_InstallLocation);
}
for (String name : installEntries) {
int level = defaultStartLevel;
boolean start = false;
int index = name.lastIndexOf('@');
if (index >= 0) {
String[] attributes = getArrayFromList(name.substring(index + 1, name.length()), ":");
for (String attribute : attributes) {
if (attribute.equals("start"))
start = true;
else {
try {
level = Integer.parseInt(attribute);
} catch (NumberFormatException e) {
index = name.length();
continue;
}
}
}
name = name.substring(0, index);
}
try {
URL location = searchForBundle(name, syspath);
if (location == null) {
FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_BUNDLE_NOT_FOUND, name), 0, null, null);
log.log(entry);
continue;
}
location = makeRelative(installLocation.getURL(), location);
String locationString = INITIAL_LOCATION + location.toExternalForm();
result.add(new InitialBundle(locationString, location, level, start));
}catch (IOException e) {
log.log(new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, e.getMessage(), 0, e, null));
}
}
return result.toArray(new InitialBundle[result.size()]);
}
private static boolean refreshPackages(Bundle[] bundles) throws InterruptedException {
FrameworkWiring frameworkWiring = context.getBundle().adapt(FrameworkWiring.class);
if (frameworkWiring == null)
return false;
Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.PACKAGES_REFRESHED);
context.addBundleListener(listener);
frameworkWiring.refreshBundles(Arrays.asList(bundles), listener);
updateSplash(semaphore, listener);
return isForcedRestart();
}
private static void waitForShutdown() {
try {
framework.waitForStop(0);
} catch (InterruptedException e) {
Thread.interrupted();
throw new RuntimeException(e);
}
}
private static void processCommandLine(String[] args) throws Exception {
allArgs = args;
if (args.length == 0) {
frameworkArgs = args;
return;
}
int[] configArgs = new int[args.length];
configArgs[0] = -1;
int configArgIndex = 0;
for (int i = 0; i < args.length; i++) {
boolean found = false;
if (args[i].equalsIgnoreCase(DEBUG) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) {
setProperty(PROP_DEBUG, "");
debug = true;
found = true;
}
if (args[i].equalsIgnoreCase(DEV) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) {
setProperty(PROP_DEV, "");
found = true;
}
if (args[i].equalsIgnoreCase(INITIALIZE)) {
initialize = true;
found = true;
}
if (args[i].equalsIgnoreCase(CLEAN)) {
setProperty(PROP_CLEAN, "true");
found = true;
}
if (args[i].equalsIgnoreCase(CONSOLE_LOG)) {
setProperty(PROP_CONSOLE_LOG, "true");
found = true;
}
if (args[i].equalsIgnoreCase(CONSOLE) && ((i + 1 == args.length) || ((i + 1 < args.length) && (args[i + 1].startsWith("-"))))) {
setProperty(PROP_CONSOLE, "");
found = true;
}
if (args[i].equalsIgnoreCase(NOEXIT)) {
setProperty(PROP_NOSHUTDOWN, "true");
found = true;
}
if (found) {
configArgs[configArgIndex++] = i;
continue;
}
if (i == args.length - 1 || args[i + 1].startsWith("-")) {
continue;
}
String arg = args[++i];
if (args[i - 1].equalsIgnoreCase(CONSOLE)) {
setProperty(PROP_CONSOLE, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
setProperty(EquinoxLocations.PROP_CONFIG_AREA, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(DATA)) {
setProperty(EquinoxLocations.PROP_INSTANCE_AREA, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(USER)) {
setProperty(EquinoxLocations.PROP_USER_AREA, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(LAUNCHER)) {
setProperty(EquinoxLocations.PROP_LAUNCHER, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(DEV)) {
setProperty(PROP_DEV, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(DEBUG)) {
setProperty(PROP_DEBUG, arg);
debug = true;
found = true;
}
if (args[i - 1].equalsIgnoreCase(WS)) {
setProperty(PROP_WS, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(OS)) {
setProperty(PROP_OS, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(ARCH)) {
setProperty(PROP_ARCH, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(NL)) {
setProperty(PROP_NL, arg);
found = true;
}
if (args[i - 1].equalsIgnoreCase(NL_EXTENSIONS)) {
setProperty(PROP_NL_EXTENSIONS, arg);
found = true;
}
if (found) {
configArgs[configArgIndex++] = i - 1;
configArgs[configArgIndex++] = i;
}
}
if (configArgIndex == 0) {
frameworkArgs = new String[0];
appArgs = args;
return;
}
appArgs = new String[args.length - configArgIndex];
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];
}
return;
}
private static String[] getArrayFromList(String prop, String separator) {
return ManifestElement.getArrayFromList(prop, separator);
}
protected static String getSysPath() {
String result = getProperty(PROP_SYSPATH);
if (result != null)
return result;
result = getSysPathFromURL(getProperty(PROP_FRAMEWORK));
if (result == null)
result = getSysPathFromCodeSource();
if (result == null)
throw new IllegalStateException("Can not find the system path.");
if (Character.isUpperCase(result.charAt(0))) {
char[] chars = result.toCharArray();
chars[0] = Character.toLowerCase(chars[0]);
result = new String(chars);
}
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 = LocationHelper.decodePath(new File(url.getPath()));
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.getPath();
if (File.separatorChar == '\\') {
result = result.replace('\\', '/');
}
if (result.endsWith(".jar")) {
result = result.substring(0, result.lastIndexOf('/'));
if ("folder".equals(getProperty(PROP_FRAMEWORK_SHAPE)))
result = result.substring(0, result.lastIndexOf('/'));
} else {
if (result.endsWith("/"))
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<>();
for (Bundle bundle : installed) {
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 (Bundle bundle : bundles) {
if (location.equalsIgnoreCase(bundle.getLocation()))
return bundle;
}
return null;
}
private static void uninstallBundles(Bundle[] curInitBundles, InitialBundle[] newInitBundles, List<Bundle> toRefresh) {
for (Bundle curInitBundle : curInitBundles) {
boolean found = false;
for (InitialBundle newInitBundle : newInitBundles) {
if (curInitBundle.getLocation().equalsIgnoreCase(newInitBundle.locationString)) {
found = true;
break;
}
}
if (!found) {
try {
curInitBundle.uninstall();
toRefresh.add(curInitBundle);
} catch (BundleException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_FAILED_UNINSTALL, curInitBundle.getLocation()), 0, e, null);
log.log(entry);
}
}
}
}
private static void installBundles(InitialBundle[] initialBundles, Bundle[] curInitBundles, List<Bundle> startBundles, List<Bundle> lazyActivationBundles, List<Bundle> toRefresh) {
for (InitialBundle initialBundle : initialBundles) {
Bundle osgiBundle = getBundleByLocation(initialBundle.locationString, curInitBundles);
try {
if (osgiBundle == null) {
InputStream in = LocationHelper.getStream(initialBundle.location);
try {
osgiBundle = context.installBundle(initialBundle.locationString, in);
}catch (BundleException e) {
if (e.getType() == BundleException.DUPLICATE_BUNDLE_ERROR) {
continue;
}
throw e;
}
if (!initialBundle.start && hasLazyActivationPolicy(osgiBundle)) {
lazyActivationBundles.add(osgiBundle);
}
}
if ((osgiBundle.getState() & Bundle.UNINSTALLED) == 0 && initialBundle.level >= 0) {
osgiBundle.adapt(BundleStartLevel.class).setStartLevel(initialBundle.level);
}
if (initialBundle.start) {
startBundles.add(osgiBundle);
}
if ((osgiBundle.getState() & Bundle.INSTALLED) != 0)
toRefresh.add(osgiBundle);
} catch (BundleException | IOException e) {
FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_FAILED_INSTALL, initialBundle.location), 0, e, null);
log.log(entry);
}
}
}
@SuppressWarnings("deprecation")
private static boolean hasLazyActivationPolicy(Bundle target) {
Dictionary<String, String> headers = target.getHeaders("");
String fragmentHost = headers.get(Constants.FRAGMENT_HOST);
if (fragmentHost != null)
return false;
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 (Constants.ACTIVATION_LAZY.equals(elements[0].getValue()))
return true;
}
} else {
String eclipseLazyStart = headers.get(EquinoxModuleDataNamespace.LAZYSTART_HEADER);
if (eclipseLazyStart == null)
eclipseLazyStart = headers.get(EquinoxModuleDataNamespace.AUTOSTART_HEADER);
ManifestElement[] elements = ManifestElement.parseHeader(EquinoxModuleDataNamespace.AUTOSTART_HEADER, eclipseLazyStart);
if (elements != null && elements.length > 0) {
if ("true".equals(elements[0].getValue()))
return true;
else if (elements[0].getDirective("exceptions") != null)
return true;
}
}
} catch (BundleException be) {
}
return false;
}
private static void startBundles(Bundle[] startBundles, Bundle[] lazyBundles) {
for (Bundle startBundle : startBundles) {
startBundle(startBundle, 0);
}
for (Bundle lazyBundle : lazyBundles) {
startBundle(lazyBundle, 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) {
FrameworkLogEntry entry = new FrameworkLogEntry(EquinoxContainer.NAME, FrameworkLogEntry.ERROR, 0, NLS.bind(Msg.ECLIPSE_STARTUP_FAILED_START, bundle.getLocation()), 0, e, null);
log.log(entry);
}
}
}
private static URL makeRelative(URL base, URL location) throws MalformedURLException {
if (base == null)
return location;
if (!"file".equals(base.getProtocol()))
return location;
if (!location.getProtocol().equals(REFERENCE_PROTOCOL))
return location;
URL nonReferenceLocation = createURL(location.getPath());
if (!base.getProtocol().equals(nonReferenceLocation.getProtocol()))
return location;
File locationPath = new File(nonReferenceLocation.getPath());
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("/"))
urlPath += '/';
URL relativeURL = createURL(base.getProtocol(), base.getHost(), base.getPort(), urlPath);
relativeURL = createURL(REFERENCE_SCHEME + relativeURL.toExternalForm());
return relativeURL;
}
private static URL createURL(String spec) throws MalformedURLException {
return createURL(null, spec);
}
private static URL createURL(URL urlContext, String spec) throws MalformedURLException {
if (context != null && spec.startsWith(REFERENCE_SCHEME)) {
return new URL(urlContext, spec, new Handler(context.getProperty(EquinoxLocations.PROP_INSTALL_AREA)));
}
return new URL(urlContext, spec);
}
private static URL createURL(String protocol, String host, String file) throws MalformedURLException {
return createURL(protocol, host, -1, file);
}
private static URL createURL(String protocol, String host, int port, String file) throws MalformedURLException {
if (context != null && REFERENCE_PROTOCOL.equalsIgnoreCase(protocol)) {
return new URL(protocol, host, port, file, new Handler(context.getProperty(EquinoxLocations.PROP_INSTALL_AREA)));
}
return new URL(protocol, host, port, file);
}
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 setStartLevel(final int value) throws InterruptedException {
FrameworkStartLevel fwkStartLevel = context.getBundle().adapt(FrameworkStartLevel.class);
final Semaphore semaphore = new Semaphore(0);
StartupEventListener listener = new StartupEventListener(semaphore, FrameworkEvent.STARTLEVEL_CHANGED);
context.addBundleListener(listener);
fwkStartLevel.setStartLevel(value, listener);
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;
}
@Override
public void bundleChanged(BundleEvent event) {
if (event.getBundle().getBundleId() == 0 && event.getType() == BundleEvent.STOPPING)
semaphore.release();
}
@Override
public void frameworkEvent(FrameworkEvent event) {
if (event.getType() == frameworkEventType)
semaphore.release();
}
}
private static void updateSplash(Semaphore semaphore, StartupEventListener listener) throws InterruptedException {
ServiceTracker<StartupMonitor, StartupMonitor> monitorTracker = new ServiceTracker<>(context, StartupMonitor.class.getName(), null);
try {
monitorTracker.open();
} catch (IllegalStateException e) {
return;
}
try {
while (true) {
StartupMonitor monitor = monitorTracker.getService();
if (monitor != null) {
try {
monitor.update();
} catch (Throwable e) {
}
}
if (semaphore.tryAcquire(50, TimeUnit.MILLISECONDS))
break;
}
} finally {
if (listener != null) {
try {
context.removeBundleListener(listener);
monitorTracker.close();
} catch (IllegalStateException e) {
}
}
}
}
private static String searchFor(final String target, String start) {
String[] candidates = searchCandidates.get(start);
if (candidates == null) {
File startFile = new File(start);
startFile = LocationHelper.decodePath(startFile);
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 (String candidateName : candidates) {
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 != '-') {
if (candidateName.length() == 4 + target.length() && candidateName.endsWith(".jar"))
simpleJar = true;
else
continue;
}
String version = candidateName.length() > target.length() + 1 && (versionSep == '_' || versionSep == '-') ? candidateName.substring(target.length() + 1) : "";
Object[] currentVersion = getVersionElements(version);
if (currentVersion != null && compareVersion(maxVersion, currentVersion) < 0) {
File candidate = new File(start, candidateName);
boolean candidateIsFile = candidate.isFile();
if (!simpleJar || candidateIsFile) {
result = candidate.getAbsolutePath();
resultIsFile = candidateIsFile;
maxVersion = currentVersion;
}
}
}
if (result == null)
return null;
return result.replace(File.separatorChar, '/') + (resultIsFile ? "" : "/");
}
private static Object[] getVersionElements(String version) {
Object[] result = {Integer.valueOf(-1), Integer.valueOf(-1), Integer.valueOf(-1), ""};
StringTokenizer t = new StringTokenizer(version, ".");
String token;
for (int i = 0; t.hasMoreTokens() && i < 4; i++) {
token = t.nextToken();
if (i < 3) {
try {
result[i] = Integer.valueOf(token);
} catch (Exception e) {
if (i == 0)
return null;
break;
}
} else {
result[i] = token;
}
}
return result;
}
private static int compareVersion(Object[] left, Object[] right) {
if (left == null)
return -1;
int result = ((Integer) left[0]).compareTo((Integer) right[0]);
if (result != 0)
return result;
result = ((Integer) left[1]).compareTo((Integer) right[1]);
if (result != 0)
return result;
result = ((Integer) left[2]).compareTo((Integer) right[2]);
if (result != 0)
return result;
return ((String) left[3]).compareTo((String) right[3]);
}
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;
}
}
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)
setProperty(entry.getKey(), entry.getValue());
else
clearProperty(entry.getKey());
}
}
public static BundleContext getSystemBundleContext() {
if (context == null || !running)
return null;
return context.getBundle().getBundleContext();
}
private static boolean isForcedRestart() {
return Boolean.valueOf(getProperty(EquinoxConfiguration.PROP_FORCED_RESTART)).booleanValue();
}
static void internalAddFrameworkShutdownHandler(Runnable handler) {
if (running)
throw new IllegalStateException(Msg.ECLIPSE_STARTUP_ALREADY_RUNNING);
if (shutdownHandlers == null)
shutdownHandlers = new ArrayList<>();
shutdownHandlers.add(handler);
}
static void internalRemoveFrameworkShutdownHandler(Runnable handler) {
if (running)
throw new IllegalStateException(Msg.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() {
@Override
public void bundleChanged(BundleEvent event) {
if (event.getBundle() == systemBundle && event.getType() == BundleEvent.STOPPED) {
handler.run();
}
}
};
context.addBundleListener(listener);
}
}
}