/*******************************************************************************
 * Copyright (c) 2000, 2006 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.launcher;

import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.*;
import java.security.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * The launcher for Eclipse.
 */
public class Main {
    /**
     * Indicates whether this instance is running in debug mode.
     */
    protected boolean debug = false;

    /**
     * The location of the launcher to run.
     */
    protected String bootLocation = null;

    /**
     * The location of the install root
     */
    protected URL installLocation = null;

    /**
     * The location of the configuration information for this instance
     */
    protected URL configurationLocation = null;

    /**
     * The location of the configuration information in the install root
     */
    protected String parentConfigurationLocation = null;

    /**
     * The id of the bundle that will contain the framework to run.  Defaults to org.eclipse.osgi.
     */
    protected String framework = OSGI;

    /**
     * The extra development time class path entries.
     */
    protected String devClassPath = null;

    /**
     * Indicates whether this instance is running in development mode.
     */
    protected boolean inDevelopmentMode = false;

    private String exitData = null;
    private String name = null; // The name to brand the launcher
    private String launcher = null; // The full path to the launcher

    private String vm = null;
    private String[] vmargs = null;
    private String[] commands = null;
    private String[] extensionPaths = null;

    // splash handling
    private String showSplash = null;
    private String endSplash = null;
    private boolean initialize = false;
    private Process showProcess = null;
    private boolean splashDown = false;
    public final class EndSplashHandler extends Thread {
    	public void run() {
    		takeDownSplash();
    	}
    	public OutputStream getOutputStream() {
			return showProcess == null ? null : showProcess.getOutputStream();
		}
    }
    private final Thread endSplashHandler = new EndSplashHandler();

    // command line args
    private static final String FRAMEWORK = "-framework"; //$NON-NLS-1$
    private static final String INSTALL = "-install"; //$NON-NLS-1$
    private static final String INITIALIZE = "-initialize"; //$NON-NLS-1$
    private static final String VM = "-vm"; //$NON-NLS-1$
    private static final String VMARGS = "-vmargs"; //$NON-NLS-1$
    private static final String DEBUG = "-debug"; //$NON-NLS-1$
    private static final String DEV = "-dev"; //$NON-NLS-1$
    private static final String CONFIGURATION = "-configuration"; //$NON-NLS-1$
    private static final String EXITDATA = "-exitdata"; //$NON-NLS-1$
    private static final String NOSPLASH = "-nosplash"; //$NON-NLS-1$
    private static final String SHOWSPLASH = "-showsplash"; //$NON-NLS-1$
    private static final String NAME = "-name"; //$NON-NLS-1$
    private static final String LAUNCHER = "-launcher"; //$NON-NLS-1$
	private static final String NL = "-nl";  //$NON-NLS-1$
    private static final String ENDSPLASH = "-endsplash"; //$NON-NLS-1$
    private static final String SPLASH_IMAGE = "splash.bmp"; //$NON-NLS-1$
	private static final String CLEAN = "-clean"; //$NON-NLS-1$
	private static final String NOEXIT = "-noExit";  //$NON-NLS-1$
	
    private static final String OSGI = "org.eclipse.osgi"; //$NON-NLS-1$
    private static final String STARTER = "org.eclipse.core.runtime.adaptor.EclipseStarter"; //$NON-NLS-1$
    private static final String PLATFORM_URL = "platform:/base/"; //$NON-NLS-1$
    private static final String ECLIPSE_PROPERTIES = "eclipse.properties"; //$NON-NLS-1$
    private static final String FILE_SCHEME = "file:"; //$NON-NLS-1$    
    protected static final String REFERENCE_SCHEME = "reference:"; //$NON-NLS-1$
    protected static final String JAR_SCHEME = "jar:"; //$NON-NLS-1$
    
    private static final String DEFAULT_JRE_REQUIRED = "1.4.1"; //$NON-NLS-1$
    
    // constants: configuration file location
    private static final String CONFIG_DIR = "configuration/"; //$NON-NLS-1$
    private static final String CONFIG_FILE = "config.ini"; //$NON-NLS-1$
    private static final String CONFIG_FILE_TEMP_SUFFIX = ".tmp"; //$NON-NLS-1$
    private static final String CONFIG_FILE_BAK_SUFFIX = ".bak"; //$NON-NLS-1$
    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$

    // constants: System property keys and/or configuration file elements
    private static final String PROP_USER_HOME = "user.home"; //$NON-NLS-1$
    private static final String PROP_USER_DIR = "user.dir"; //$NON-NLS-1$
    private static final String PROP_INSTALL_AREA = "osgi.install.area"; //$NON-NLS-1$
    private static final String PROP_CONFIG_AREA = "osgi.configuration.area"; //$NON-NLS-1$
    private static final String PROP_CONFIG_AREA_DEFAULT = "osgi.configuration.area.default"; //$NON-NLS-1$
    private static final String PROP_BASE_CONFIG_AREA = "osgi.baseConfiguration.area"; //$NON-NLS-1$
    private static final String PROP_SHARED_CONFIG_AREA = "osgi.sharedConfiguration.area"; //$NON-NLS-1$
    private static final String PROP_CONFIG_CASCADED = "osgi.configuration.cascaded"; //$NON-NLS-1$
    protected static final String PROP_FRAMEWORK = "osgi.framework"; //$NON-NLS-1$
    private static final String PROP_SPLASHPATH = "osgi.splashPath"; //$NON-NLS-1$
    private static final String PROP_SPLASHLOCATION = "osgi.splashLocation"; //$NON-NLS-1$
    private static final String PROP_CLASSPATH = "osgi.frameworkClassPath"; //$NON-NLS-1$
    private static final String PROP_EXTENSIONS = "osgi.framework.extensions"; //$NON-NLS-1$
    private static final String PROP_FRAMEWORK_SYSPATH = "osgi.syspath"; //$NON-NLS-1$
    private static final String PROP_FRAMEWORK_SHAPE = "osgi.framework.shape"; //$NON-NLS-1$
    private static final String PROP_LOGFILE = "osgi.logfile"; //$NON-NLS-1$
    private static final String PROP_REQUIRED_JAVA_VERSION = "osgi.requiredJavaVersion"; //$NON-NLS-1$
    private static final String PROP_PARENT_CLASSLOADER = "osgi.parentClassloader"; //$NON-NLS-1$
	private static final String PROP_NL = "osgi.nl";  //$NON-NLS-1$
    private static final String PROP_NOSHUTDOWN = "osgi.noShutdown"; //$NON-NLS-1$
    private static final String PROP_DEBUG = "osgi.debug"; //$NON-NLS-1$	
	
    private static final String PROP_EXITCODE = "eclipse.exitcode"; //$NON-NLS-1$
    private static final String PROP_EXITDATA = "eclipse.exitdata"; //$NON-NLS-1$

    private static final String PROP_VM = "eclipse.vm"; //$NON-NLS-1$
    private static final String PROP_VMARGS = "eclipse.vmargs"; //$NON-NLS-1$
    private static final String PROP_COMMANDS = "eclipse.commands"; //$NON-NLS-1$
    private static final String PROP_ECLIPSESECURITY = "eclipse.security"; //$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$

    // types of parent classloaders the framework can have
    private static final String PARENT_CLASSLOADER_APP = "app"; //$NON-NLS-1$
    private static final String PARENT_CLASSLOADER_EXT = "ext"; //$NON-NLS-1$
    private static final String PARENT_CLASSLOADER_BOOT = "boot"; //$NON-NLS-1$

    // log file handling
    protected static final String SESSION = "!SESSION"; //$NON-NLS-1$
    protected static final String ENTRY = "!ENTRY"; //$NON-NLS-1$
    protected static final String MESSAGE = "!MESSAGE"; //$NON-NLS-1$
    protected static final String STACK = "!STACK"; //$NON-NLS-1$
    protected static final int ERROR = 4;
    protected static final String PLUGIN_ID = "org.eclipse.core.launcher"; //$NON-NLS-1$
    protected File logFile = null;
    protected BufferedWriter log = null;
    protected boolean newSession = true;

    /**
     * A structured form for a version identifier.
     * 
     * @see http://java.sun.com/j2se/versioning_naming.html for information on valid version strings
     */
    static class Identifier {
        private static final String DELIM = ". _-"; //$NON-NLS-1$
        private int major, minor, service;
        Identifier(int major, int minor, int service) {
            super();
            this.major = major;
            this.minor = minor;
            this.service = service;
        }
        /**
         * @throws NumberFormatException if cannot parse the major and minor version components
         */
        Identifier(String versionString) {
            super();
            StringTokenizer tokenizer = new StringTokenizer(versionString, DELIM);

            // major
            if (tokenizer.hasMoreTokens())
                major = Integer.parseInt(tokenizer.nextToken());

            // minor
            if (tokenizer.hasMoreTokens())
                minor = Integer.parseInt(tokenizer.nextToken());

            try {
                // service
                if (tokenizer.hasMoreTokens())
                    service = Integer.parseInt(tokenizer.nextToken());
            } catch (NumberFormatException nfe) {
                // ignore the service qualifier in that case and default to 0
                // this will allow us to tolerate other non-conventional version numbers 
            }
        }
        /**
         * Returns true if this id is considered to be greater than or equal to the given baseline.
         * e.g. 
         * 1.2.9 >= 1.3.1 -> false
         * 1.3.0 >= 1.3.1 -> false
         * 1.3.1 >= 1.3.1 -> true
         * 1.3.2 >= 1.3.1 -> true
         * 2.0.0 >= 1.3.1 -> true
         */
        boolean isGreaterEqualTo(Identifier minimum) {
            if (major < minimum.major)
                return false;
            if (major > minimum.major)
                return true;
            // major numbers are equivalent so check minor
            if (minor < minimum.minor)
                return false;
            if (minor > minimum.minor)
                return true;
            // minor numbers are equivalent so check service
            return service >= minimum.service;
        }
    }   

    /**
     * Executes the launch.
     * 
     * @param args command-line arguments
     * @exception Exception thrown if a problem occurs during the launch
     */
    protected void basicRun(String[] args) throws Exception {
        System.getProperties().setProperty("eclipse.startTime", Long.toString(System.currentTimeMillis())); //$NON-NLS-1$
        commands = args;
        String[] passThruArgs = processCommandLine(args);
        if (!debug)
        	// debug can be specified as system property as well
        	debug = System.getProperty(PROP_DEBUG) != null;
        setupVMProperties();
        processConfiguration();
        
        //ensure minimum Java version
        if (!checkVersion(System.getProperty("java.version"), System.getProperty(PROP_REQUIRED_JAVA_VERSION, DEFAULT_JRE_REQUIRED))) //$NON-NLS-1$
            return;
        
        // need to ensure that getInstallLocation is called at least once to initialize the value.
        // Do this AFTER processing the configuration to allow the configuration to set
        // the install location.  
        getInstallLocation();

        // locate boot plugin (may return -dev mode variations)
        URL[] bootPath = getBootPath(bootLocation);
        setSecurityPolicy(bootPath);
        // splash handling is done here, because the default case needs to know
        // the location of the boot plugin we are going to use
        handleSplash(bootPath);

        invokeFramework(passThruArgs, bootPath);
    }

    protected void setSecurityPolicy(URL[] bootPath) {
        String eclipseSecurity = System.getProperty(PROP_ECLIPSESECURITY);
        if (eclipseSecurity != null) {
            SecurityManager sm = System.getSecurityManager();
            boolean setSM = false;
            if (sm == null) {
                if (eclipseSecurity.length() < 1) {
                    eclipseSecurity = "java.lang.SecurityManager"; //$NON-NLS-1$
                }
                try {
                    Class clazz = Class.forName(eclipseSecurity);
                    sm = (SecurityManager) clazz.newInstance();
                    setSM = true;
                }
                catch (Throwable t) {
                    System.setProperty("java.security.manager", eclipseSecurity); // let the framework try to load it later. //$NON-NLS-1$
                }
            }
            
            ProtectionDomain domain = Main.class.getProtectionDomain();
            CodeSource source = null; 
            if (domain != null)
            	source = Main.class.getProtectionDomain().getCodeSource();
			if (domain == null || source == null) {
				log("Can not automatically set the security manager. Please use a policy file."); //$NON-NLS-1$
				return;
			}
            // get the list of codesource URLs to grant AllPermission to
            URL[] rootURLs = new URL[bootPath.length + 1];
			rootURLs[0] = source.getLocation();
            System.arraycopy(bootPath, 0, rootURLs, 1, bootPath.length);
            // replace the security policy
            Policy eclipsePolicy = new EclipsePolicy(Policy.getPolicy(), rootURLs);
            Policy.setPolicy(eclipsePolicy);
            if (setSM)
                System.setSecurityManager(sm);
        }
    }

    private void invokeFramework(String[] passThruArgs, URL[] bootPath) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, Error, Exception, InvocationTargetException {
        String type = System.getProperty(PROP_PARENT_CLASSLOADER, PARENT_CLASSLOADER_BOOT);
        ClassLoader parent = null;
        if (PARENT_CLASSLOADER_APP.equalsIgnoreCase(type))
            parent = ClassLoader.getSystemClassLoader();
        else if (PARENT_CLASSLOADER_EXT.equalsIgnoreCase(type)) {
            ClassLoader appCL = ClassLoader.getSystemClassLoader();
            if (appCL != null)
                parent = appCL.getParent();
        }
        URLClassLoader loader = new StartupClassLoader(bootPath, parent);
        Class clazz = loader.loadClass(STARTER);
        Method method = clazz.getDeclaredMethod("run", new Class[] {String[].class, Runnable.class}); //$NON-NLS-1$
        try {
            method.invoke(clazz, new Object[] {passThruArgs, endSplashHandler});
        } catch (InvocationTargetException e) {
            if (e.getTargetException() instanceof Error)
                throw (Error) e.getTargetException();
            else if (e.getTargetException() instanceof Exception)
                throw (Exception) e.getTargetException();
            else
                //could be a subclass of Throwable!
                throw e;
        }
    }

    /**
     * Checks whether the given available version is greater or equal to the 
     * given required version.
     * <p>Will set PROP_EXITCODE/PROP_EXITDATA accordingly if check fails.</p>
     *   
     * @return a boolean indicating whether the checking passed 
     */
    protected boolean checkVersion(String availableVersion, String requiredVersion) {
        if (requiredVersion == null || availableVersion == null)
            return true;
        try {
            Identifier required = new Identifier(requiredVersion);
            Identifier available = new Identifier(availableVersion);
            boolean compatible = available.isGreaterEqualTo(required);
            if (!compatible) {
                // any non-zero value should do it - 14 used to be used for version incompatibility in Eclipse 2.1 
                System.getProperties().put(PROP_EXITCODE, "14"); //$NON-NLS-1$
                System.getProperties().put(PROP_EXITDATA, "<title>Incompatible JVM</title>Version " + availableVersion + " of the JVM is not suitable for this product. Version: "+ requiredVersion + " or greater is required."); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
            }
            return compatible;
        } catch (SecurityException e) {
            // If the security manager won't allow us to get the system property, continue for
            // now and let things fail later on their own if necessary.
            return true;
        } catch (NumberFormatException e) {
            // If the version string was in a format that we don't understand, continue and
            // let things fail later on their own if necessary.
            return true;
        }
    }
    
    /**
     * Returns a string representation of the given URL String.  This converts
     * escaped sequences (%..) in the URL into the appropriate characters.
     * NOTE: due to class visibility there is a copy of this method
     *       in InternalBootLoader
     */
    protected String decode(String urlString) {
        //try to use Java 1.4 method if available
        try {
            Class clazz = URLDecoder.class;
            Method method = clazz.getDeclaredMethod("decode", new Class[] {String.class, String.class}); //$NON-NLS-1$
            //first encode '+' characters, because URLDecoder incorrectly converts 
            //them to spaces on certain class library implementations.
            if (urlString.indexOf('+') >= 0) {
                int len = urlString.length();
                StringBuffer buf = new StringBuffer(len);
                for (int i = 0; i < len; i++) {
                    char c = urlString.charAt(i);
                    if (c == '+')
                        buf.append("%2B"); //$NON-NLS-1$
                    else
                        buf.append(c);
                }
                urlString = buf.toString();
            }
            Object result = method.invoke(null, new Object[] {urlString, "UTF-8"}); //$NON-NLS-1$
            if (result != null)
                return (String) result;
        } catch (Exception e) {
            //JDK 1.4 method not found -- fall through and decode by hand
        }
        //decode URL by hand
        boolean replaced = false;
        byte[] encodedBytes = urlString.getBytes();
        int encodedLength = encodedBytes.length;
        byte[] decodedBytes = new byte[encodedLength];
        int decodedLength = 0;
        for (int i = 0; i < encodedLength; i++) {
            byte b = encodedBytes[i];
            if (b == '%') {
            	if(i+2 >= encodedLength)
            		throw new IllegalArgumentException("Malformed URL (\""+urlString+"\"): % must be followed by 2 digits.");  //$NON-NLS-1$//$NON-NLS-2$
                byte enc1 = encodedBytes[++i];
                byte enc2 = encodedBytes[++i];
                b = (byte) ((hexToByte(enc1) << 4) + hexToByte(enc2));
                replaced = true;
            }
            decodedBytes[decodedLength++] = b;
        }
        if (!replaced)
            return urlString;
        try {
            return new String(decodedBytes, 0, decodedLength, "UTF-8"); //$NON-NLS-1$
        } catch (UnsupportedEncodingException e) {
            //use default encoding
            return new String(decodedBytes, 0, decodedLength);
        }
    }

    /**
     * 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
     */
    protected String[] getArrayFromList(String prop) {
        if (prop == null || prop.trim().equals("")) //$NON-NLS-1$
            return new String[0];
        Vector list = new Vector();
        StringTokenizer tokens = new StringTokenizer(prop, ","); //$NON-NLS-1$
        while (tokens.hasMoreTokens()) {
            String token = tokens.nextToken().trim();
            if (!token.equals("")) //$NON-NLS-1$
                list.addElement(token);
        }
        return list.isEmpty() ? new String[0] : (String[]) list.toArray(new String[list.size()]);
    }

    /**
     * Returns the <code>URL</code>-based class path describing where the boot classes
     * are located when running in development mode.
     * 
     * @return the url-based class path
     * @param base the base location
     * @exception MalformedURLException if a problem occurs computing the class path
     */
    private URL[] getDevPath(URL base) throws IOException {
        ArrayList result = new ArrayList(5);
        if (inDevelopmentMode)
            addDevEntries(base, result);
        //The jars from the base always need to be added, even when running in dev mode (bug 46772)
        addBaseJars(base, result);
        return (URL[]) result.toArray(new URL[result.size()]);
    }

    URL constructURL(URL url, String name) {
        //Recognize the following URLs
        //url: file:foo/dir/
        //url: file:foo/file.jar
        
        String externalForm = url.toExternalForm();
        if (externalForm.endsWith(".jar")) { //$NON-NLS-1$
            try {
                return new URL(JAR_SCHEME + url + "!/" + name); //$NON-NLS-1$
            } catch (MalformedURLException e) {
                //Ignore
            }
        }
        
        try {
            return new URL(url, name);
        } catch (MalformedURLException e) {
            //Ignore
            return null;
        }
    }
    private void readFrameworkExtensions(URL base, ArrayList result) throws IOException {
        String[] extensions = getArrayFromList(System.getProperties().getProperty(PROP_EXTENSIONS));
        String parent = new File(base.getFile()).getParent().toString();
        ArrayList extensionResults = new ArrayList(extensions.length);
        for (int i = 0; i < extensions.length; i++) {
            //Search the extension relatively to the osgi plugin 
            String path = searchFor(extensions[i], parent);
            if (path == null) {
                log("Could not find extension: " + extensions[i]); //$NON-NLS-1$
                continue;
            }
            if (debug)
                System.out.println("Loading extension: " + extensions[i]); //$NON-NLS-1$

            URL extensionURL = null;
            if (installLocation.getProtocol().equals("file")) { //$NON-NLS-1$
                extensionResults.add(path);
                extensionURL = new File(path).toURL();
            } else
                extensionURL = new URL(installLocation.getProtocol(), installLocation.getHost(), installLocation.getPort(), path);

            //Load a property file of the extension, merge its content, and in case of dev mode add the bin entries
            Properties extensionProperties = null;
            try {
                extensionProperties = loadProperties(constructURL(extensionURL, ECLIPSE_PROPERTIES));
            } catch (IOException e) {
                if (debug)
                    System.out.println("\t" + ECLIPSE_PROPERTIES + " not found"); //$NON-NLS-1$ //$NON-NLS-2$
            }
            String extensionClassPath = null;
            if (extensionProperties != null)
                extensionClassPath = extensionProperties.getProperty(PROP_CLASSPATH);
            else // this is a "normal" RFC 101 framework extension bundle just put the base path on the classpath
                extensionProperties = new Properties();
            String[] entries = extensionClassPath == null || extensionClassPath.length() == 0 ? new String[] {""} : getArrayFromList(extensionClassPath); //$NON-NLS-1$
            String qualifiedPath;
			if (System.getProperty(PROP_CLASSPATH)==null)
				qualifiedPath = "."; //$NON-NLS-1$
			else
				qualifiedPath = ""; //$NON-NLS-1$
            for (int j = 0; j < entries.length; j++)
                qualifiedPath += ", " + FILE_SCHEME + path + entries[j]; //$NON-NLS-1$
            extensionProperties.put(PROP_CLASSPATH, qualifiedPath);
            mergeProperties(System.getProperties(), extensionProperties);
            if (inDevelopmentMode) 
                addDevEntries(extensionURL, result);
        }
        extensionPaths = (String[]) extensionResults.toArray(new String[extensionResults.size()]);
    }

    private void addBaseJars(URL base, ArrayList result) throws IOException {
        String baseJarList = System.getProperty(PROP_CLASSPATH);
        if (baseJarList == null) {
            readFrameworkExtensions(base, result);
            baseJarList = System.getProperties().getProperty(PROP_CLASSPATH);
        }
        
        File fwkFile = new File(base.getFile());
        boolean fwkIsDirectory = fwkFile.isDirectory();
        //We found where the fwk is, remember it and its shape
        if (fwkIsDirectory) {
            System.getProperties().setProperty(PROP_FRAMEWORK_SHAPE, "folder");//$NON-NLS-1$
        } else {
            System.getProperties().setProperty(PROP_FRAMEWORK_SHAPE, "jar");//$NON-NLS-1$
        }
	    String fwkPath = new File(base.getFile()).getParentFile().getAbsolutePath();
		if (Character.isUpperCase(fwkPath.charAt(0))) {
			char[] chars = fwkPath.toCharArray();
			chars[0] = Character.toLowerCase(chars[0]);
			fwkPath = new String(chars);
		}
        System.getProperties().setProperty(PROP_FRAMEWORK_SYSPATH, fwkPath);
        
        String[] baseJars = getArrayFromList(baseJarList);
        if (baseJars.length == 0) {
            if (!inDevelopmentMode && new File(base.getFile()).isDirectory())
                throw new IOException("Unable to initialize " + PROP_CLASSPATH); //$NON-NLS-1$
            addEntry(base, result);
            return;
        }
        for (int i = 0; i < baseJars.length; i++) {
            String string = baseJars[i];
            try {
                // if the string is a file: URL then *carefully* construct the
                // URL. Otherwisejust try to build a URL. In either case, if we fail, use
                // string as something to tack on the end of the base.
                
                if (string.equals(".")) { //$NON-NLS-1$
                    addEntry(base, result);
                }
                URL url = null;
                if (string.startsWith(FILE_SCHEME))
                    url = new File(string.substring(5)).toURL();
                else
                    url = new URL(string);
                addEntry(url, result);
            } catch (MalformedURLException e) {
                addEntry(new URL(base, string), result);
            }
        }
    }

	protected void addEntry(URL url, List result) {
        if (new File(url.getFile()).exists())
            result.add(url);
    }

    private void addDevEntries(URL base, List result) throws MalformedURLException {
        String[] locations = getArrayFromList(devClassPath);
        for (int i = 0; i < locations.length; i++) {
            String location = locations[i];
            File path = new File(location);
            URL url;
            if (path.isAbsolute())
                url = path.toURL();
            else {
                // dev path is relative, combine with base location
                char lastChar = location.charAt(location.length() - 1);
                if ((location.endsWith(".jar") || (lastChar == '/' || lastChar == '\\'))) //$NON-NLS-1$
                    url = new URL(base, location);
                else
                    url = new URL(base, location + "/"); //$NON-NLS-1$
            }
            addEntry(url, result);
        }
    }

    /**
     * Returns the <code>URL</code>-based class path describing where the boot classes are located.
     * 
     * @return the url-based class path
     * @param base the base location
     * @exception MalformedURLException if a problem occurs computing the class path
     */
    protected URL[] getBootPath(String base) throws IOException {
        URL url = null;
        if (base != null) {
            url = buildURL(base, true);
        } else {
            // search in the root location
            url = getInstallLocation();
            String path = new File(url.getFile(), "plugins").toString(); //$NON-NLS-1$
            path = searchFor(framework, path);
            if (path == null)
                throw new RuntimeException("Could not find framework"); //$NON-NLS-1$
            if (url.getProtocol().equals("file")) //$NON-NLS-1$
                url = new File(path).toURL();
            else
                url = new URL(url.getProtocol(), url.getHost(), url.getPort(), path);
        }
        if (System.getProperty(PROP_FRAMEWORK) == null)
            System.getProperties().put(PROP_FRAMEWORK, url.toExternalForm());
        if (debug)
            System.out.println("Framework located:\n    " + url.toExternalForm()); //$NON-NLS-1$
        // add on any dev path elements
        URL[] result = getDevPath(url);
        if (debug) {
            System.out.println("Framework classpath:"); //$NON-NLS-1$
            for (int i = 0; i < result.length; i++)
                System.out.println("    " + result[i].toExternalForm()); //$NON-NLS-1$
        }
        return result;
    }

    /**
     * Searches for the given target directory starting in the "plugins" subdirectory
     * of the given 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
     */
    protected String searchFor(final String target, String start) {
        FileFilter filter = new FileFilter() {
            public boolean accept(File candidate) {
                return candidate.getName().equals(target) || candidate.getName().startsWith(target + "_"); //$NON-NLS-1$
            }
        };
        File[] candidates = new File(start).listFiles(filter);
        if (candidates == null)
            return null;
        String[] arrays = new String[candidates.length];
        for (int i = 0; i < arrays.length; i++) {
            arrays[i] = candidates[i].getName();
        }
       int result = findMax(arrays);
        if (result == -1)
            return null;
        return candidates[result].getAbsolutePath().replace(File.separatorChar, '/') + (candidates[result].isDirectory() ? "/" : "");  //$NON-NLS-1$//$NON-NLS-2$
    }

    protected int findMax(String[] candidates) {
        int result = -1;
        Object maxVersion = null;
        for (int i = 0; i < candidates.length; i++) {
            String name = candidates[i];
            String version = ""; //$NON-NLS-1$ // Note: directory with version suffix is always > than directory without version suffix
            int index = name.indexOf('_');
            if (index != -1)
                version = name.substring(index + 1);
            Object currentVersion = getVersionElements(version);
            if (maxVersion == null) {
                result = i;
                maxVersion = currentVersion;
            } else {
                if (compareVersion((Object[]) maxVersion, (Object[]) currentVersion) < 0) {
                    result = i;
                    maxVersion = currentVersion;
                }
            }
        }
        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 int compareVersion(Object[] left, Object[] right) {

        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
    }

    /**
     * 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). Note, that returning anything else will cause exceptions in the caller.
     */
    private Object[] getVersionElements(String version) {
        if (version.endsWith(".jar")) //$NON-NLS-1$
            version = version.substring(0, version.length() - 4);
        Object[] result = {new Integer(0), new Integer(0), new Integer(0), ""}; //$NON-NLS-1$
        StringTokenizer t = new StringTokenizer(version, "."); //$NON-NLS-1$
        String token;
        int i = 0;
        while (t.hasMoreTokens() && i < 4) {
            token = t.nextToken();
            if (i < 3) {
                // major, minor or service ... numeric values
                try {
                    result[i++] = new Integer(token);
                } catch (Exception e) {
                    // invalid number format - use default numbers (0) for the rest
                    break;
                }
            } else {
                // qualifier ... string value
                result[i++] = token;
            }
        }
        return result;
    }

    private static URL buildURL(String spec, boolean trailingSlash) {
        if (spec == null)
            return null;
        boolean isFile = spec.startsWith(FILE_SCHEME);
        try {
            if (isFile) {
                File toAdjust = new File(spec.substring(5));
                if (toAdjust.isDirectory())
                    return adjustTrailingSlash(toAdjust.toURL(), trailingSlash);
                else
                    return toAdjust.toURL();
            } else
                return new URL(spec);
        } catch (MalformedURLException e) {
            // if we failed and it is a file spec, there is nothing more we can do
            // otherwise, try to make the spec into a file URL.
            if (isFile)
                return null;
            try {
                File toAdjust = new File(spec);
                if (toAdjust.isDirectory())
                    return adjustTrailingSlash(toAdjust.toURL(), trailingSlash);
                else
                    return toAdjust.toURL();
            } catch (MalformedURLException e1) {
                return null;
            }
        }
    }

    private static URL adjustTrailingSlash(URL url, boolean trailingSlash) throws MalformedURLException {
        String file = url.getFile();
        if (trailingSlash == (file.endsWith("/"))) //$NON-NLS-1$
            return url;
        file = trailingSlash ? file + "/" : file.substring(0, file.length() - 1); //$NON-NLS-1$
        return new URL(url.getProtocol(), url.getHost(), file);
    }

    private URL buildLocation(String property, URL defaultLocation, String userDefaultAppendage) {
        URL result = null;
        String location = System.getProperty(property);
        System.getProperties().remove(property);
        // if the instance location is not set, predict where the workspace will be and 
        // put the instance area inside the workspace meta area.
        try {
            if (location == null)
                result = defaultLocation;
            else if (location.equalsIgnoreCase(NONE))
                return null;
            else if (location.equalsIgnoreCase(NO_DEFAULT))
                result = buildURL(location, true);
            else {
                if (location.startsWith(USER_HOME)) {
                    String base = substituteVar(location, USER_HOME, PROP_USER_HOME);
                    location = new File(base, userDefaultAppendage).getAbsolutePath();
                } else if (location.startsWith(USER_DIR)) {
                    String base = substituteVar(location, USER_DIR, PROP_USER_DIR);
                    location = new File(base, userDefaultAppendage).getAbsolutePath();
                }
                result = buildURL(location, true);
            }
        } finally {
            if (result != null)
                System.getProperties().put(property, result.toExternalForm());
        }
        return result;
    }

    private String substituteVar(String source, String var, String prop) {
        String value = System.getProperty(prop, ""); //$NON-NLS-1$
        return value + source.substring(var.length());
    }

    /** 
     * Retuns the default file system path for the configuration location.
     * By default the configuration information is in the installation directory
     * if this is writeable.  Otherwise it is located somewhere in the user.home
     * area relative to the current product. 
     * @return the default file system path for the configuration information
     */
    private 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 install = getInstallLocation();
        // TODO a little dangerous here.  Basically we have to assume that it is a file URL.
        if (install.getProtocol().equals("file")) { //$NON-NLS-1$
            File installDir = new File(install.getFile());
            if (canWrite(installDir))
                return installDir.getAbsolutePath() + File.separator + CONFIG_DIR;
        }
        // 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(File installDir) {
        if (installDir.canWrite() == false)
            return false;

        if (!installDir.isDirectory())
            return false;

        File fileTest = null;
        try {
            fileTest = File.createTempFile("writtableArea", null, installDir); //$NON-NLS-1$
        } catch (IOException e) {
            //If an exception occured while trying to create the file, it means that it is not writtable
            return false;
        } finally {
            if (fileTest != null)
                fileTest.delete();
        }
        return true;
    }
    
    /**
     * Returns a files system path for an area in the user.home region related to the
     * current product.  The given appendage is added to this base location
     * @param pathAppendage the path segments to add to computed base
     * @return a file system location in the user.home area related the the current
     *   product and the given appendage
     */
    private 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.
        URL installURL = getInstallLocation();
        if (installURL == null)
            return null;
        File installDir = new File(installURL.getFile());
        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; //$NON-NLS-1$
            } catch (IOException e) {
                // Do nothing if we get an exception.  We will default to a standard location 
                // in the user's home dir.
            }
        }
        String userHome = System.getProperty(PROP_USER_HOME);
        return new File(userHome, appName + "/" + pathAppendage).getAbsolutePath(); //$NON-NLS-1$
    }

    /**
     * Runs this launcher with the arguments specified in the given string.
     * 
     * @param argString the arguments string
     */
    public static void main(String argString) {
        Vector list = new Vector(5);
        for (StringTokenizer tokens = new StringTokenizer(argString, " "); tokens.hasMoreElements();) //$NON-NLS-1$
            list.addElement(tokens.nextElement());
        main((String[]) list.toArray(new String[list.size()]));
    }

    /**
     * Runs the platform with the given arguments.  The arguments must identify
     * an application to run (e.g., <code>-application com.example.application</code>).
     * After running the application <code>System.exit(N)</code> is executed.
     * The value of N is derived from the value returned from running the application.
     * If the application's return value is an <code>Integer</code>, N is this value.
     * In all other cases, N = 0.
     * <p>
     * Clients wishing to run the platform without a following <code>System.exit</code>
     * call should use <code>run()</code>.
     * </p>
     * 
     * @param args the command line arguments
     * @see #run(String[])
     */
	public static void main(String[] args) {
		int result = 0;
		try {
			result = new Main().run(args);
		} catch (Throwable t) {
			// This is *really* unlikely to happen - run() takes care of exceptional situations.
			// In case something weird happens, just dump stack - logging is not available at this point
			t.printStackTrace();
		} finally {
			if (!Boolean.getBoolean(PROP_NOSHUTDOWN))
			// make sure we always terminate the VM
				System.exit(result);
		}
	}


    /**
     * Runs the platform with the given arguments.  The arguments must identify
     * an application to run (e.g., <code>-application com.example.application</code>).
     * Returns the value returned from running the application.
     * If the application's return value is an <code>Integer</code>, N is this value.
     * In all other cases, N = 0.
     *
     * @param args the command line arguments
     */
    public int run(String[] args) {
        int result = 0;
        try {
            basicRun(args);
            String exitCode = System.getProperty(PROP_EXITCODE);
            try {
                result = exitCode == null ? 0 : Integer.parseInt(exitCode);
            } catch (NumberFormatException e) {
                result = 17;
            }
        } catch (Throwable e) {
            // only log the exceptions if they have not been caught by the 
            // EclipseStarter (i.e., if the exitCode is not 13) 
            if (!"13".equals(System.getProperty(PROP_EXITCODE))) { //$NON-NLS-1$
                log("Exception launching the Eclipse Platform:"); //$NON-NLS-1$
                log(e);
                String message = "An error has occurred"; //$NON-NLS-1$
                if (logFile == null)
                    message += " and could not be logged: \n" + e.getMessage(); //$NON-NLS-1$
                else
                    message += ".  See the log file\n" + logFile.getAbsolutePath(); //$NON-NLS-1$
                System.getProperties().put(PROP_EXITDATA, message);
            }
            // Return "unlucky" 13 as the exit code. The executable will recognize
            // this constant and display a message to the user telling them that
            // there is information in their log file.
            result = 13;
        } finally {
            // always try putting down the splash screen just in case the application failed to do so
            takeDownSplash();           
        }
        // Return an int exit code and ensure the system property is set.
        System.getProperties().put(PROP_EXITCODE, Integer.toString(result));
        setExitData();
        return result;
    }

    private void setExitData() {
        String data = System.getProperty(PROP_EXITDATA);
        if (exitData == null || data == null)
            return;
        // sync call to the launcher
        runCommand(true, new String[] {EXITDATA, exitData, data});
    }

    /**
     * Processes the command line arguments.  The general principle is to NOT
     * consume the arguments and leave them to be processed by Eclipse proper.
     * There are a few args which are directed towards main() and a few others
     * which we need to know about. Very few should actually be consumed here.
     * 
     * @return the arguments to pass through to the launched application
     * @param args the command line arguments
     */
    protected String[] processCommandLine(String[] args) {
        if (args.length == 0)
            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 (args[i].equalsIgnoreCase(DEBUG)) {
                debug = true;
                // passed thru this arg (i.e., do not set found = true)
                continue;
            }

            // look for and consume the nosplash directive.  This supercedes any
            // -showsplash command that might be present.
            if (args[i].equalsIgnoreCase(NOSPLASH)) {
                splashDown = true;
                found = true;
            }

            if (args[i].equalsIgnoreCase(NOEXIT)) {
            	System.getProperties().put(PROP_NOSHUTDOWN, "true"); //$NON-NLS-1$
            	found = true;
            }
            
            // check if this is initialization pass
            if (args[i].equalsIgnoreCase(INITIALIZE)) {
                initialize = true;
                // passed thru this arg (i.e., do not set found = true)
                continue;
            }

            // 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$
                inDevelopmentMode = true;
                // do not mark the arg as found so it will be passed through
                continue;
            }

            // done checking for args.  Remember where an arg was found 
            if (found) {
                configArgs[configArgIndex++] = i;
                continue;
            }

            // look for the VM args arg.  We have to do that before looking to see
            // if the next element is a -arg as the thing following -vmargs may in
            // fact be another -arg.
            if (args[i].equalsIgnoreCase(VMARGS)) {
                // consume the -vmargs arg itself
                args[i] = null;
                i++;
                vmargs = new String[args.length - i];
                for (int j = 0; i < args.length; i++) {
                    vmargs[j++] = args[i];
                    args[i] = null;
                }
                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 development mode and class path entries.  
            if (args[i - 1].equalsIgnoreCase(DEV)) {
                inDevelopmentMode = true;
                devClassPath = processDevArg(arg);
                continue;
            }

            // look for the framework to run
            if (args[i - 1].equalsIgnoreCase(FRAMEWORK)) {
                framework = arg;
                found = true;
            }

            // look for explicitly set install root
            // Consume the arg here to ensure that the launcher and Eclipse get the 
            // same value as each other.  
            if (args[i - 1].equalsIgnoreCase(INSTALL)) {
                System.getProperties().put(PROP_INSTALL_AREA, arg);
                found = true;
            }

            // look for the configuration to use.  
            // Consume the arg here to ensure that the launcher and Eclipse get the 
            // same value as each other.  
            if (args[i - 1].equalsIgnoreCase(CONFIGURATION)) {
                System.getProperties().put(PROP_CONFIG_AREA, arg);
                found = true;
            }

            // look for the command to use to set exit data in the launcher
            if (args[i - 1].equalsIgnoreCase(EXITDATA)) {
                exitData = arg;
                found = true;
            }

            // look for the command to use to show the splash screen
            if (args[i - 1].equalsIgnoreCase(SHOWSPLASH)) {
                showSplash = arg;
                found = true;
            }

            // look for the name to use by the launcher
            if (args[i - 1].equalsIgnoreCase(NAME)) {
                name = arg;
                found = true;
            }

            // look for the launcher location
            if (args[i - 1].equalsIgnoreCase(LAUNCHER)) {
                launcher = arg;
                found = true;
            }
            
            // look for the command to use to end the splash screen
            if (args[i - 1].equalsIgnoreCase(ENDSPLASH)) {
                endSplash = arg;
                found = true;
            }

            // look for the VM location arg
            if (args[i - 1].equalsIgnoreCase(VM)) {
                vm = arg;
                found = true;
            }

			//look for the nl setting
			if (args[i - 1].equalsIgnoreCase(NL)) {
				System.getProperties().put(PROP_NL, 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
        String[] passThruArgs = new String[args.length - configArgIndex - (vmargs == null ? 0 : vmargs.length + 1)];
        configArgIndex = 0;
        int j = 0;
        for (int i = 0; i < args.length; i++) {
            if (i == configArgs[configArgIndex])
                configArgIndex++;
            else if (args[i] != null)
                passThruArgs[j++] = args[i];
        }
        return passThruArgs;
    }

    private String processDevArg(String arg) {
        if (arg == null)
            return null;
        try {
            URL location = new URL(arg);
            Properties props = load(location, null);
            String result = props.getProperty(OSGI);
            return result == null ? props.getProperty("*") : result; //$NON-NLS-1$
        } catch (MalformedURLException e) {
            // the arg was not a URL so use it as is.
            return arg;
        } catch (IOException e) {
            // TODO consider logging here
            return null;
        }
    }

    private URL getConfigurationLocation() {
        if (configurationLocation != null)
            return configurationLocation;
        configurationLocation = buildLocation(PROP_CONFIG_AREA, null, ""); //$NON-NLS-1$
        if (configurationLocation == null) {
            configurationLocation = buildLocation(PROP_CONFIG_AREA_DEFAULT, null, ""); //$NON-NLS-1$
            if (configurationLocation == null)
                configurationLocation = buildURL(computeDefaultConfigurationLocation(), true);
        }
        if (configurationLocation != null)
            System.getProperties().put(PROP_CONFIG_AREA, configurationLocation.toExternalForm());
        if (debug)
            System.out.println("Configuration location:\n    " + configurationLocation); //$NON-NLS-1$
        return configurationLocation;
    }

    private void processConfiguration() {
        // if the configuration area is not already defined, discover the config area by
        // trying to find a base config area.  This is either defined in a system property or
        // is computed relative to the install location.
        // Note that the config info read here is only used to determine a value 
        // for the user configuration area
        URL baseConfigurationLocation = null;
        Properties baseConfiguration = null;
        if (System.getProperty(PROP_CONFIG_AREA) == null) {
            String baseLocation = System.getProperty(PROP_BASE_CONFIG_AREA);
            if (baseLocation != null)
                // here the base config cannot have any symbolic (e..g, @xxx) entries.  It must just
                // point to the config file.
                baseConfigurationLocation = buildURL(baseLocation, true);
            if (baseConfigurationLocation == null)
                try {
                    // here we access the install location but this is very early.  This case will only happen if
                    // the config area is not set and the base config area is not set (or is bogus).
                    // In this case we compute based on the install location.
                    baseConfigurationLocation = new URL(getInstallLocation(), CONFIG_DIR);
                } catch (MalformedURLException e) {
                    // leave baseConfigurationLocation null
                }
            baseConfiguration = loadConfiguration(baseConfigurationLocation);
            if (baseConfiguration != null) {
                // if the base sets the install area then use that value if the property.  We know the 
                // property is not already set.
                String location = baseConfiguration.getProperty(PROP_CONFIG_AREA);
                if (location != null)
                    System.getProperties().put(PROP_CONFIG_AREA, location);
                // if the base sets the install area then use that value if the property is not already set.
                // This helps in selfhosting cases where you cannot easily compute the install location
                // from the code base.
                location = baseConfiguration.getProperty(PROP_INSTALL_AREA);
                if (location != null && System.getProperty(PROP_INSTALL_AREA) == null)
                    System.getProperties().put(PROP_INSTALL_AREA, location);
            }
        }

        // Now we know where the base configuration is supposed to be.  Go ahead and load
        // it and merge into the System properties.  Then, if cascaded, read the parent configuration
        // Note that the parent may or may not be the same parent as we read above since the 
        // base can define its parent.  The first parent we read was either defined by the user
        // on the command line or was the one in the install dir.  
        // if the config or parent we are about to read is the same as the base config we read above,
        // just reuse the base
        Properties configuration = baseConfiguration;
        if (configuration == null || !getConfigurationLocation().equals(baseConfigurationLocation))
            configuration = loadConfiguration(getConfigurationLocation());
        mergeProperties(System.getProperties(), configuration);
        if ("false".equalsIgnoreCase(System.getProperty(PROP_CONFIG_CASCADED))) //$NON-NLS-1$
            // if we are not cascaded then remove the parent property even if it was set.
            System.getProperties().remove(PROP_SHARED_CONFIG_AREA);
        else {
        	ensureAbsolute(PROP_SHARED_CONFIG_AREA);
            URL sharedConfigURL = buildLocation(PROP_SHARED_CONFIG_AREA, null, ""); //$NON-NLS-1$
            if (sharedConfigURL == null)
                try {
                    // there is no shared config value so compute one
                    sharedConfigURL = new URL(getInstallLocation(), CONFIG_DIR);
                } catch (MalformedURLException e) {
                    // leave sharedConfigurationLocation null
                }
            // if the parent location is different from the config location, read it too.
            if (sharedConfigURL != null) {
                if (sharedConfigURL.equals(getConfigurationLocation()))
                    // remove the property to show that we do not have a parent.
                    System.getProperties().remove(PROP_SHARED_CONFIG_AREA);
                else {
                    // if the parent we are about to read is the same as the base config we read above,
                    // just reuse the base
                    configuration = baseConfiguration;
                    if (!sharedConfigURL.equals(baseConfigurationLocation))
                        configuration = loadConfiguration(sharedConfigURL);
                    mergeProperties(System.getProperties(), configuration);
                    System.getProperties().put(PROP_SHARED_CONFIG_AREA, sharedConfigURL.toExternalForm());
                    if (debug)
                        System.out.println("Shared configuration location:\n    " + sharedConfigURL.toExternalForm()); //$NON-NLS-1$
                }
            }
        }
        // setup the path to the framework
        String urlString = System.getProperty(PROP_FRAMEWORK, null);
        if (urlString != null) {
            URL url = buildURL(urlString, true);
            System.getProperties().put(PROP_FRAMEWORK, url.toExternalForm());
            bootLocation = resolve(urlString);
        }
    }

    /**
	 * Ensures the value for a system property is an absolute URL. Relative URLs are translated to
	 * absolute URLs by taking the install URL as reference.
	 *   
	 * @param locationProperty the key for a system property containing a URL
	 */
	private void ensureAbsolute(String locationProperty) {
		String propertyValue = System.getProperty(locationProperty);
		if (propertyValue == null)
			// property not defined
			return;
		URL locationURL = null;
		try {
			locationURL = new URL(propertyValue);
		} catch (MalformedURLException e) {
			// property is not a valid URL
			return;
		}
		String locationPath = locationURL.getPath();
		if (locationPath.startsWith("/")) //$NON-NLS-1$
			// property value is absolute
			return;
		URL installURL = getInstallLocation();
		if (!locationURL.getProtocol().equals(installURL.getProtocol()))
			// not same protocol
			return;
		try {
			URL absoluteURL = new URL(installURL, locationPath);
			System.getProperties().put(locationProperty, absoluteURL.toExternalForm());
		} catch (MalformedURLException e) {
			// should not happen - the relative URL is known to be valid
		}
	}

    /**
     * Returns url of the location this class was loaded from
     */
    private URL getInstallLocation() {
        if (installLocation != null)
            return installLocation;

        // value is not set so compute the default and set the value
        String installArea = System.getProperty(PROP_INSTALL_AREA);
        if (installArea != null) {
            installLocation = buildURL(installArea, true);
            if (installLocation == null)
                throw new IllegalStateException("Install location is invalid: " + installArea); //$NON-NLS-1$
            System.getProperties().put(PROP_INSTALL_AREA, installLocation.toExternalForm());
            if (debug)
                System.out.println("Install location:\n    " + installLocation); //$NON-NLS-1$
            return installLocation;
        }

        ProtectionDomain domain = Main.class.getProtectionDomain();
        CodeSource source = null;
		URL result = null;
        if (domain != null)
        	source = domain.getCodeSource();
        if (source == null || domain == null) {
			if (debug)
				System.out.println("CodeSource location is null. Defaulting the install location to file:startup.jar"); //$NON-NLS-1$
			try {
				result = new URL("file:startup.jar"); //$NON-NLS-1$
			} catch (MalformedURLException e2) {
				//Ignore
			}
        }
		if (source != null)
			result = source.getLocation();
		
        String path = decode(result.getFile());
        // normalize to not have leading / so we can check the form
        File file = new File(path);
        path = file.toString().replace('\\', '/');
        // TODO need a better test for windows
        // If on Windows then canonicalize the drive letter to be lowercase.
        // remember that there may be UNC paths 
        if (File.separatorChar == '\\')
            if (Character.isUpperCase(path.charAt(0))) {
                char[] chars = path.toCharArray();
                chars[0] = Character.toLowerCase(chars[0]);
                path = new String(chars);
            }
        if (path.toLowerCase().endsWith(".jar")) //$NON-NLS-1$
            path = path.substring(0, path.lastIndexOf("/") + 1); //$NON-NLS-1$
        try {
            try {
                // create a file URL (via File) to normalize the form (e.g., put 
                // the leading / on if necessary)
                path = new File(path).toURL().getFile();
            } catch (MalformedURLException e1) {
                // will never happen.  The path is straight from a URL.  
            }
            installLocation = new URL(result.getProtocol(), result.getHost(), result.getPort(), path);
            System.getProperties().put(PROP_INSTALL_AREA, installLocation.toExternalForm());
        } catch (MalformedURLException e) {
            // TODO Very unlikely case.  log here.  
        }
        if (debug)
            System.out.println("Install location:\n    " + installLocation); //$NON-NLS-1$
        return installLocation;
    }

    /*
     * Load the given configuration file
     */
    private Properties loadConfiguration(URL url) {
        Properties result = null;
        try {
            url = new URL(url, CONFIG_FILE);
        } catch (MalformedURLException e) {
            return null;
        }
        try {
            if (debug)
                System.out.print("Configuration file:\n    " + url.toString()); //$NON-NLS-1$
            result = loadProperties(url);
            if (debug)
                System.out.println(" loaded"); //$NON-NLS-1$
        } catch (IOException e) {
            if (debug)
                System.out.println(" not found or not read"); //$NON-NLS-1$
        }
        return result;
    }

    private Properties loadProperties(URL url) throws IOException {
        // try to load saved configuration file (watch for failed prior save())
        if (url == null)
            return null;
        Properties result = null;
        IOException originalException = null;
        try {
            result = load(url, null); // try to load config file
        } catch (IOException e1) {
            originalException = e1;
            try {
                result = load(url, CONFIG_FILE_TEMP_SUFFIX); // check for failures on save
            } catch (IOException e2) {
                try {
                    result = load(url, CONFIG_FILE_BAK_SUFFIX); // check for failures on save
                } catch (IOException e3) {
                    throw originalException; // we tried, but no config here ...
                }
            }
        }
        return result;
    }

    /*
     * Load the configuration  
     */
    private Properties load(URL url, String suffix) throws IOException {
        // figure out what we will be loading
        if (suffix != null && !suffix.equals("")) //$NON-NLS-1$
            url = new URL(url.getProtocol(), url.getHost(), url.getPort(), url.getFile() + suffix);

        // try to load saved configuration file
        Properties props = new Properties();
        InputStream is = null;
        try {
            is = url.openStream();
            props.load(is);
        } finally {
            if (is != null)
                try {
                    is.close();
                } catch (IOException e) {
                    //ignore failure to close
                }
        }
        return props;
    }

    /*
     * Handle splash screen.
     * We support 2 startup scenarios:
     * 
     * (1) the executable launcher put up the splash screen. In that
     *     scenario we are invoked with -endsplash command which is
     *     fully formed to take down the splash screen
     * 
     * (2) the executable launcher did not put up the splash screen,
     *     but invokes Eclipse with partially formed -showsplash command.
     *     In this scenario we determine which splash to display (based on 
     *     feature information) and then call -showsplash command. 
     * 
     * In both scenarios we pass a handler (Runnable) to the platform.
     * The handler is called as a result of the launched application calling
     * Platform.endSplash(). In the first scenario this results in the
     * -endsplash command being executed. In the second scenario this
     * results in the process created as a result of the -showsplash command
     * being destroyed.
     * 
     * @param defaultPath search path for the boot plugin
     */
    private void handleSplash(URL[] defaultPath) {
        // run without splash if we are initializing or nosplash 
        // was specified (splashdown = true)
        if (initialize || splashDown) {
            showSplash = null;
            endSplash = null;
            return;
        }
        
        if (showSplash != null || endSplash != null) {
        	// Register the endSplashHandler to be run at VM shutdown. This hook will be 
        	// removed once the splash screen has been taken down.
        	try {
        		Runtime.getRuntime().addShutdownHook(endSplashHandler);
        	} catch(Exception ex) {
        		// Best effort to register the handler
        	}
        }

        // if -endsplash is specified, use it and ignore any -showsplash command
        if (endSplash != null) {
            showSplash = null;
            return;
        }

        // check if we are running without a splash screen
        if (showSplash == null)
            return;

        // determine the splash location
        String location = getSplashLocation(defaultPath);
        if (debug)
            System.out.println("Splash location:\n    " + location); //$NON-NLS-1$
        if (location == null)
            return;
        // async call to the launcher
        showProcess = runCommand(false, new String[] {SHOWSPLASH, showSplash, location});
    }
    
    private Process runCommand(boolean block, String[] extraArgs) {
        final int NBR_DEFAULT_ARGS = 3;
        String[] args = new String[NBR_DEFAULT_ARGS + extraArgs.length];
        args[0] = launcher;
        args[1] = NAME;
        args[2] = name;

        for (int i = 0; i < extraArgs.length; i++) {
            args[i + NBR_DEFAULT_ARGS] = extraArgs[i];
        }

        if (debug) {
            System.out.print("runCommand:\n    ");//$NON-NLS-1$ 
            for (int i = 0; i < args.length; i++) {
                System.out.print('<' + args[i] + '>');
            }
            System.out.println();
        }

        Process result = null;
        try {
            result = Runtime.getRuntime().exec(args);
            if (block)
                result.waitFor();
        } catch (Exception e) {
            log("Exception running command: " + extraArgs != null && extraArgs.length > 0 ? extraArgs[0] : null); //$NON-NLS-1$ 
            log(e);
        }
        return result;
    }

    /*
     * Take down the splash screen. Try both take-down methods just in case
     * (only one should ever be set)
     */
    protected void takeDownSplash() {
        if (splashDown) // splash is already down
            return;

        // check if -endsplash was specified
        if (endSplash != null) {
            try {
                Runtime.getRuntime().exec(endSplash);
            } catch (Exception e) {
                //ignore failure to end splash
            }
        }

        // check if -showsplash was specified and executed
        if (showProcess != null) {
            showProcess.destroy();
            showProcess = null;
        }
        splashDown = true;
        
        try {
        	Runtime.getRuntime().removeShutdownHook(endSplashHandler);
        } catch (IllegalStateException e) {
        	// OK to ignore this, happens when the VM is already shutting down
        }
    }

    /*
     * Return path of the splash image to use.  First search the defined splash path.
     * If that does not work, look for a default splash.  Currently the splash must be in the file system
     * so the return value here is the file system path.
     */
    private String getSplashLocation(URL[] bootPath) {
        String result = System.getProperty(PROP_SPLASHLOCATION);
        if (result != null)
            return result;
        String splashPath = System.getProperty(PROP_SPLASHPATH);
        if (splashPath != null) {
            String[] entries = getArrayFromList(splashPath);
            ArrayList path = new ArrayList(entries.length);
            for (int i = 0; i < entries.length; i++) {
                String entry = resolve(entries[i]);
                if (entry == null || entry.startsWith(FILE_SCHEME)) {
                    File entryFile = new File(entry.substring(5).replace('/', File.separatorChar));
                    entry = searchFor(entryFile.getName(), entryFile.getParent());
                    if (entry != null)
                        path.add(entry);
                } else
                    log("Invalid splash path entry: " + entries[i]); //$NON-NLS-1$
            }
            // see if we can get a splash given the splash path
            result = searchForSplash((String[]) path.toArray(new String[path.size()]));
            if (result != null) {
                System.getProperties().put(PROP_SPLASHLOCATION, result);
                return result;
            }
        }

        // can't find it on the splashPath so look for a default splash
        String temp = bootPath[0].getFile(); // take the first path element
        temp = temp.replace('/', File.separatorChar);
        int ix = temp.lastIndexOf("plugins" + File.separator); //$NON-NLS-1$
        if (ix != -1) {
            int pix = temp.indexOf(File.separator, ix + 8);
            if (pix != -1) {
                temp = temp.substring(0, pix);
                result = searchForSplash(new String[] {temp});
                if (result != null)
                    System.getProperties().put(PROP_SPLASHLOCATION, result);
            }
        }
        return result;
    }

    /*
     * Do a locale-sensitive lookup of splash image
     */
    private String searchForSplash(String[] searchPath) {
        if (searchPath == null)
            return null;

        // Get the splash screen for the specified locale
		String locale = (String) System.getProperties().get(PROP_NL);
		if (locale == null)
			locale = Locale.getDefault().toString();
		String[] nlVariants = buildNLVariants(locale);

		for (int i=0; i<nlVariants.length; i++) {
			for (int j=0; j<searchPath.length; j++) {
				// do we have a JAR?
				if (isJAR(searchPath[j])) {
					String result = extractSplashFromJAR(searchPath[j], nlVariants[i]);
					if (result != null)
						return result;
				} else {
					// we have a file or a directory
	                String path = searchPath[j];
	                if (!path.endsWith(File.separator))
	                    path += File.separator;
	                path += nlVariants[i];
	                File result = new File(path);
	                if (result.exists())
	                    return result.getAbsolutePath(); // return the first match found [20063]
				}
			}
		}

        // sorry, could not find splash image
        return null;
    }

	/**
	 * Transfers all available bytes from the given input stream to the given output stream. 
	 * Regardless of failure, this method closes both streams.
	 */
	private static void transferStreams(InputStream source, OutputStream destination) {
		byte[] buffer = new byte[8096];
		try {
			while (true) {
				int bytesRead = -1;
				try {
					bytesRead = source.read(buffer);
				} catch (IOException e) {
					return;
				}
				if (bytesRead == -1)
					break;
				try {
					destination.write(buffer, 0, bytesRead);
				} catch (IOException e) {
					return;
				}
			}
		} finally {
			try {
				source.close();
			} catch (IOException e) {
				// ignore
			} finally {
				//close destination in finally in case source.close fails
				try {
					destination.close();
				} catch (IOException e) {
					// ignore
				}
			}
		}
	}

	/*
	 * Look for the specified spash file in the given JAR and extract it to the config 
	 * area for caching purposes.
	 */
	private String extractSplashFromJAR(String jarPath, String splashPath) {
		String configLocation = System.getProperty(PROP_CONFIG_AREA);
		if (configLocation == null) {
			log("Configuration area not set yet. Unable to extract splash from JAR'd plug-in: " + jarPath); //$NON-NLS-1$
			return null;
		}
		URL configURL = buildURL(configLocation, false);
		if (configURL == null)
			return null;
		// cache the splash in the OSGi sub-dir in the config area
		File splash = new File(configURL.getPath(), OSGI);
		splash = new File(splash, splashPath);
		// if we have already extracted this file before, then return
		if (splash.exists()) {
			// if we are running with -clean then delete the cached splash file
			boolean clean = false;
			for (int i=0; i<commands.length; i++) {
				if (CLEAN.equalsIgnoreCase(commands[i])) {
					clean = true;
					splash.delete();
					break;
				}
			}
			if (!clean)
				return splash.getAbsolutePath();
		}
		ZipFile file;
		try {
			file = new ZipFile(jarPath);
		} catch (IOException e) {
			log("Exception looking for splash  in JAR file: " + jarPath); //$NON-NLS-1$
			log(e);
			return null;
		}
		ZipEntry entry = file.getEntry(splashPath.replace(File.separatorChar, '/'));
		if (entry == null)
			return null;
		InputStream input = null;
		try {
			input = file.getInputStream(entry);
		} catch (IOException e) {
			log("Exception opening splash: " + entry.getName() + " in JAR file: " + jarPath);  //$NON-NLS-1$ //$NON-NLS-2$
			log(e);
			return null;
		}
		splash.getParentFile().mkdirs();
		OutputStream output;
		try {
			output = new BufferedOutputStream(new FileOutputStream(splash));
		} catch (FileNotFoundException e) {
			try {
				input.close();
			} catch (IOException e1) {
				// ignore
			}
			return null;
		}
		transferStreams(input, output);
		return splash.exists() ? splash.getAbsolutePath() : null;
	}

	/*
	 * Return a boolean value indicating whether or not the given
	 * path represents a JAR file.
	 */
	private boolean isJAR(String path) {
		if (path.endsWith(File.separator))
			return false;
		int index = path.lastIndexOf('.');
		if (index == -1)
			return false;
		index++;
		// handle the case where we have a '.' at the end
		if (index >= path.length()) 
			return false;
		return "JAR".equalsIgnoreCase(path.substring(index)); //$NON-NLS-1$
	}

	/*
	 * Build an array of path suffixes based on the given NL which is suitable
	 * for splash path searching.  The returned array contains paths in order 
	 * from most specific to most generic. So, in the FR_fr locale, it will return 
	 * "nl/fr/FR/splash.bmp", then "nl/fr/splash.bmp", and finally "splash.bmp". 
	 * (we always search the root)
	 */
	private static String[] buildNLVariants(String locale) {
		//build list of suffixes for loading resource bundles
		String nl = locale;
		ArrayList result = new ArrayList(4);
		int lastSeparator;
		while (true) {
			result.add("nl" + File.separatorChar + nl.replace('_', File.separatorChar) + File.separatorChar + SPLASH_IMAGE); //$NON-NLS-1$
			lastSeparator = nl.lastIndexOf('_');
			if (lastSeparator == -1)
				break;
			nl = nl.substring(0, lastSeparator);
		}
		//add the empty suffix last (most general)
		result.add(SPLASH_IMAGE);
		return (String[]) result.toArray(new String[result.size()]);
	}

    /*
     * resolve platform:/base/ URLs
     */
    private String resolve(String urlString) {
        // handle the case where people mistakenly spec a refererence: url.
        if (urlString.startsWith(REFERENCE_SCHEME)) {
            urlString = urlString.substring(10);
            System.getProperties().put(PROP_FRAMEWORK, urlString);
        }
        if (urlString.startsWith(PLATFORM_URL)) {
            String path = urlString.substring(PLATFORM_URL.length());
            return getInstallLocation() + path;
        } else
            return urlString;
    }

    /*
     * Entry point for logging.
     */
    protected synchronized void log(Object obj) {
        if (obj == null)
            return;
        try {
            openLogFile();
            try {
                if (newSession) {
                    log.write(SESSION);
                    log.write(' ');
                    String timestamp = new Date().toString();
                    log.write(timestamp);
                    log.write(' ');
                    for (int i = SESSION.length() + timestamp.length(); i < 78; i++)
                        log.write('-');
                    log.newLine();
                    newSession = false;
                }
                write(obj);
            } finally {
                if (logFile == null) {
                    if (log != null)
                        log.flush();
                } else
                    closeLogFile();
            }
        } catch (Exception e) {
            System.err.println("An exception occurred while writing to the platform log:"); //$NON-NLS-1$
            e.printStackTrace(System.err);
            System.err.println("Logging to the console instead."); //$NON-NLS-1$
            //we failed to write, so dump log entry to console instead
            try {
                log = logForStream(System.err);
                write(obj);
                log.flush();
            } catch (Exception e2) {
                System.err.println("An exception occurred while logging to the console:"); //$NON-NLS-1$
                e2.printStackTrace(System.err);
            }
        } finally {
            log = null;
        }
    }

    /*
     * This should only be called from #log()
     */
    private void write(Object obj) throws IOException {
        if (obj == null)
            return;
        if (obj instanceof Throwable) {
            log.write(STACK);
            log.newLine();
            ((Throwable) obj).printStackTrace(new PrintWriter(log));
        } else {
            log.write(ENTRY);
            log.write(' ');
            log.write(PLUGIN_ID);
            log.write(' ');
            log.write(String.valueOf(ERROR));
            log.write(' ');
            log.write(String.valueOf(0));
            log.write(' ');
            try {
                DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SS"); //$NON-NLS-1$
                log.write(formatter.format(new Date()));
            } catch (Exception e) {
                // continue if we can't write out the date
                log.write(Long.toString(System.currentTimeMillis()));
            }
            log.newLine();
            log.write(MESSAGE);
            log.write(' ');
            log.write(String.valueOf(obj));
        }
        log.newLine();
    }

    private void computeLogFileLocation() {
        String logFileProp = System.getProperty(PROP_LOGFILE);
        if (logFileProp != null) {
            if (logFile == null || !logFileProp.equals(logFile.getAbsolutePath())) {
                logFile = new File(logFileProp);
                logFile.getParentFile().mkdirs();
            }
            return;
        }

        // compute the base location and then append the name of the log file
        URL base = buildURL(System.getProperty(PROP_CONFIG_AREA), false);
        if (base == null)
            return;
        logFile = new File(base.getPath(), Long.toString(System.currentTimeMillis()) + ".log"); //$NON-NLS-1$
        logFile.getParentFile().mkdirs();
        System.setProperty(PROP_LOGFILE, logFile.getAbsolutePath());
    }

    /**
     * Converts an ASCII character representing a hexadecimal
     * value into its integer equivalent.
     */
    private int hexToByte(byte b) {
        switch (b) {
            case '0' :
                return 0;
            case '1' :
                return 1;
            case '2' :
                return 2;
            case '3' :
                return 3;
            case '4' :
                return 4;
            case '5' :
                return 5;
            case '6' :
                return 6;
            case '7' :
                return 7;
            case '8' :
                return 8;
            case '9' :
                return 9;
            case 'A' :
            case 'a' :
                return 10;
            case 'B' :
            case 'b' :
                return 11;
            case 'C' :
            case 'c' :
                return 12;
            case 'D' :
            case 'd' :
                return 13;
            case 'E' :
            case 'e' :
                return 14;
            case 'F' :
            case 'f' :
                return 15;
            default :
                throw new IllegalArgumentException("Switch error decoding URL"); //$NON-NLS-1$
        }
    }

    private void openLogFile() throws IOException {
        computeLogFileLocation();
        try {
            log = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(logFile.getAbsolutePath(), true), "UTF-8")); //$NON-NLS-1$
        } catch (IOException e) {
            logFile = null;
            throw e;
        }
    }

    private BufferedWriter logForStream(OutputStream output) {
        try {
            return new BufferedWriter(new OutputStreamWriter(output, "UTF-8")); //$NON-NLS-1$
        } catch (UnsupportedEncodingException e) {
            return new BufferedWriter(new OutputStreamWriter(output));
        }
    }

    private void closeLogFile() throws IOException {
        try {
            if (log != null) {
                log.flush();
                log.close();
            }
        } finally {
            log = null;
        }
    }

    private void mergeProperties(Properties destination, Properties source) {
		if (destination == null || source == null)
			return;
		for (Enumeration e = source.keys(); e.hasMoreElements();) {
			String key = (String) e.nextElement();
			if (key.equals(PROP_CLASSPATH)) {
				String destinationClasspath = destination.getProperty(PROP_CLASSPATH);
				String sourceClasspath = source.getProperty(PROP_CLASSPATH);
				if (destinationClasspath == null)
					destinationClasspath = sourceClasspath;
				else
					destinationClasspath = destinationClasspath + sourceClasspath;
				destination.put(PROP_CLASSPATH, destinationClasspath);
				continue;
			}
			String value = source.getProperty(key);
			if (destination.getProperty(key) == null)
				destination.put(key, value);
		}
	}

    private void setupVMProperties() {
        if (vm != null)
            System.getProperties().put(PROP_VM, vm);
        setMultiValueProperty(PROP_VMARGS, vmargs);
        setMultiValueProperty(PROP_COMMANDS, commands);
    }

    private void setMultiValueProperty(String property, String[] value) {
        if (value != null) {
            StringBuffer result = new StringBuffer(300);
            for (int i = 0; i < value.length; i++) {
                if (value[i] != null) {
                    result.append(value[i]);
                    result.append('\n');
                }
            }
            System.getProperties().put(property, result.toString());
        }
    }

    /*
     * NOTE: It is ok here for EclipsePolicy to use 1.4 methods because the methods
     * that it calls them from don't exist in Foundation so they will never be called. A more
     * detailed explanation from Tom:
     * 
     * They will never get called because in a pre 1.4 VM the methods 
     * getPermissions(CodeSource) and implies(ProtectionDomain, Permission) are 
     * undefined on the Policy class which is what EclipsePolicy extends.  EclipsePolicy 
     * implements these two methods so it can proxy them to the parent Policy.  
     * But since these methods are not actually defined on Policy in a pre-1.4 VM 
     * nobody will actually call them (unless they casted the policy to EclipsePolicy and 
     * called our methods)
     */
    private class EclipsePolicy extends Policy {
        // The policy that this EclipsePolicy is replacing
        private Policy policy;

        // The set of URLs to give AllPermissions to; this is the set of bootURLs
        private URL[] urls;

        // The AllPermissions collection
        private PermissionCollection allPermissions;

        // The AllPermission permission
        private Permission allPermission = new AllPermission();

        EclipsePolicy(Policy policy, URL[] urls) {
            this.policy = policy;
            this.urls = urls;
            allPermissions = new PermissionCollection() {
                private static final long serialVersionUID = 3258131349494708277L;

                // A simple PermissionCollection that only has AllPermission
                public void add(Permission permission) {
                }

                public boolean implies(Permission permission) {
                    return true;
                }

                public Enumeration elements() {
                    return new Enumeration() {
                        int cur = 0;

                        public boolean hasMoreElements() {
                            return cur < 1;
                        }

                        public Object nextElement() {
                            if (cur == 0) {
                                cur = 1;
                                return allPermission;
                            } else
                                throw new NoSuchElementException();
                        }
                    };
                }
            };
        }

        public PermissionCollection getPermissions(CodeSource codesource) {
            if (contains(codesource.getLocation()))
                return allPermissions;
            return policy == null ? allPermissions : policy.getPermissions(codesource);
        }

        public PermissionCollection getPermissions(ProtectionDomain domain) {
            if (contains(domain.getCodeSource().getLocation()))
                return allPermissions;
            return policy == null ? allPermissions : policy.getPermissions(domain);
        }

        public boolean implies(ProtectionDomain domain, Permission permission) {
            if (contains(domain.getCodeSource().getLocation()))
                return true;
            return policy == null ? true : policy.implies(domain, permission);
        }

        public void refresh() {
            if (policy != null)
                policy.refresh();
        }

        private boolean contains(URL url) {
            // Check to see if this URL is in our set of URLs to give AllPermissions to.
            for (int i = 0; i < urls.length; i++) {
                // We do simple equals test here because we assume the URLs will be the same objects.
                if (urls[i] == url)
                    return true;
            }
            return false;
        }
    }

    private class StartupClassLoader extends URLClassLoader {

        public StartupClassLoader(URL[] urls) {
            super(urls);
        }

        public StartupClassLoader(URL[] urls, ClassLoader parent) {
            super(urls, parent);
        }

        public StartupClassLoader(URL[] urls, ClassLoader parent, URLStreamHandlerFactory factory) {
            super(urls, parent, factory);
        }

        protected String findLibrary(String name) {
            if (extensionPaths ==  null)
                return super.findLibrary(name);
            String libName = System.mapLibraryName(name);
            for (int i = 0; i < extensionPaths.length; i++) {
                File libFile = new File(extensionPaths[i], libName);
                if (libFile.isFile())
                    return libFile.getAbsolutePath();
            }
            return super.findLibrary(name);
        }       
    }
}
