jdk/src/share/classes/sun/jkernel/DownloadManager.java
changeset 8197 e45f21c2a40b
parent 7867 f83cd8bd35c6
child 8198 aca2f99e4b52
--- a/jdk/src/share/classes/sun/jkernel/DownloadManager.java	Wed Jul 05 17:32:52 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1786 +0,0 @@
-/*
- * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.  Oracle designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Oracle in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package sun.jkernel;
-
-import java.io.*;
-import java.net.URLStreamHandlerFactory;
-import java.net.URL;
-import java.net.MalformedURLException;
-import java.security.*;
-import java.util.*;
-import java.util.concurrent.*;
-import java.util.jar.*;
-import java.util.zip.*;
-import sun.misc.BootClassLoaderHook;
-import sun.misc.Launcher;
-import sun.misc.URLClassPath;
-import sun.net.www.ParseUtil;
-
-/**
- * Handles the downloading of additional JRE components.  The bootstrap class
- * loader automatically invokes DownloadManager when it comes across a resource
- * that can't be located.
- *
- *@author Ethan Nicholas
- */
-public class DownloadManager extends BootClassLoaderHook {
-    public static final String KERNEL_DOWNLOAD_URL_PROPERTY =
-            "kernel.download.url";
-    public static final String KERNEL_DOWNLOAD_ENABLED_PROPERTY =
-            "kernel.download.enabled";
-
-    public static final String KERNEL_DOWNLOAD_DIALOG_PROPERTY =
-            "kernel.download.dialog";
-
-    public static final String KERNEL_DEBUG_PROPERTY = "kernel.debug";
-    // disables JRE completion when set to true, used as part of the build
-    // process
-    public static final String KERNEL_NOMERGE_PROPERTY = "kernel.nomerge";
-
-    public static final String KERNEL_SIMULTANEOUS_DOWNLOADS_PROPERTY =
-            "kernel.simultaneous.downloads";
-
-    // used to bypass some problems with JAR entry modtimes not matching.
-    // originally was set to zero, but apparently the epochs are different
-    // for zip and pack so the pack/unpack cycle was causing the modtimes
-    // to change.  With some recent changes to the reconstruction, I'm
-    // not sure if this is actually necessary anymore.
-    public static final int KERNEL_STATIC_MODTIME = 10000000;
-
-    // indicates that bundles should be grabbed using getResource(), rather
-    // than downloaded from a network path -- this is used during the build
-    // process
-    public static final String RESOURCE_URL = "internal-resource/";
-    public static final String REQUESTED_BUNDLES_PATH = "lib" + File.separator +
-            "bundles" + File.separator + "requested.list";
-
-    private static final boolean disableDownloadDialog = "false".equals(
-            System.getProperty(KERNEL_DOWNLOAD_DIALOG_PROPERTY));
-
-    static boolean debug = "true".equals(
-            System.getProperty(KERNEL_DEBUG_PROPERTY));
-    // points to stderr in case we need to println before System.err is
-    // initialized
-    private static OutputStream errorStream;
-    private static OutputStream logStream;
-
-    static String MUTEX_PREFIX;
-
-    static boolean complete;
-
-    // 1 if jbroker started; 0 otherwise
-    private static int _isJBrokerStarted = -1;
-
-    // maps bundle names to URL strings
-    private static Properties bundleURLs;
-
-    public static final String JAVA_HOME = System.getProperty("java.home");
-    public static final String USER_HOME = System.getProperty("user.home");
-    public static final String JAVA_VERSION =
-            System.getProperty("java.version");
-    static final int BUFFER_SIZE = 2048;
-
-    static volatile boolean jkernelLibLoaded = false;
-
-    public static String DEFAULT_DOWNLOAD_URL =
-        "http://javadl.sun.com/webapps/download/GetList/"
-        +  System.getProperty("java.runtime.version") + "-kernel/windows-i586/";
-
-    private static final String CUSTOM_PREFIX = "custom";
-    private static final String KERNEL_PATH_SUFFIX = "-kernel";
-
-    public static final String JAR_PATH_PROPERTY = "jarpath";
-    public static final String SIZE_PROPERTY = "size";
-    public static final String DEPENDENCIES_PROPERTY = "dependencies";
-    public static final String INSTALL_PROPERTY = "install";
-
-    private static boolean reportErrors = true;
-
-    static final int ERROR_UNSPECIFIED = 0;
-    static final int ERROR_DISK_FULL   = 1;
-    static final int ERROR_MALFORMED_BUNDLE_PROPERTIES = 2;
-    static final int ERROR_DOWNLOADING_BUNDLE_PROPERTIES = 3;
-    static final int ERROR_MALFORMED_URL = 4;
-    static final int ERROR_RETRY_CANCELLED = 5;
-    static final int ERROR_NO_SUCH_BUNDLE = 6;
-
-
-    // tracks whether the current thread is downloading.  A count of zero means
-    // not currently downloading, >0 means the current thread is downloading or
-    // installing a bundle.
-    static ThreadLocal<Integer> downloading = new ThreadLocal<Integer>() {
-        protected Integer initialValue() {
-            return 0;
-        }
-    };
-
-    private static File[] additionalBootStrapPaths = { };
-
-    private static String[] bundleNames;
-    private static String[] criticalBundleNames;
-
-    private static String downloadURL;
-
-    private static boolean visitorIdDetermined;
-    private static String visitorId;
-
-    /**
-     * File and path where the Check value properties are gotten from
-     */
-    public static String CHECK_VALUES_FILE = "check_value.properties";
-    static String CHECK_VALUES_DIR = "sun/jkernel/";
-    static String CHECK_VALUES_PATH = CHECK_VALUES_DIR + CHECK_VALUES_FILE;
-
-    /**
-     * The contents of the bundle.properties file, which contains various
-     * information about individual bundles.
-     */
-    private static Map<String, Map<String, String>> bundleProperties;
-
-
-    /**
-     * The contents of the resource_map file, which maps resources
-     * to their respective bundles.
-     */
-    private static Map<String, String> resourceMap;
-
-
-    /**
-     * The contents of the file_map file, which maps files
-     * to their respective bundles.
-     */
-    private static Map<String, String> fileMap;
-
-    private static boolean extDirDetermined;
-    private static boolean extDirIncluded;
-
-    static {
-        AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
-                if (debug)
-                    println("DownloadManager startup");
-
-                 // this mutex is global and will apply to all different
-                // version of java kernel installed on the local machine
-                MUTEX_PREFIX = "jkernel";
-                boolean downloadEnabled = !"false".equals(
-                        System.getProperty(KERNEL_DOWNLOAD_ENABLED_PROPERTY));
-                complete = !getBundlePath().exists() ||
-                        !downloadEnabled;
-
-                // only load jkernel.dll if we are not "complete".
-                // DownloadManager will be loaded during build time, before
-                // jkernel.dll is built.  We only need to load jkernel.dll
-                // when DownloadManager needs to download something, which is
-                // not necessary during build time
-                if (!complete) {
-                    loadJKernelLibrary();
-                    log("Log opened");
-
-                    if (isWindowsVista()) {
-                        getLocalLowTempBundlePath().mkdirs();
-                    }
-
-                    new Thread() {
-                        public void run() {
-                            startBackgroundDownloads();
-                        }
-                    }.start();
-
-                    try {
-                        String dummyPath;
-                        if (isWindowsVista()) {
-                            dummyPath = USER_HOME +
-                                    "\\appdata\\locallow\\dummy.kernel";
-                        } else {
-                            dummyPath = USER_HOME + "\\dummy.kernel";
-                        }
-
-                        File f = new File(dummyPath);
-                        FileOutputStream out = new FileOutputStream(f, true);
-                        out.close();
-                        f.deleteOnExit();
-
-                    } catch (IOException e) {
-                        log(e);
-                    }
-                    // end of warm up code
-
-                    new Thread("BundleDownloader") {
-                        public void run() {
-                            downloadRequestedBundles();
-                        }
-                    }.start();
-                }
-                return null;
-            }
-        });
-    }
-
-
-    static synchronized void loadJKernelLibrary() {
-        if (!jkernelLibLoaded) {
-            try {
-                System.loadLibrary("jkernel");
-                jkernelLibLoaded = true;
-                debug = getDebugProperty();
-            } catch (Exception e) {
-                throw new Error(e);
-            }
-        }
-    }
-
-    static String appendTransactionId(String url) {
-        StringBuilder result = new StringBuilder(url);
-        String visitorId = DownloadManager.getVisitorId();
-        if (visitorId != null) {
-            if (url.indexOf("?") == -1)
-                result.append('?');
-            else
-                result.append('&');
-            result.append("transactionId=");
-            result.append(DownloadManager.getVisitorId());
-        }
-        return result.toString();
-    }
-
-
-    /**
-     * Returns the URL for the directory from which bundles should be
-     * downloaded.
-     */
-    static synchronized String getBaseDownloadURL() {
-        if (downloadURL == null) {
-            log("Determining download URL...");
-            loadJKernelLibrary();
-
-            /*
-             * First check if system property has been set - system
-             * property should take over registry key setting.
-             */
-            downloadURL = System.getProperty(
-                          DownloadManager.KERNEL_DOWNLOAD_URL_PROPERTY);
-            log("System property kernel.download.url = " + downloadURL);
-
-            /*
-             * Now check if registry key has been set
-             */
-            if (downloadURL == null){
-                downloadURL = getUrlFromRegistry();
-                log("getUrlFromRegistry = " + downloadURL);
-            }
-
-            /*
-             * Use default download url
-             */
-            if (downloadURL == null)
-                downloadURL = DEFAULT_DOWNLOAD_URL;
-            log("Final download URL: " + downloadURL);
-        }
-        return downloadURL;
-    }
-
-
-    /**
-     * Loads a file representing a node tree.  The format is described in
-     * SplitJRE.writeTreeMap().  The node paths (such as
-     * core/java/lang/Object.class) are interpreted with the root node as the
-     * value and the remaining nodes as
-     * the key, so the mapping for this entry would be java/lang/Object.class =
-     * core.
-     */
-    static Map<String, String> readTreeMap(InputStream rawIn)
-            throws IOException {
-        // "token level" refers to the 0-31 byte that occurs prior to every
-        // token in the stream, and would be e.g. <0> core <1> java <2> lang
-        // <3> Object.class <3> String.class, which gives us two mappings:
-        // java/lang/Object.class = core, and java/lang/String.class = core.
-        // See the format description in SplitJRE.writeTreeMap for more details.
-        Map<String, String> result = new HashMap<String, String>();
-        InputStream in = new BufferedInputStream(rawIn);
-        // holds the current token sequence,
-        // e.g. {"core", "java", "lang", "Object.class"}
-        List<String> tokens = new ArrayList<String>();
-        StringBuilder currentToken = new StringBuilder();
-        for (;;) {
-            int c = in.read();
-            if (c  == -1) // eof
-                break;
-            if (c < 32) { // new token level
-                if (tokens.size() > 0) {
-                    // replace the null at the end of the list with the token
-                    // we just finished reading
-                    tokens.set(tokens.size() - 1, currentToken.toString());
-                }
-
-                currentToken.setLength(0);
-
-                if (c > tokens.size()) {
-                    // can't increase by more than one token level at a step
-                    throw new InternalError("current token level is " +
-                            (tokens.size() - 1) + " but encountered token " +
-                            "level " + c);
-                }
-                else if (c == tokens.size()) {
-                    // token level increased by 1; this means we are still
-                    // adding tokens for the current mapping -- e.g. we have
-                    // read "core", "java", "lang" and are just about to read
-                    // "Object.class"
-                    // add a placeholder for the new token
-                    tokens.add(null);
-                }
-                else {
-                    // we just stayed at the same level or backed up one or more
-                    // token levels; this means that the current sequence is
-                    // complete and needs to be added to the result map
-                    StringBuilder key = new StringBuilder();
-                    // combine all tokens except the first into a single string
-                    for (int i = 1; i < tokens.size(); i++) {
-                        if (i > 1)
-                            key.append('/');
-                        key.append(tokens.get(i));
-                    }
-                    // map the combined string to the first token, e.g.
-                    // java/lang/Object.class = core
-                    result.put(key.toString(), tokens.get(0));
-                    // strip off tokens until we get back to the current token
-                    // level
-                    while (c < tokens.size())
-                        tokens.remove(c);
-                    // placeholder for upcoming token
-                    tokens.add(null);
-                }
-            }
-            else if (c < 254) // character
-                currentToken.append((char) c);
-            else if (c == 255)
-                currentToken.append(".class");
-            else { // out-of-band value
-                throw new InternalError("internal error processing " +
-                        "resource_map (can't-happen error)");
-            }
-        }
-        if (tokens.size() > 0) // add token we just finished reading
-            tokens.set(tokens.size() - 1, currentToken.toString());
-        StringBuilder key = new StringBuilder();
-        // add the last entry to the map
-        for (int i = 1; i < tokens.size(); i++) {
-            if (i > 1)
-                key.append('/');
-            key.append(tokens.get(i));
-        }
-        if (!tokens.isEmpty())
-            result.put(key.toString(), tokens.get(0));
-        in.close();
-        return Collections.unmodifiableMap(result);
-    }
-
-
-    /**
-     * Returns the contents of the resource_map file, which maps
-     * resources names to their respective bundles.
-     */
-    public static Map<String, String> getResourceMap() throws IOException {
-        if (resourceMap == null) {
-            InputStream in = DownloadManager.class.getResourceAsStream("resource_map");
-            if (in != null) {
-                in = new BufferedInputStream(in);
-                try {
-                    resourceMap = readTreeMap(in);
-                    in.close();
-                }
-                catch (IOException e) {
-                    // turns out we can be returned a broken stream instead of
-                    // just null
-                    resourceMap = new HashMap<String, String>();
-                    complete = true;
-                    log("Can't find resource_map, forcing complete to true");
-                }
-                in.close();
-            }
-            else {
-                resourceMap = new HashMap<String, String>();
-                complete = true;
-                log("Can't find resource_map, forcing complete to true");
-            }
-
-            for (int i = 1; ; i++) { // run through the numbered custom bundles
-                String name = CUSTOM_PREFIX + i;
-                File customPath = new File(getBundlePath(), name + ".jar");
-                if (customPath.exists()) {
-                    JarFile custom = new JarFile(customPath);
-                    Enumeration entries = custom.entries();
-                    while (entries.hasMoreElements()) {
-                        JarEntry entry = (JarEntry) entries.nextElement();
-                        if (!entry.isDirectory())
-                            resourceMap.put(entry.getName(), name);
-                    }
-                }
-                else
-                    break;
-            }
-        }
-        return resourceMap;
-    }
-
-
-    /**
-     * Returns the contents of the file_map file, which maps
-     * file names to their respective bundles.
-     */
-    public static Map<String, String> getFileMap() throws IOException {
-        if (fileMap == null) {
-            InputStream in = DownloadManager.class.getResourceAsStream("file_map");
-            if (in != null) {
-                in = new BufferedInputStream(in);
-                try {
-                    fileMap = readTreeMap(in);
-                    in.close();
-                }
-                catch (IOException e) {
-                    // turns out we can be returned a broken stream instead of
-                    // just null
-                    fileMap = new HashMap<String, String>();
-                    complete = true;
-                    log("Can't find file_map, forcing complete to true");
-                }
-                in.close();
-            }
-            else {
-                fileMap = new HashMap<String, String>();
-                complete = true;
-                log("Can't find file_map, forcing complete to true");
-            }
-        }
-        return fileMap;
-    }
-
-
-    /**
-     * Returns the contents of the bundle.properties file, which maps
-     * bundle names to a pipe-separated list of their properties.  Properties
-     * include:
-     * jarpath - By default, the JAR files (unpacked from classes.pack in the
-     *           bundle) are stored under lib/bundles.  The jarpath property
-     *           overrides this default setting, causing the JAR to be unpacked
-     *           at the specified location.  This is used to preserve the
-     *           identity of JRE JAR files such as lib/deploy.jar.
-     * size    - The size of the download in bytes.
-     */
-    private static synchronized Map<String, Map<String, String>> getBundleProperties()
-            throws IOException {
-        if (bundleProperties == null) {
-            InputStream in = DownloadManager.class.getResourceAsStream("bundle.properties");
-            if (in == null) {
-                complete = true;
-                log("Can't find bundle.properties, forcing complete to true");
-                return null;
-            }
-            in = new BufferedInputStream(in);
-            Properties tmp = new Properties();
-            tmp.load(in);
-            bundleProperties = new HashMap<String, Map<String, String>>();
-            for (Map.Entry e : tmp.entrySet()) {
-                String key = (String) e.getKey();
-                String[] properties = ((String) e.getValue()).split("\\|");
-                Map<String, String> map = new HashMap<String, String>();
-                for (String entry : properties) {
-                    int equals = entry.indexOf("=");
-                    if (equals == -1)
-                        throw new InternalError("error parsing bundle.properties: " +
-                            entry);
-                    map.put(entry.substring(0, equals).trim(),
-                        entry.substring(equals + 1).trim());
-                }
-                bundleProperties.put(key, map);
-            }
-            in.close();
-        }
-        return bundleProperties;
-    }
-
-
-    /**
-     * Returns a single bundle property value loaded from the bundle.properties
-     * file.
-     */
-    static String getBundleProperty(String bundleName, String property) {
-        try {
-            Map<String, Map<String, String>> props = getBundleProperties();
-            Map/*<String, String>*/ map = props != null ? props.get(bundleName) : null;
-            return map != null ? (String) map.get(property) : null;
-        }
-        catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    /** Returns an array of all supported bundle names. */
-    static String[] getBundleNames() throws IOException {
-        if (bundleNames == null) {
-            Set<String> result = new HashSet<String>();
-            Map<String, String> resourceMap = getResourceMap();
-            if (resourceMap != null)
-                result.addAll(resourceMap.values());
-            Map<String, String> fileMap = getFileMap();
-            if (fileMap != null)
-                result.addAll(fileMap.values());
-            bundleNames = result.toArray(new String[result.size()]);
-        }
-        return bundleNames;
-    }
-
-
-    /**
-     * Returns an array of all "critical" (must be downloaded prior to
-     * completion) bundle names.
-     */
-    private static String[] getCriticalBundleNames() throws IOException {
-        if (criticalBundleNames == null) {
-            Set<String> result = new HashSet<String>();
-            Map<String, String> fileMap = getFileMap();
-            if (fileMap != null)
-                result.addAll(fileMap.values());
-            criticalBundleNames = result.toArray(new String[result.size()]);
-        }
-        return criticalBundleNames;
-    }
-
-
-    public static void send(InputStream in, OutputStream out)
-            throws IOException {
-        byte[] buffer = new byte[BUFFER_SIZE];
-        int c;
-        while ((c = in.read(buffer)) > 0)
-            out.write(buffer, 0, c);
-    }
-
-
-    /**
-     * Determine whether all bundles have been downloaded, and if so create
-     * the merged jars that will eventually replace rt.jar and resoures.jar.
-     * IMPORTANT: this method should only be called from the background
-     * download process.
-     */
-    static void performCompletionIfNeeded() {
-        if (debug)
-            log("DownloadManager.performCompletionIfNeeded: checking (" +
-                    complete + ", " + System.getProperty(KERNEL_NOMERGE_PROPERTY)
-                    + ")");
-        if (complete ||
-                "true".equals(System.getProperty(KERNEL_NOMERGE_PROPERTY)))
-            return;
-        Bundle.loadReceipts();
-        try {
-            if (debug) {
-                List critical = new ArrayList(Arrays.asList(getCriticalBundleNames()));
-                critical.removeAll(Bundle.receipts);
-                log("DownloadManager.performCompletionIfNeeded: still need " +
-                        critical.size() + " bundles (" + critical + ")");
-            }
-            if (Bundle.receipts.containsAll(Arrays.asList(getCriticalBundleNames()))) {
-                log("DownloadManager.performCompletionIfNeeded: running");
-                // all done!
-                new Thread("JarMerger") {
-                    public void run() {
-                        createMergedJars();
-                    }
-                }.start();
-            }
-        }
-        catch (IOException e) {
-            throw new RuntimeException(e);
-        }
-    }
-
-
-    /**
-     * Returns the bundle corresponding to a given resource path (e.g.
-     * "java/lang/Object.class").  If the resource does not appear in a bundle,
-     * null is returned.
-     */
-    public static Bundle getBundleForResource(String resource)
-            throws IOException {
-        String bundleName = getResourceMap().get(resource);
-        return bundleName != null ? Bundle.getBundle(bundleName) : null;
-    }
-
-
-    /**
-     * Returns the bundle corresponding to a given JRE file path (e.g.
-     * "bin/awt.dll").  If the file does not appear in a bundle, null is
-     * returned.
-     */
-    private static Bundle getBundleForFile(String file) throws IOException {
-        String bundleName = getFileMap().get(file);
-        return bundleName != null ? Bundle.getBundle(bundleName) : null;
-    }
-
-
-    /**
-     * Returns the path to the lib/bundles directory.
-     */
-    static File getBundlePath() {
-        return new File(JAVA_HOME, "lib" + File.separatorChar + "bundles");
-    }
-
-    private static String getAppDataLocalLow() {
-        return USER_HOME + "\\appdata\\locallow\\";
-    }
-
-    public static String getKernelJREDir() {
-        return "kerneljre" + JAVA_VERSION;
-    }
-
-    static File getLocalLowTempBundlePath() {
-        return new File(getLocalLowKernelJava() + "-bundles");
-    }
-
-    static String getLocalLowKernelJava() {
-        return getAppDataLocalLow() + getKernelJREDir();
-    }
-
-    // To be revisited:
-    // How DownloadManager maintains its bootstrap class path.
-    // sun.misc.Launcher.getBootstrapClassPath() returns
-    // DownloadManager.getBootstrapClassPath() instead.
-    //
-    // So should no longer need to lock the Launcher.class.
-    // In addition, additionalBootStrapPaths is not really needed
-    // if it obtains the initial bootclasspath during DownloadManager's
-    // initialization.
-    private static void addEntryToBootClassPath(File path) {
-        // Must acquire these locks in this order
-        synchronized(Launcher.class) {
-            synchronized(DownloadManager.class) {
-                File[] newBootStrapPaths = new File[
-                    additionalBootStrapPaths.length + 1];
-                System.arraycopy(additionalBootStrapPaths, 0, newBootStrapPaths,
-                        0, additionalBootStrapPaths.length);
-                newBootStrapPaths[newBootStrapPaths.length - 1] = path;
-                additionalBootStrapPaths = newBootStrapPaths;
-                if (bootstrapClassPath != null)
-                    bootstrapClassPath.addURL(getFileURL(path));
-           }
-       }
-    }
-
-    /**
-     * Returns the kernel's bootstrap class path which includes the additional
-     * JARs downloaded
-     */
-    private static URLClassPath bootstrapClassPath = null;
-    private synchronized static
-           URLClassPath getBootClassPath(URLClassPath bcp,
-                                         URLStreamHandlerFactory factory)
-    {
-        if (bootstrapClassPath == null) {
-            bootstrapClassPath = new URLClassPath(bcp.getURLs(), factory);
-            for (File path : additionalBootStrapPaths) {
-                bootstrapClassPath.addURL(getFileURL(path));
-            }
-        }
-        return bootstrapClassPath;
-    }
-
-    private static URL getFileURL(File file) {
-        try {
-            file = file.getCanonicalFile();
-        } catch (IOException e) {}
-
-        try {
-            return ParseUtil.fileToEncodedURL(file);
-        } catch (MalformedURLException e) {
-            // Should never happen since we specify the protocol...
-            throw new InternalError();
-        }
-    }
-
-    /**
-     * Scan through java.ext.dirs to see if the lib/ext directory is included.
-     * If not, we shouldn't be "finding" lib/ext jars for download.
-     */
-    private static synchronized boolean extDirIsIncluded() {
-        if (!extDirDetermined) {
-            extDirDetermined = true;
-            String raw = System.getProperty("java.ext.dirs");
-            String ext = JAVA_HOME + File.separator + "lib" + File.separator + "ext";
-            int index = 0;
-            while (index < raw.length()) {
-                int newIndex = raw.indexOf(File.pathSeparator, index);
-                if (newIndex == -1)
-                    newIndex = raw.length();
-                String path = raw.substring(index, newIndex);
-                if (path.equals(ext)) {
-                    extDirIncluded = true;
-                    break;
-                }
-                index = newIndex + 1;
-            }
-        }
-        return extDirIncluded;
-    }
-
-
-    private static String doGetBootClassPathEntryForResource(
-            String resourceName) {
-        boolean retry = false;
-        do {
-            Bundle bundle = null;
-            try {
-                bundle = getBundleForResource(resourceName);
-                if (bundle != null) {
-                    File path = bundle.getJarPath();
-                    boolean isExt = path.getParentFile().getName().equals("ext");
-                    if (isExt && !extDirIsIncluded()) // this is a lib/ext jar, but
-                        return null;                  // lib/ext isn't in the path
-                    if (getBundleProperty(bundle.getName(), JAR_PATH_PROPERTY) == null) {
-                        // if the bundle doesn't have its own JAR path, that means it's
-                        // going to be merged into rt.jar.  If we already have the
-                        // merged rt.jar, we can simply point to that.
-                        Bundle merged = Bundle.getBundle("merged");
-                        if (merged != null && merged.isInstalled()) {
-                            File jar;
-                            if (resourceName.endsWith(".class"))
-                                jar = merged.getJarPath();
-                            else
-                                jar = new File(merged.getJarPath().getPath().replaceAll("merged-rt.jar",
-                                        "merged-resources.jar"));
-                            addEntryToBootClassPath(jar);
-                            return jar.getPath();
-                        }
-                    }
-                    if (!bundle.isInstalled()) {
-                        bundle.queueDependencies(true);
-                        log("On-demand downloading " +
-                                bundle.getName() + " for resource " +
-                                resourceName + "...");
-                        bundle.install();
-                        log(bundle + " install finished.");
-                    }
-                    log("Double-checking " + bundle + " state...");
-                    if (!bundle.isInstalled()) {
-                        throw new IllegalStateException("Expected state of " +
-                                bundle + " to be INSTALLED");
-                    }
-                    if (isExt) {
-                        // don't add lib/ext entries to the boot class path, add
-                        // them to the extension classloader instead
-                        Launcher.addURLToExtClassLoader(path.toURL());
-                        return null;
-                    }
-
-                    if ("javaws".equals(bundle.getName())) {
-                        Launcher.addURLToAppClassLoader(path.toURL());
-                        log("Returning null for javaws");
-                        return null;
-                    }
-
-                    if ("core".equals(bundle.getName()))
-                        return null;
-
-                    // else add to boot class path
-                    addEntryToBootClassPath(path);
-
-                    return path.getPath();
-                }
-                return null; // not one of the JRE's classes
-            }
-            catch (Throwable e) {
-                retry = handleException(e);
-                log("Error downloading bundle for " +
-                        resourceName + ":");
-                log(e);
-                if (e instanceof IOException) {
-                    // bundle did not get installed correctly, remove incomplete
-                    // bundle files
-                    if (bundle != null) {
-                        if (bundle.getJarPath() != null) {
-                            File packTmp = new File(bundle.getJarPath() + ".pack");
-                            packTmp.delete();
-                            bundle.getJarPath().delete();
-                        }
-                        if (bundle.getLocalPath() != null) {
-                            bundle.getLocalPath().delete();
-                        }
-                        bundle.setState(Bundle.NOT_DOWNLOADED);
-                    }
-                }
-            }
-        } while (retry);
-        sendErrorPing(ERROR_RETRY_CANCELLED); // bundle failed to install, user cancelled
-
-        return null; // failed, user chose not to retry
-    }
-
-    static synchronized void sendErrorPing(int code) {
-        try {
-            File bundlePath;
-            if (isWindowsVista()) {
-                bundlePath = getLocalLowTempBundlePath();
-            } else {
-                bundlePath = getBundlePath();
-            }
-            File tmp = new File(bundlePath, "tmp");
-            File errors = new File(tmp, "errors");
-            String errorString = String.valueOf(code);
-            if (errors.exists()) {
-                BufferedReader in = new BufferedReader(new FileReader(errors));
-                String line = in.readLine();
-                while (line != null) {
-                    if (line.equals(errorString))
-                        return; // we have already pinged this error
-                    line = in.readLine();
-                }
-            }
-            tmp.mkdirs();
-            Writer out = new FileWriter(errors, true);
-            out.write(errorString + System.getProperty("line.separator"));
-            out.close();
-            postDownloadError(code);
-        }
-        catch (IOException e) {
-            e.printStackTrace();
-        }
-    }
-
-
-
-    /**
-     * Displays an error dialog and prompts the user to retry or cancel.
-     * Returns true if the user chose to retry, false if he chose to cancel.
-     */
-    static boolean handleException(Throwable e) {
-        if (e instanceof IOException) {
-            // I don't know of a better method to determine the root cause of
-            // the exception, unfortunately...
-            int code = ERROR_UNSPECIFIED;
-            if (e.getMessage().indexOf("not enough space") != -1)
-                code = ERROR_DISK_FULL;
-            return askUserToRetryDownloadOrQuit(code);
-        }
-        else
-            return false;
-    }
-
-
-    static synchronized void flushBundleURLs() {
-        bundleURLs = null;
-    }
-
-
-    static synchronized Properties getBundleURLs(boolean showUI)
-            throws IOException {
-        if (bundleURLs == null) {
-            log("Entering DownloadManager.getBundleURLs");
-            String base = getBaseDownloadURL();
-            String url = appendTransactionId(base);
-            // use PID instead of createTempFile or other random filename so as
-            // to avoid dependencies on the random number generator libraries
-            File bundlePath = null;
-            // write temp file to locallow directory on vista
-            if (isWindowsVista()) {
-                bundlePath = getLocalLowTempBundlePath();
-            } else {
-                bundlePath = getBundlePath();
-            }
-            File tmp = new File(bundlePath, "urls." + getCurrentProcessId() +
-                    ".properties");
-            try {
-                log("Downloading from " + url + " to " + tmp);
-                downloadFromURL(url, tmp, "", showUI);
-                bundleURLs = new Properties();
-                if (tmp.exists()) {
-                    addToTotalDownloadSize((int) tmp.length()); // better late than never
-                    InputStream in = new FileInputStream(tmp);
-                    in = new BufferedInputStream(in);
-                    bundleURLs.load(in);
-                    in.close();
-                    if (bundleURLs.isEmpty()) {
-                        fatalError(ERROR_MALFORMED_BUNDLE_PROPERTIES);
-                    }
-                } else {
-                    fatalError(ERROR_DOWNLOADING_BUNDLE_PROPERTIES);
-                }
-            } finally {
-                // delete the temp file
-                if (!debug)
-                    tmp.delete();
-            }
-            log("Leaving DownloadManager.getBundleURLs");
-            // else an error occurred and user chose not to retry; leave
-            // bundleURLs empty so we don't continually try to re-download it
-        }
-        return bundleURLs;
-    }
-
-    /**
-     * Checks to see if the specified resource is part of a bundle, and if so
-     * downloads it.  Returns either a string which should be added to the boot
-     * class path (the newly-downloaded JAR's location), or null to indicate
-     * that it isn't one of the JRE's resources or could not be downloaded.
-     */
-    public static String getBootClassPathEntryForResource(
-            final String resourceName) {
-        if (debug)
-            log("Entering getBootClassPathEntryForResource(" + resourceName + ")");
-        if (isJREComplete() || downloading == null ||
-                resourceName.startsWith("sun/jkernel")) {
-            if (debug)
-                log("Bailing: " + isJREComplete() + ", " + (downloading == null));
-            return null;
-        }
-        incrementDownloadCount();
-        try {
-            String result = (String) AccessController.doPrivileged(
-                new PrivilegedAction() {
-                    public Object run() {
-                        return (String) doGetBootClassPathEntryForResource(
-                                resourceName);
-                    }
-                }
-            );
-            log("getBootClassPathEntryForResource(" + resourceName + ") == " + result);
-            return result;
-        }
-        finally {
-            decrementDownloadCount();
-        }
-    }
-
-
-    /**
-     * Called by the boot class loader when it encounters a class it can't find.
-     * This method will check to see if the class is part of a bundle, and if so
-     * download it.  Returns either a string which should be added to the boot
-     * class path (the newly-downloaded JAR's location), or null to indicate
-     * that it isn't one of the JRE's classes or could not be downloaded.
-     */
-    public static String getBootClassPathEntryForClass(final String className) {
-        return getBootClassPathEntryForResource(className.replace('.', '/') +
-                ".class");
-    }
-
-
-    private static boolean doDownloadFile(String relativePath)
-            throws IOException {
-        Bundle bundle = getBundleForFile(relativePath);
-        if (bundle != null) {
-            bundle.queueDependencies(true);
-            log("On-demand downloading " + bundle.getName() +
-                    " for file " + relativePath + "...");
-            bundle.install();
-            return true;
-        }
-        return false;
-    }
-
-
-    /**
-     * Locates the bundle for the specified JRE file (e.g. "bin/awt.dll") and
-     * installs it.  Returns true if the file is indeed part of the JRE and has
-     * now been installed, false if the file is not part of the JRE, and throws
-     * an IOException if the file is part of the JRE but could not be
-     * downloaded.
-     */
-    public static boolean downloadFile(final String relativePath)
-            throws IOException {
-        if (isJREComplete() || downloading == null)
-            return false;
-
-        incrementDownloadCount();
-        try {
-            Object result =
-                    AccessController.doPrivileged(new PrivilegedAction() {
-                public Object run() {
-                    File path = new File(JAVA_HOME,
-                            relativePath.replace('/', File.separatorChar));
-                    if (path.exists())
-                        return true;
-                    try {
-                        return new Boolean(doDownloadFile(relativePath));
-                    }
-                    catch (IOException e) {
-                        return e;
-                    }
-                }
-            });
-            if (result instanceof Boolean)
-                return ((Boolean) result).booleanValue();
-            else
-                throw (IOException) result;
-        }
-        finally {
-            decrementDownloadCount();
-        }
-    }
-
-
-    // increments the counter that tracks whether the current thread is involved
-    // in any download-related activities.  A non-zero count indicates that the
-    // thread is currently downloading or installing a bundle.
-    static void incrementDownloadCount() {
-        downloading.set(downloading.get() + 1);
-    }
-
-
-    // increments the counter that tracks whether the current thread is involved
-    // in any download-related activities.  A non-zero count indicates that the
-    // thread is currently downloading or installing a bundle.
-    static void decrementDownloadCount() {
-        // will generate an exception if incrementDownloadCount() hasn't been
-        // called first, this is intentional
-        downloading.set(downloading.get() - 1);
-    }
-
-
-    /**
-     * Returns <code>true</code> if the current thread is in the process of
-     * downloading a bundle.  This is called by DownloadManager.loadLibrary()
-     * that is called by System.loadLibrary(), so
-     * that when we run into a library required by the download process itself,
-     * we don't call back into DownloadManager in an attempt to download it
-     * (which would lead to infinite recursion).
-     *
-     * All classes and libraries required to download classes must by
-     * definition already be present.  So if this method returns true, we are
-     * currently in the middle of performing a download, and the class or
-     * library load must be happening due to the download itself.  We can
-     * immediately abort such requests -- the class or library should already
-     * be present.  If it isn't, we're not going to be able to download it,
-     * since we have just established that it is required to perform a
-     * download, and we might as well just let the NoClassDefFoundError /
-     * UnsatisfiedLinkError occur.
-     */
-    public static boolean isCurrentThreadDownloading() {
-        return downloading != null ? downloading.get() > 0 : false;
-    }
-
-
-    /**
-     * Returns true if everything is downloaded and the JRE has been
-     * reconstructed.  Also returns true if kernel functionality is disabled
-     * for any other reason.
-     */
-    public static boolean isJREComplete() {
-        return complete;
-    }
-
-
-    // called by BackgroundDownloader
-    static void doBackgroundDownloads(boolean showProgress) {
-        if (!complete) {
-            if (!showProgress && !debug)
-                reportErrors = false;
-            try {
-                // install swing first for ergonomic reasons
-                Bundle swing = Bundle.getBundle("javax_swing_core");
-                if (!swing.isInstalled())
-                    swing.install(showProgress, false, false);
-                // install remaining bundles
-                for (String name : getCriticalBundleNames()) {
-                    Bundle bundle = Bundle.getBundle(name);
-                    if (!bundle.isInstalled()) {
-                        bundle.install(showProgress, false, true);
-                    }
-                }
-                shutdown();
-            }
-            catch (IOException e) {
-                log(e);
-            }
-        }
-    }
-
-    // copy receipt file to destination path specified
-    static void copyReceiptFile(File from, File to) throws IOException {
-        DataInputStream in = new DataInputStream(
-                new BufferedInputStream(new FileInputStream(from)));
-        OutputStream out = new FileOutputStream(to);
-        String line = in.readLine();
-        while (line != null) {
-            out.write((line + '\n').getBytes("utf-8"));
-            line = in.readLine();
-        }
-        in.close();
-        out.close();
-    }
-
-
-    private static void downloadRequestedBundles() {
-        log("Checking for requested bundles...");
-        try {
-            File list = new File(JAVA_HOME, REQUESTED_BUNDLES_PATH);
-            if (list.exists()) {
-                FileInputStream in = new FileInputStream(list);
-                ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-                send(in, buffer);
-                in.close();
-
-                // split string manually to avoid relying on regexes or
-                // StringTokenizer
-                String raw = new String(buffer.toByteArray(), "utf-8");
-                List/*<String>*/ bundles = new ArrayList/*<String>*/();
-                StringBuilder token = new StringBuilder();
-                for (int i = 0; i < raw.length(); i++) {
-                    char c = raw.charAt(i);
-                    if (c == ',' || Character.isWhitespace(c)) {
-                        if (token.length() > 0) {
-                            bundles.add(token.toString());
-                            token.setLength(0);
-                        }
-                    }
-                    else
-                        token.append(c);
-                }
-                if (token.length() > 0)
-                    bundles.add(token.toString());
-                log("Requested bundles: " + bundles);
-                for (int i = 0; i < bundles.size(); i++) {
-                    Bundle bundle = Bundle.getBundle((String) bundles.get(i));
-                    if (bundle != null && !bundle.isInstalled()) {
-                        log("Downloading " + bundle + " due to requested.list");
-                        bundle.install(true, false, false);
-                    }
-                }
-            }
-        }
-        catch (IOException e) {
-            log(e);
-        }
-    }
-
-
-    static void fatalError(int code) {
-        fatalError(code, null);
-    }
-
-
-    /**
-     * Called to cleanly shut down the VM when a fatal download error has
-     * occurred.  Calls System.exit() if outside of the Java Plug-In, otherwise
-     * throws an error.
-     */
-    static void fatalError(int code, String arg) {
-        sendErrorPing(code);
-
-        for (int i = 0; i < Bundle.THREADS; i++)
-            bundleInstallComplete();
-        if (reportErrors)
-            displayError(code, arg);
-        // inPlugIn check isn't 100% reliable but should be close enough.
-        // headless is for the browser side of things in the out-of-process
-        // plug-in
-        boolean inPlugIn = (Boolean.getBoolean("java.awt.headless") ||
-           System.getProperty("javaplugin.version") != null);
-        KernelError error = new KernelError("Java Kernel bundle download failed");
-        if (inPlugIn)
-            throw error;
-        else {
-            log(error);
-            System.exit(1);
-        }
-    }
-
-
-    // start the background download process using the jbroker broker process
-    // the method will first launch the broker process, if it is not already
-    // running
-    // it will then send the command necessary to start the background download
-    // process to the broker process
-    private static void startBackgroundDownloadWithBroker() {
-
-        if (!BackgroundDownloader.getBackgroundDownloadProperty()) {
-            // If getBackgroundDownloadProperty() returns false
-            // we're doing the downloads from this VM; we don't want to
-            // spawn another one
-            return;
-        }
-
-        // launch broker process if necessary
-        if (!launchBrokerProcess()) {
-            return;
-        }
-
-
-        String kernelDownloadURLProperty = getBaseDownloadURL();
-
-        String kernelDownloadURL;
-
-        // only set KERNEL_DOWNLOAD_URL_PROPERTY if we override
-        // the default download url
-        if (kernelDownloadURLProperty == null ||
-                kernelDownloadURLProperty.equals(DEFAULT_DOWNLOAD_URL)) {
-            kernelDownloadURL = " ";
-        } else {
-            kernelDownloadURL = kernelDownloadURLProperty;
-        }
-
-        startBackgroundDownloadWithBrokerImpl(kernelDownloadURLProperty);
-    }
-
-    private static void startBackgroundDownloads() {
-        if (!complete) {
-            if (BackgroundDownloader.getBackgroundMutex().acquire(0)) {
-                // we don't actually need to hold the mutex -- it was just a
-                // quick check to see if there is any point in even attempting
-                // to start the background downloader
-                BackgroundDownloader.getBackgroundMutex().release();
-                if (isWindowsVista()) {
-                    // use broker process to start background download
-                    // at high integrity
-                    startBackgroundDownloadWithBroker();
-                } else {
-                    BackgroundDownloader.startBackgroundDownloads();
-                }
-            }
-        }
-    }
-
-
-    /**
-     * Increases the total download size displayed in the download progress
-     * dialog.
-     */
-    static native void addToTotalDownloadSize(int size);
-
-
-    /**
-     * Displays a progress dialog while downloading from the specified URL.
-     *
-     *@param url the URL string from which to download
-     *@param file the destination path
-     *@param name the user-visible name of the component we are downloading
-     */
-    static void downloadFromURL(String url, File file, String name,
-            boolean showProgress) {
-        // do not show download dialog if kernel.download.dialog is false
-        downloadFromURLImpl(url, file, name,
-                disableDownloadDialog ? false : showProgress);
-    }
-
-    private static native void downloadFromURLImpl(String url, File file,
-            String name, boolean showProgress);
-
-    // This is for testing purposes only - allows to specify URL
-    // to download kernel bundles from through the registry key.
-    static native String getUrlFromRegistry();
-
-    static native String getVisitorId0();
-
-    static native void postDownloadComplete();
-
-    static native void postDownloadError(int code);
-
-    // Returns the visitor ID set by the installer, will be sent to the server
-    // during bundle downloads for logging purposes.
-    static synchronized String getVisitorId() {
-        if (!visitorIdDetermined) {
-            visitorIdDetermined = true;
-            visitorId = getVisitorId0();
-        }
-        return visitorId;
-    }
-
-    // display an error message using a native dialog
-    public static native void displayError(int code, String arg);
-
-    // prompt user whether to retry download, or quit
-    // returns true if the user chose to retry
-    public static native boolean askUserToRetryDownloadOrQuit(int code);
-
-    // returns true if we are running Windows Vista; false otherwise
-    static native boolean isWindowsVista();
-
-    private static native void startBackgroundDownloadWithBrokerImpl(
-            String command);
-
-    private static int isJBrokerStarted() {
-        if (_isJBrokerStarted == -1) {
-            // initialize state of jbroker
-            _isJBrokerStarted = isJBrokerRunning() ? 1 : 0;
-        }
-        return _isJBrokerStarted;
-    }
-
-    // returns true if broker process (jbroker) is running; false otherwise
-    private static native boolean isJBrokerRunning();
-
-    // returns true if we are running in IE protected mode; false otherwise
-    private static native boolean isIEProtectedMode();
-
-    private static native boolean launchJBroker(String jbrokerPath);
-
-    static native void bundleInstallStart();
-
-    static native void bundleInstallComplete();
-
-    private static native boolean moveFileWithBrokerImpl(String fromPath,
-            String userHome);
-
-    private static native boolean moveDirWithBrokerImpl(String fromPath,
-            String userHome);
-
-    static boolean moveFileWithBroker(String fromPath) {
-        // launch jbroker if necessary
-        if (!launchBrokerProcess()) {
-            return false;
-        }
-
-        return moveFileWithBrokerImpl(fromPath, USER_HOME);
-    }
-
-    static boolean moveDirWithBroker(String fromPath) {
-        // launch jbroker if necessary
-        if (!launchBrokerProcess()) {
-            return false;
-        }
-
-        return moveDirWithBrokerImpl(fromPath, USER_HOME);
-    }
-
-    private static synchronized boolean launchBrokerProcess() {
-        // launch jbroker if necessary
-        if (isJBrokerStarted() == 0) {
-            // launch jbroker if needed
-            boolean ret = launchJBroker(JAVA_HOME);
-            // set state of jbroker
-            _isJBrokerStarted = ret ? 1 : 0;
-            return ret;
-        }
-        return true;
-    }
-
-    private static class StreamMonitor implements Runnable {
-        private InputStream istream;
-        public StreamMonitor(InputStream stream) {
-            istream = new BufferedInputStream(stream);
-            new Thread(this).start();
-        }
-        public void run() {
-            byte[] buffer = new byte[4096];
-            try {
-                int ret = istream.read(buffer);
-                while (ret != -1) {
-                    ret = istream.read(buffer);
-                }
-            } catch (IOException e) {
-                try {
-                    istream.close();
-                } catch (IOException e2) {
-                } // Should allow clean exit when process shuts down
-            }
-        }
-    }
-
-
-    /** Copy a file tree, excluding certain named files. */
-    private static void copyAll(File src, File dest, Set/*<String>*/ excludes)
-                            throws IOException {
-        if (!excludes.contains(src.getName())) {
-            if (src.isDirectory()) {
-                File[] children = src.listFiles();
-                if (children != null) {
-                    for (int i = 0; i < children.length; i++)
-                        copyAll(children[i],
-                                new File(dest, children[i].getName()),
-                                excludes);
-                }
-            }
-            else {
-                dest.getParentFile().mkdirs();
-                FileInputStream in = new FileInputStream(src);
-                FileOutputStream out = new FileOutputStream(dest);
-                send(in, out);
-                in.close();
-                out.close();
-            }
-        }
-    }
-
-
-    public static void dumpOutput(final Process p) {
-        Thread outputReader = new Thread("outputReader") {
-            public void run() {
-                try {
-                    InputStream in = p.getInputStream();
-                    DownloadManager.send(in, System.out);
-                } catch (IOException e) {
-                    log(e);
-                }
-            }
-        };
-        outputReader.start();
-        Thread errorReader = new Thread("errorReader") {
-            public void run() {
-                try {
-                    InputStream in = p.getErrorStream();
-                    DownloadManager.send(in, System.err);
-                } catch (IOException e) {
-                    log(e);
-                }
-            }
-        };
-        errorReader.start();
-    }
-
-
-    /**
-     * Creates the merged rt.jar and resources.jar files.
-     */
-    private static void createMergedJars() {
-        log("DownloadManager.createMergedJars");
-        File bundlePath;
-        if (isWindowsVista()) {
-            bundlePath = getLocalLowTempBundlePath();
-        } else {
-            bundlePath = getBundlePath();
-        }
-        File tmp = new File(bundlePath, "tmp");
-        // explicitly check the final location, not the (potentially) local-low
-        // location -- a local-low finished isn't good enough to call it done
-        if (new File(getBundlePath(), "tmp" + File.separator + "finished").exists())
-            return; // already done
-        log("DownloadManager.createMergedJars: running");
-        tmp.mkdirs();
-        boolean retry = false;
-        do {
-            try {
-                Bundle.getBundle("merged").install(false, false, true);
-                postDownloadComplete();
-                // done, write an empty "finished" file to flag completion
-                File finished = new File(tmp, "finished");
-                new FileOutputStream(finished).close();
-                if (isWindowsVista()) {
-                    if (!moveFileWithBroker(getKernelJREDir() +
-                            "-bundles\\tmp\\finished")) {
-                        throw new IOException("unable to create 'finished' file");
-                    }
-                }
-                log("DownloadManager.createMergedJars: created " + finished);
-                // next JRE startup will move these files into their final
-                // locations, as long as no other JREs are running
-
-                // clean up the local low bundle directory on vista
-                if (isWindowsVista()) {
-                    File tmpDir = getLocalLowTempBundlePath();
-                    File[] list = tmpDir.listFiles();
-                    if (list != null) {
-                        for (int i = 0; i < list.length; i++) {
-                            list[i].delete();
-                        }
-                    }
-                    tmpDir.delete();
-                    log("Finished cleanup, " + tmpDir + ".exists(): " + tmpDir.exists());
-                }
-            }
-            catch (IOException e) {
-                log(e);
-            }
-        }
-        while (retry);
-        log("DownloadManager.createMergedJars: finished");
-    }
-
-
-    private static void shutdown() {
-        try {
-            ExecutorService e = Bundle.getThreadPool();
-            e.shutdown();
-            e.awaitTermination(60 * 60 * 24, TimeUnit.SECONDS);
-        }
-        catch (InterruptedException e) {
-        }
-    }
-
-
-    // returns the registry key for kernel.debug
-    static native boolean getDebugKey();
-
-
-    // returns the final value for the kernel debug property
-    public static boolean getDebugProperty(){
-         /*
-          * Check registry key value
-          */
-         boolean debugEnabled = getDebugKey();
-
-         /*
-          * Check system property - it should override the registry
-          * key value.
-          */
-         if (System.getProperty(KERNEL_DEBUG_PROPERTY) != null) {
-             debugEnabled = Boolean.valueOf(
-                      System.getProperty(KERNEL_DEBUG_PROPERTY));
-         }
-         return debugEnabled;
-
-    }
-
-
-    /**
-     * Outputs to the error stream even when System.err has not yet been
-     * initialized.
-     */
-    static void println(String msg) {
-        if (System.err != null)
-            System.err.println(msg);
-        else {
-            try {
-                if (errorStream == null)
-                    errorStream = new FileOutputStream(FileDescriptor.err);
-                errorStream.write((msg +
-                        System.getProperty("line.separator")).getBytes("utf-8"));
-            }
-            catch (IOException e) {
-                throw new RuntimeException(e);
-            }
-        }
-    }
-
-
-    static void log(String msg) {
-        if (debug) {
-            println(msg);
-            try {
-                if (logStream == null) {
-                    loadJKernelLibrary();
-                    File path = isWindowsVista() ? getLocalLowTempBundlePath() :
-                            getBundlePath();
-                    path = new File(path, "kernel." + getCurrentProcessId() + ".log");
-                    logStream = new FileOutputStream(path);
-                }
-                logStream.write((msg +
-                        System.getProperty("line.separator")).getBytes("utf-8"));
-                logStream.flush();
-            }
-            catch (IOException e) {
-                // ignore
-            }
-        }
-    }
-
-
-    static void log(Throwable e) {
-        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
-        PrintStream p = new PrintStream(buffer);
-        e.printStackTrace(p);
-        p.close();
-        log(buffer.toString(0));
-    }
-
-
-    /** Dump the contents of a map to System.out. */
-    private static void printMap(Map/*<String, String>*/ map) {
-        int size = 0;
-        Set<Integer> identityHashes = new HashSet<Integer>();
-        Iterator/*<Map.Entry<String, String>>*/ i = map.entrySet().iterator();
-        while (i.hasNext()) {
-            Map.Entry/*<String, String>*/ e = (Map.Entry) i.next();
-            String key = (String) e.getKey();
-            String value = (String) e.getValue();
-            System.out.println(key + ": " + value);
-            Integer keyHash = Integer.valueOf(System.identityHashCode(key));
-            if (!identityHashes.contains(keyHash)) {
-                identityHashes.add(keyHash);
-                size += key.length();
-            }
-            Integer valueHash = Integer.valueOf(System.identityHashCode(value));
-            if (!identityHashes.contains(valueHash)) {
-                identityHashes.add(valueHash);
-                size += value.length();
-            }
-        }
-        System.out.println(size + " bytes");
-    }
-
-
-    /** Process the "-dumpmaps" command-line argument. */
-    private static void dumpMaps() throws IOException {
-        System.out.println("Resources:");
-        System.out.println("----------");
-        printMap(getResourceMap());
-        System.out.println();
-        System.out.println("Files:");
-        System.out.println("----------");
-        printMap(getFileMap());
-    }
-
-
-    /** Process the "-download" command-line argument. */
-    private static void processDownload(String bundleName) throws IOException {
-        if (bundleName.equals("all")) {
-            debug = true;
-            doBackgroundDownloads(true);
-            performCompletionIfNeeded();
-        }
-        else {
-            Bundle bundle = Bundle.getBundle(bundleName);
-            if (bundle == null) {
-                println("Unknown bundle: " + bundleName);
-                System.exit(1);
-            }
-            else
-                bundle.install();
-        }
-    }
-
-
-    static native int getCurrentProcessId();
-
-    private DownloadManager() {
-    }
-
-    // Invoked by jkernel VM after the VM is initialized
-    static void setBootClassLoaderHook() {
-        if (!isJREComplete()) {
-            sun.misc.BootClassLoaderHook.setHook(new DownloadManager());
-        }
-    }
-
-    // Implementation of the BootClassLoaderHook interface
-    public String loadBootstrapClass(String name) {
-        // Check for download before we look for it.  If
-        // DownloadManager ends up downloading it, it will add it to
-        // our search path before we proceed to the findClass().
-        return DownloadManager.getBootClassPathEntryForClass(name);
-    }
-
-    public boolean loadLibrary(String name) {
-       try {
-            if (!DownloadManager.isJREComplete() &&
-                    !DownloadManager.isCurrentThreadDownloading()) {
-                return DownloadManager.downloadFile("bin/" +
-                    System.mapLibraryName(name));
-                // it doesn't matter if the downloadFile call returns false --
-                // it probably just means that this is a user library, as
-                // opposed to a JRE library
-            }
-        } catch (IOException e) {
-            throw new UnsatisfiedLinkError("Error downloading library " +
-                                                name + ": " + e);
-        } catch (NoClassDefFoundError e) {
-            // This happens while Java itself is being compiled; DownloadManager
-            // isn't accessible when this code is first invoked.  It isn't an
-            // issue, as if we can't find DownloadManager, we can safely assume
-            // that additional code is not available for download.
-        }
-        return false;
-    }
-
-    public boolean prefetchFile(String name) {
-        try {
-            return sun.jkernel.DownloadManager.downloadFile(name);
-        } catch (IOException ioe) {
-            return false;
-        }
-    }
-
-    public String getBootstrapResource(String name) {
-        try {
-            // If this is a known JRE resource, ensure that its bundle is
-            // downloaded.  If it isn't known, we just ignore the download
-            // failure and check to see if we can find the resource anyway
-            // (which is possible if the boot class path has been modified).
-            return DownloadManager.getBootClassPathEntryForResource(name);
-        } catch (NoClassDefFoundError e) {
-            // This happens while Java itself is being compiled; DownloadManager
-            // isn't accessible when this code is first invoked.  It isn't an
-            // issue, as if we can't find DownloadManager, we can safely assume
-            // that additional code is not available for download.
-            return null;
-        }
-    }
-
-    public URLClassPath getBootstrapClassPath(URLClassPath bcp,
-                                              URLStreamHandlerFactory factory)
-    {
-        return DownloadManager.getBootClassPath(bcp, factory);
-    }
-
-    public boolean isCurrentThreadPrefetching() {
-        return DownloadManager.isCurrentThreadDownloading();
-    }
-
-    public static void main(String[] arg) throws Exception {
-        AccessController.checkPermission(new AllPermission());
-
-        boolean valid = false;
-        if (arg.length == 2 && arg[0].equals("-install")) {
-            valid = true;
-            Bundle bundle = new Bundle() {
-                protected void updateState() {
-                    // the bundle path was provided on the command line, so we
-                    // just claim it has already been "downloaded" to the local
-                    // filesystem
-                    state = DOWNLOADED;
-                }
-            };
-
-            File jarPath;
-            int index = 0;
-            do {
-                index++;
-                jarPath = new File(getBundlePath(),
-                        CUSTOM_PREFIX + index + ".jar");
-            }
-            while (jarPath.exists());
-            bundle.setName(CUSTOM_PREFIX + index);
-            bundle.setLocalPath(new File(arg[1]));
-            bundle.setJarPath(jarPath);
-            bundle.setDeleteOnInstall(false);
-            bundle.install();
-        }
-        else if (arg.length == 2 && arg[0].equals("-download")) {
-            valid = true;
-            processDownload(arg[1]);
-        }
-        else if (arg.length == 1 && arg[0].equals("-dumpmaps")) {
-            valid = true;
-            dumpMaps();
-        }
-        else if (arg.length == 2 && arg[0].equals("-sha1")) {
-            valid = true;
-            System.out.println(BundleCheck.getInstance(new File(arg[1])));
-        }
-        else if (arg.length == 1 && arg[0].equals("-downloadtest")) {
-            valid = true;
-            File file = File.createTempFile("download", ".test");
-            for (;;) {
-                file.delete();
-                downloadFromURL(getBaseDownloadURL(), file, "URLS", true);
-                System.out.println("Downloaded " + file.length() + " bytes");
-            }
-        }
-        if (!valid) {
-            System.out.println("usage: DownloadManager -install <path>.zip |");
-            System.out.println("       DownloadManager -download " +
-                    "<bundle_name> |");
-            System.out.println("       DownloadManager -dumpmaps");
-            System.exit(1);
-        }
-    }
-}