blob: d40ea1c98f24a6f334c9f53ff45fa4b9c468efde [file] [log] [blame]
package org.eclipse.core.internal.boot;
/*
* Licensed Materials - Property of IBM,
* WebSphere Studio Workbench
* (c) Copyright IBM Corp 2000
*/
import org.eclipse.core.boot.*;
import org.eclipse.core.internal.boot.*;
import java.io.*;
import java.lang.reflect.*;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.zip.ZipFile;
import java.util.*;
/**
* Special boot loader 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 Platform Core Runtime itself, including
* the <code>Platform</code> class, needs to be loaded by a special
* class loader. The upshot is that a client program (such as a Java main
* program, a servlet) cannot directly reference even the
* <code>Platform</code> class. Instead, a client must use this
* loader class for initializing the platform, invoking functionality
* defined in plug-ins, and shutting down the platform when done.
* </p>
*
* @see org.eclipse.core.runtime.Platform
*/
public final class InternalBootLoader {
private static boolean running = false;
private static boolean starting = false;
private static String[] commandLine;
private static ClassLoader loader = null;
private static String baseLocation = null;
private static URL plugins = null;
private static String application = null;
private static URL installURL = null;
private static boolean debugRequested = false;
private static boolean usage = false;
private static String devClassPath = null;
private static String debugOptionsFilename = null;
private static Properties options = null;
private static boolean inDevelopmentMode = false;
// state for tracking the Platform context (e.g., the OS, Window system, locale, ...)
private static String NL = null;
private static String WS = null;
private static String OS = null;
private static final String[] OS_LIST = { BootLoader.OS_WIN32, BootLoader.OS_LINUX, BootLoader.OS_AIX, BootLoader.OS_SOLARIS, BootLoader.OS_HPUX };
private static final String PLATFORM_ENTRYPOINT = "org.eclipse.core.internal.runtime.InternalPlatform";
private static final String BOOTNAME = "org.eclipse.core.boot";
private static final String RUNTIMENAME = "org.eclipse.core.runtime";
private static final String PLUGINSDIR = "plugins/";
private static final String LIBRARY = "library";
private static final String EXPORT = "export";
private static final String EXPORT_PUBLIC = "public";
private static final String EXPORT_PROTECTED = "protected";
private static final String META_AREA = ".metadata";
private static final String PLUGIN_PATH = ".plugin-path";
private static final String BOOTDIR = PLUGINSDIR + BOOTNAME + "/";
private static final String RUNTIMEDIR = PLUGINSDIR + RUNTIMENAME + "/";
private static final String CONFIG = "platform.properties";
private static final String OPTIONS = ".options";
/**
* Execution options for the Runtime plug-in. They are defined here because
* we need to load them into the PlatformClassLoader which is created by the
* boot system. Users should see these options as Runtime options since there
* boot does not figure into normal Platform operation.
*/
private static final String PI_RUNTIME = "org.eclipse.core.runtime";
private static final String OPTION_STARTTIME = PI_RUNTIME + "/starttime";
private static final String OPTION_LOADER_DEBUG = PI_RUNTIME + "/loader/debug";
private static final String OPTION_LOADER_SHOW_CREATE = PI_RUNTIME + "/loader/debug/create";
private static final String OPTION_LOADER_SHOW_ACTIVATE = PI_RUNTIME + "/loader/debug/activateplugin";
private static final String OPTION_LOADER_SHOW_ACTIONS = PI_RUNTIME + "/loader/debug/actions";
private static final String OPTION_LOADER_SHOW_SUCCESS = PI_RUNTIME + "/loader/debug/success";
private static final String OPTION_LOADER_SHOW_FAILURE = PI_RUNTIME + "/loader/debug/failure";
private static final String OPTION_LOADER_FILTER_CLASS = PI_RUNTIME + "/loader/debug/filter/class";
private static final String OPTION_LOADER_FILTER_LOADER = PI_RUNTIME + "/loader/debug/filter/loader";
private static final String OPTION_LOADER_FILTER_RESOURCE = PI_RUNTIME + "/loader/debug/filter/resource";
private static final String OPTION_LOADER_FILTER_NATIVE = PI_RUNTIME + "/loader/debug/filter/native";
private static final String OPTION_URL_DEBUG = PI_RUNTIME+ "/url/debug";
private static final String OPTION_URL_DEBUG_CONNECT = PI_RUNTIME+ "/url/debug/connect";
private static final String OPTION_URL_DEBUG_CACHE_LOOKUP = PI_RUNTIME+ "/url/debug/cachelookup";
private static final String OPTION_URL_DEBUG_CACHE_COPY = PI_RUNTIME+ "/url/debug/cachecopy";
private static final String OPTION_UPDATE_DEBUG = PI_RUNTIME+ "/update/debug";
// command line arguments
private static final String DEBUG = "-debug";
private static final String PLATFORM = "-platform";
private static final String PLUGINS = "-plugins";
private static final String APPLICATION = "-application";
private static final String DEV = "-dev";
private static final String USAGE = "-?";
// Development mode constants
private static final String PLUGIN_JARS = "plugin.jars";
private static final String VA_PROPERTIES = ".va.properties";
private static final String KEY_LIBRARY = "library";
private static final String KEY_EXPORT = "export";
private static final String KEY_PROJECT = "projects";
private static boolean inVAJ;
static {
try {
Class.forName("com.ibm.uvm.lang.ProjectClassLoader");
inVAJ = true;
} catch (Exception e) {
inVAJ = false;
}
}
private static boolean inVAME;
static {
try {
Class.forName("com.ibm.eclipse.core.VAME");
inVAME = true;
} catch (Exception e) {
inVAME = false;
}
}
/**
* Private constructor to block instance creation.
*/
private InternalBootLoader() {
}
private static void assertNotRunning() {
if (running)
throw new RuntimeException("The Platform must not be running");
}
private static void assertRunning() {
if (!running)
throw new RuntimeException("The Platform is not running");
}
/**
* Configure the loader.
* Semantically, the configuration properties are similar to plugin.xml
* They contains the equivalent to <runtime> specification.
* The exact format of the properties is as follows ([a] is optional,
* a* is repeating 0 or more times, {a|b} is a choice)
* <ul>
* <li>library.n= name[,name]*
* <li>export.n=mask[,mask]*
* <eul>
*
*
* index <b>.n</b> is an integer, starting from 1. If multiple <b>library</b>
* entries are present, they must be numbered consecutively. <b>export</b>
* entries are matched to their corresponding <b>library</b> entries.
*
* <b>library</b> defines a list of .jar(s), .zip(s) or directory roots to
* search. These are specified relative to the platform install location.
*
* <b>export</b> optionally specifies exported classes. The mask follows
* Java import conventions. The value indicates which classes are
* visible to other plug-ins. Export mask value of "*" indicates a fully-exported
* runtime. Absent export mask indicates a private runtime.
*/
private static PlatformClassLoader configurePlatformLoader(Properties config) {
Object[] loadPath = getPlatformClassLoaderPath(config);
URL base = null;
try {
base = new URL(PlatformURLBaseConnection.PLATFORM_URL_STRING+RUNTIMEDIR);
} catch (MalformedURLException e) {
}
return new PlatformClassLoader((URL[]) loadPath[0], (URLContentFilter[]) loadPath[1], InternalBootLoader.class.getClassLoader(), base);
}
/**
* @see BootLoader
*/
public static boolean containsSavedPlatform(String location) {
return new File(location + "/" + META_AREA).exists();
}
private static URL[] defaultPluginPath() {
URL[] result = new URL[1];
try {
// at this point use "real" (internal) URL to allow registry manager to discover plugins.
result[0] = new URL(getInstallURL(),PLUGINSDIR);
} catch (MalformedURLException e) {
}
return result;
}
/**
* convert a list of comma-separated tokens into an array
*/
private static String[] getArrayFromList(String prop) {
if (prop == null || prop.trim().equals(""))
return new String[0];
Vector list = new Vector();
StringTokenizer tokens = new StringTokenizer(prop, ",");
while (tokens.hasMoreTokens()) {
String token = tokens.nextToken().trim();
if (!token.equals(""))
list.addElement(token);
}
return list.isEmpty() ? new String[0] : (String[]) list.toArray(new String[0]);
}
private static boolean getBooleanOption(String option, boolean defaultValue) {
String optionValue = options.getProperty(option);
return (optionValue == null) ? defaultValue : optionValue.equalsIgnoreCase("true");
}
/**
* @see BootLoader#getCommandLineArgs
*/
public static String[] getCommandLineArgs() {
return commandLine;
}
/**
* @see BootLoader
*/
public static IInstallInfo getInstallationInfo() {
return LaunchInfo.getCurrent();
}
/**
* @see BootLoader
*/
public static URL getInstallURL() {
if (installURL != null)
return installURL;
// Get the location of this class and compute the install location.
// this involves striping off last element (jar or directory) and adjusting
// for VAJ/VAME peculiarities.
URL url = InternalBootLoader.class.getProtectionDomain().getCodeSource().getLocation();
String path = url.getFile();
if (path.endsWith("/"))
path = path.substring(0, path.length() - 1);
int ix = path.lastIndexOf("/");
path = path.substring(0, ix + 1);
if (!(inVAJ || inVAME)) {
// in jdk ... strip off BOOTDIR
path = path.substring(0, path.length() - BOOTDIR.length());
}
try {
if (url.getProtocol().equals("jar")) installURL = new URL(path);
else installURL = new URL(url.getProtocol(), url.getHost(), url.getPort(), path);
if (debugRequested) System.out.println("Install URL: "+installURL.toExternalForm());
} catch (MalformedURLException e) {
throw new RuntimeException("Fatal Error: Unable to determine platform installation URL "+e);
}
return installURL;
}
private static String[] getListOption(String option) {
String filter = options.getProperty(option);
if (filter == null)
return new String[0];
List result = new ArrayList(5);
StringTokenizer tokenizer = new StringTokenizer(filter, " ,\t\n\r\f");
while (tokenizer.hasMoreTokens())
result.add(tokenizer.nextToken());
return (String[]) result.toArray(new String[result.size()]);
}
/**
* @see BootLoader
*/
public static String getNL() {
return NL;
}
/**
* @see BootLoader
*/
public static String getOS() {
return OS;
}
private static Object[] getPlatformClassLoaderPath(Properties config) {
// If running in va, check for va properties file.
// The property file has entries corresponding to <library>
// elements from the plugin.xml. Each defined property is of form
//
// projects[.libname]=proj1,proj2,proj3
//
// The optional ".libname" suffix allows a project mapping to be specified
// for the corresponding <library>. The default "projects=" (w/o suffix)
// applies to the first/ only <library> element in plugin.xml. Example:
//
// plugin.xml
// <runtime>
// <library name=baseapi.jar>
// <export name="*"/>
// </library>
// <library name=another.jar/>
// <library name=base.jar/>
// </runtime>
//
// .va.properties
// projects=Base API Project
// projects.base.jar=Base Project 1, Base Project 2
// ** OR **
// projects.baseapi.jar=Base API Project
// projects.base.jar=Base Project 1, Base Project 2
//
// The above results in a loader search path consisting of
// Base API Project
// another.jar
// Base Project 1, Base Project 2
//
// Any library access filters specified in the plugin.xml are
// applied to the corresponding loader search path entries
//
Properties jarDefinitions = loadJarDefinitions();
ArrayList urls = new ArrayList(5);
ArrayList cfs = new ArrayList(5);
String execBase = getInstallURL() + RUNTIMEDIR;
String devBase = null;
if (InternalBootLoader.inVAJ || InternalBootLoader.inVAME)
devBase = getInstallURL().toExternalForm();
else
devBase = execBase;
ArrayList list = new ArrayList(5);
// process the config and create a list of alternating library and the library's export filter
for (int i = 1; true; i++) {
// get library specification, if we have run out of library specs, break and return
String key = KEY_LIBRARY + "." + Integer.toString(i);
String value = config.getProperty(key);
if (value == null)
break;
String[] libList = getArrayFromList(value);
// get the corresponding exports if any
key = KEY_EXPORT + "." + Integer.toString(i);
String[] filterList = getArrayFromList(config.getProperty(key));
for (int j = 0; j < libList.length; j++) {
list.add(libList[j]);
list.add(filterList);
}
}
// build a list alternating lib spec and export spec
ArrayList libSpecs = new ArrayList(5);
String[] exportAll = new String[] { "*" };
// add in any development mode class paths and the export all filter
if (DelegatingURLClassLoader.devClassPath != null) {
String[] specs = getArrayFromList(DelegatingURLClassLoader.devClassPath);
// convert dev class path into url strings
for (int j = 0; j < specs.length; j++) {
libSpecs.add(devBase + specs[j] + "/");
libSpecs.add(exportAll);
}
}
// add in the class path entries spec'd in the config. If in development mode,
// add the entries from the plugin.jars first.
for (Iterator i = list.iterator(); i.hasNext();) {
String library = (String) i.next();
String[] filters = (String[]) i.next();
// check for jar definitions
if (jarDefinitions != null) {
String key = library.substring(library.lastIndexOf('/') + 1);
String[] specs = getArrayFromList(jarDefinitions.getProperty(key));
for (int j = 0; j < specs.length; j++) {
libSpecs.add(devBase + specs[j] + "/");
libSpecs.add(filters);
}
}
// convert plugin.xml library entries to url strings if running in JDK
if (!(InternalBootLoader.inVAJ || InternalBootLoader.inVAME)) {
String libSpec = execBase + library.replace(File.separatorChar, '/');
if (!libSpec.endsWith("/")) {
if (libSpec.startsWith(PlatformURLHandler.PROTOCOL + PlatformURLHandler.PROTOCOL_SEPARATOR))
libSpec += PlatformURLHandler.JAR_SEPARATOR;
else
libSpec = PlatformURLHandler.JAR + PlatformURLHandler.PROTOCOL_SEPARATOR + libSpec + PlatformURLHandler.JAR_SEPARATOR;
}
libSpecs.add(libSpec);
libSpecs.add(filters);
}
}
// create path entries for libraries
for (Iterator it = libSpecs.iterator(); it.hasNext();) {
try {
urls.add(new URL((String) it.next()));
cfs.add(new URLContentFilter((String[]) it.next()));
} catch (MalformedURLException e) {
// skip bad URLs
}
}
Object[] result = new Object[2];
result[0] = urls.toArray(new URL[urls.size()]);
result[1] = cfs.toArray(new URLContentFilter[cfs.size()]);
return result;
}
/**
* @see BootLoader
*/
public static URL[] getPluginPath(URL pluginPathLocation) {
InputStream input = null;
// first try and see if the given plugin path location exists.
if (pluginPathLocation == null)
return defaultPluginPath();
try {
input = pluginPathLocation.openStream();
} catch (IOException e) {
}
// if the given path was null or did not exist, look for a plugin path
// definition in the install location.
if (input == null)
try {
URL url = new URL(PlatformURLBaseConnection.PLATFORM_URL_STRING + PLUGIN_PATH);
input = url.openStream();
} catch (MalformedURLException e) {
} catch (IOException e) {
}
// if nothing was found at the supplied location or in the install
// location, compute the default plugin path.
if (input == null)
return defaultPluginPath();
// if we found a plugin path definition somewhere so read it and close the location.
URL[] result = null;
try {
try {
result = readPluginPath(input);
} finally {
input.close();
}
} catch (IOException e) {
}
return result;
}
private static URL[] getPluginPathVa(URL[] pluginPath) {
Vector result = new Vector(Arrays.asList(pluginPath));
if (inVAME) {
// check for projects with plugins on Java classpath
String classpath = System.getProperty("java.class.path");
StringTokenizer paths = new StringTokenizer(classpath, File.pathSeparator);
while (paths.hasMoreTokens()) {
String curr = (String) paths.nextToken();
if (!curr.endsWith(File.separator))
curr += File.separator;
curr += "plugins" + File.separator;
File dir = new File(curr);
if (dir.isDirectory()) {
try {
result.add(dir.toURL());
} catch (MalformedURLException e) {
}
}
}
} else
if (inVAJ /*disabled*/
&& false) {
// check for projects with plugins in project_resources
File pr = new File(getInstallURL().getFile());
String[] projects = ((projects = pr.list()) == null) ? new String[0] : projects;
for (int i = 0; i < projects.length; i++) {
File dir = new File(pr, projects[i] + File.separator + "plugins");
if (dir.isDirectory()) {
try {
result.add(dir.toURL());
} catch (MalformedURLException e) {
}
}
}
}
// if there are no new entries, return original plugin path. Otherwise, return the new path
if (pluginPath.length == result.size())
return pluginPath;
else
return (URL[]) result.toArray(new URL[result.size()]);
}
/**
* @see BootLoader
*/
public static IPlatformRunnable getRunnable(String applicationName) throws Exception {
assertRunning();
Class platform = loader.loadClass(PLATFORM_ENTRYPOINT);
Method method = platform.getDeclaredMethod("loaderGetRunnable", new Class[] {String.class});
try {
return (IPlatformRunnable) method.invoke(platform, new Object[] {applicationName});
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof Error)
throw (Error) e.getTargetException();
else
throw e;
}
}
/**
* @see BootLoader
*/
public static IPlatformRunnable getRunnable(String pluginId, String className, Object args) throws Exception {
assertRunning();
Class platform = loader.loadClass(PLATFORM_ENTRYPOINT);
Method method = platform.getDeclaredMethod("loaderGetRunnable", new Class[] {String.class, String.class, Object.class});
try {
return (IPlatformRunnable) method.invoke(platform, new Object[] {pluginId, className, args});
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof Error)
throw (Error) e.getTargetException();
else
throw e;
}
}
/**
* @see BootLoader
*/
public static String getWS() {
return WS;
}
/**
* @see BootLoader
*/
public static boolean inDebugMode() {
return debugRequested;
}
/**
* @see BootLoader
*/
public static boolean inDevelopmentMode() {
return inDevelopmentMode || inVAJ || inVAME;
}
private static String[] initialize(URL pluginPathLocation, String location, String[] args) throws Exception {
if (running)
throw new RuntimeException("The platform is already running");
// preset the locations so the command line processor does not overwrite.
plugins = pluginPathLocation;
baseLocation = location;
String[] appArgs = processCommandLine(args);
// setup the devClassPath if any
DelegatingURLClassLoader.devClassPath = devClassPath;
setupSystemContext();
// if a platform location was not found in the arguments, set it to user.dir.
// In VAJ, set user.dir to be <code>eclipse</code> in the parent of the install
// directory. This typically makes the platform working directory:
// .../ide/eclipse
if (baseLocation == null) {
if (inVAJ || inVAME) {
String dir = new File(new File(getInstallURL().getFile()).getParent(), "eclipse").getAbsolutePath();
System.setProperty("user.dir", dir);
}
baseLocation = System.getProperty("user.dir");
}
// load any debug options
loadOptions();
// load update profile
LaunchInfo.startup(getInstallURL());
// initialize eclipse URL handling
PlatformURLHandlerFactory.startup(baseLocation + File.separator + META_AREA);
PlatformURLBaseConnection.startup(getInstallURL()); // past this point we can use eclipse:/platform/ URLs
PlatformURLConfigurationConnection.startup(getInstallURL()); // past this point we can use eclipse:/configuration/ URLs
PlatformURLComponentConnection.startup(getInstallURL()); // past this point we can use eclipse:/component/ URLs
// create and configure platform class loader
Properties config = loadConfiguration();
if (config == null)
throw new RuntimeException("Fatal Error: The platform was unable to locate/read platform.properties");
loader = configurePlatformLoader(config);
return appArgs;
}
/**
* Returns the complete plugin path defined by the file at the given location.
* If the given location is <code>null</code> or does not indicate a valid
* pluginPath definition file, the returned value is the default
* pluginPath computed relative to the location of the platform being started.
* If in development mode, the returned value may have additional VA
* values added.
*/
private static URL[] internalGetPluginPath(URL pluginPathLocation) {
URL[] result = getPluginPath(pluginPathLocation);
if (result == null)
result = defaultPluginPath();
// augment with additional VA entries if in development mode.
if (inDevelopmentMode())
result = getPluginPathVa(result);
return result;
}
/**
* @see BootLoader
*/
public static boolean isRunning() {
return running;
}
public static boolean isStarting() {
return starting;
}
/**
* Load platform configuration. Implemented as property file
* because at this point we do not have access to xml support.
*/
private static Properties loadConfiguration() {
Properties config = new Properties();
try {
URL url = BootLoader.class.getResource(CONFIG);
InputStream input = url.openStream();
try {
config.load(input);
return config;
} finally {
input.close();
}
} catch (IOException e) {
}
return null;
}
private static Properties loadJarDefinitions() {
if (!inDevelopmentMode())
return null;
Properties result = null;
InputStream is;
try {
result = new Properties();
URL props = new URL(getInstallURL(), PLUGINSDIR + RUNTIMENAME + "/" + PLUGIN_JARS);
is = props.openStream();
try {
result.load(is);
return result;
} finally {
is.close();
}
} catch (IOException e) {
result = null;
}
return result;
}
private static void loadOptions() {
// if no debug option was specified, don't even bother to try.
// Must ensure that the options slot is null as this is the signal to the
// platform that debugging is not enabled.
if (!debugRequested) {
options = null;
return;
}
options = new Properties();
URL optionsFile;
if (debugOptionsFilename == null)
debugOptionsFilename = getInstallURL().toExternalForm() + OPTIONS;
try {
optionsFile = new URL(debugOptionsFilename);
} catch (MalformedURLException e) {
System.out.println("Unable to construct URL for options file: " + debugOptionsFilename);
e.printStackTrace(System.out);
return;
}
System.out.println("Debug-Options: " + debugOptionsFilename);
try {
InputStream input = optionsFile.openStream();
try {
options.load(input);
} finally {
input.close();
}
} catch (FileNotFoundException e) {
// Its not an error to not find the options file
} catch (IOException e) {
System.out.println("Could not parse the options file: " + optionsFile);
e.printStackTrace(System.out);
}
// trim off all the blanks since properties files don't do that.
for (Iterator i = options.keySet().iterator(); i.hasNext();) {
Object key = i.next();
options.put(key, ((String) options.get(key)).trim());
}
InternalBootLoader.setupOptions();
}
private static String[] processCommandLine(String[] args) throws Exception {
int[] configArgs = new int[100];
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("-"))))) {
found = true;
debugRequested = 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("-"))))) {
inDevelopmentMode = true;
// do not mark the arg as found so it will be passed through
continue;
}
// look for the usage flag
if (args[i].equalsIgnoreCase(USAGE)) {
usage = true;
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("-")) {
continue;
}
String arg = args[++i];
// look for the debug options file location.
if (args[i - 1].equalsIgnoreCase(DEBUG)) {
found = true;
debugRequested = true;
debugOptionsFilename = arg;
}
// look for the development mode and class path entries.
if (args[i - 1].equalsIgnoreCase(DEV)) {
inDevelopmentMode = true;
devClassPath = arg;
// do not mark the arg as found so it will be passed through
continue;
}
// look for the platform location. Only set it if not already set. This
// preserves the value set in the startup() parameter. Be sure however
// to consume the command-line argument.
if (args[i - 1].equalsIgnoreCase(PLATFORM)) {
found = true;
if (baseLocation == null)
baseLocation = arg;
}
// look for the plugins location. Only set it if not already set. This
// preserves the value set in the startup() parameter. Be sure however
// to consume the command-line argument.
if (args[i - 1].equalsIgnoreCase(PLUGINS)) {
found = true;
// if the arg can be made into a URL use it. Otherwise assume that
// it is a file path so make a file URL.
try {
if (plugins == null)
plugins = new URL(arg);
} catch (MalformedURLException e) {
try {
plugins = new URL("file:" + arg);
} catch (MalformedURLException e2) {
}
}
}
// look for the application to run. Only heed the value if the application is
// not already set.
if (args[i - 1].equalsIgnoreCase(APPLICATION)) {
found = true;
if (application == null)
application = arg;
}
// 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)
return args;
String[] passThruArgs = new String[args.length - configArgIndex];
configArgIndex = 0;
int j = 0;
for (int i = 0; i < args.length; i++) {
if (i == configArgs[configArgIndex])
configArgIndex++;
else
passThruArgs[j++] = args[i];
}
return passThruArgs;
}
private static URL[] readPluginPath(InputStream input) {
Properties ini = new Properties();
try {
ini.load(input);
} catch (IOException e) {
return null;
}
Vector result = new Vector(5);
for (Enumeration groups = ini.propertyNames(); groups.hasMoreElements();) {
String group = (String) groups.nextElement();
for (StringTokenizer entries = new StringTokenizer(ini.getProperty(group), ";"); entries.hasMoreElements();) {
String entry = (String) entries.nextElement();
if (!entry.equals(""))
try {
result.addElement(new URL(entry));
} catch (MalformedURLException e) {
}
}
}
return (URL[]) result.toArray(new URL[result.size()]);
}
/**
* @see BootLoader
*/
public static Object run(String applicationName, URL pluginPathLocation, String location, String[] args) throws Exception {
Object result = null;
if (applicationName != null)
application = applicationName;
String[] applicationArgs = null;
try {
applicationArgs = startup(pluginPathLocation, location, args);
} catch (Exception e) {
throw e;
}
IPlatformRunnable runnable = getRunnable(application);
if (runnable == null)
throw new IllegalArgumentException("Application not found: " + application);
try {
result = runnable.run(applicationArgs);
} catch (Throwable e) {
e.printStackTrace();
throw e;
} finally {
shutdown();
return result;
}
}
/**
* Setup the debug flags for the given debug options. This method will likely
* be called twice. Once when loading the options file from the command
* line or install dir and then again when we have loaded options from the
* specific platform metaarea.
*/
public static void setupOptions() {
// if no debug option was specified, don't even bother to try.
// Must ensure that the options slot is null as this is the signal to the
// platform that debugging is not enabled.
if (!debugRequested)
return;
options.put(OPTION_STARTTIME, Long.toString(System.currentTimeMillis()));
DelegatingURLClassLoader.DEBUG = getBooleanOption(OPTION_LOADER_DEBUG, false);
DelegatingURLClassLoader.DEBUG_SHOW_CREATE = getBooleanOption(OPTION_LOADER_SHOW_CREATE, true);
DelegatingURLClassLoader.DEBUG_SHOW_ACTIVATE = getBooleanOption(OPTION_LOADER_SHOW_ACTIVATE, true);
DelegatingURLClassLoader.DEBUG_SHOW_ACTIONS = getBooleanOption(OPTION_LOADER_SHOW_ACTIONS, true);
DelegatingURLClassLoader.DEBUG_SHOW_SUCCESS = getBooleanOption(OPTION_LOADER_SHOW_SUCCESS, true);
DelegatingURLClassLoader.DEBUG_SHOW_FAILURE = getBooleanOption(OPTION_LOADER_SHOW_FAILURE, true);
DelegatingURLClassLoader.DEBUG_FILTER_CLASS = getListOption(OPTION_LOADER_FILTER_CLASS);
DelegatingURLClassLoader.DEBUG_FILTER_LOADER = getListOption(OPTION_LOADER_FILTER_LOADER);
DelegatingURLClassLoader.DEBUG_FILTER_RESOURCE = getListOption(OPTION_LOADER_FILTER_RESOURCE);
DelegatingURLClassLoader.DEBUG_FILTER_NATIVE = getListOption(OPTION_LOADER_FILTER_NATIVE);
PlatformURLConnection.DEBUG = getBooleanOption(OPTION_URL_DEBUG, false);
PlatformURLConnection.DEBUG_CONNECT = getBooleanOption(OPTION_URL_DEBUG_CONNECT, true);
PlatformURLConnection.DEBUG_CACHE_LOOKUP = getBooleanOption(OPTION_URL_DEBUG_CACHE_LOOKUP, true);
PlatformURLConnection.DEBUG_CACHE_COPY = getBooleanOption(OPTION_URL_DEBUG_CACHE_COPY, true);
LaunchInfo.DEBUG = getBooleanOption(OPTION_UPDATE_DEBUG, false);
}
/**
* Initializes the execution context for this run of the platform. The context
* includes information about the locale, operating system and window system.
*/
private static void setupSystemContext() {
if (NL == null)
NL = Locale.getDefault().toString();
if (OS == null) {
String name = System.getProperty("os.name");
for (int i = 0; i < OS_LIST.length; i++)
if (name.regionMatches(true, 0, OS_LIST[i], 0, 3))
OS = OS_LIST[i];
if (OS == null)
OS = BootLoader.OS_UNKNOWN;
}
if (WS == null)
WS = BootLoader.WS_UNKNOWN;
}
/**
* @see BootLoader
*/
public static void shutdown() throws Exception {
assertRunning();
// no matter what happens, record that its no longer running
running = false;
Class platform = loader.loadClass(PLATFORM_ENTRYPOINT);
Method method = platform.getDeclaredMethod("loaderShutdown", new Class[0]);
try {
method.invoke(platform, new Object[0]);
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof Error)
throw (Error) e.getTargetException();
else
throw e;
} finally {
PlatformURLHandlerFactory.shutdown();
LaunchInfo.shutdown();
loader = null;
}
}
/**
* @see BootLoader
*/
public static String[] startup(URL pluginPathLocation, String location, String[] args) throws Exception {
assertNotRunning();
starting = true;
commandLine = args;
String[] applicationArgs = initialize(pluginPathLocation, location, args);
Class platform = loader.loadClass(PLATFORM_ENTRYPOINT);
Method method = platform.getDeclaredMethod("loaderStartup", new Class[] { URL[].class, String.class, Properties.class, String[].class });
try {
URL[] pluginPath = internalGetPluginPath(plugins);
method.invoke(platform, new Object[] { pluginPath, baseLocation, options, args });
} catch (InvocationTargetException e) {
if (e.getTargetException() instanceof Error)
throw (Error) e.getTargetException();
else
throw e;
}
// only record the platform as running if everything went swimmingly
running = true;
starting = false;
return applicationArgs;
}
}