/*
 * Copyright (c) 2008, 2009, 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.security.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.jar.*;
import java.util.zip.*;
import sun.misc.Launcher;
import sun.misc.BootClassLoaderHook;

/**
 * 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();
    }

    /**
     * Returns an array of JAR files which have been added to the boot strap
     * class path since the JVM was first booted.
     */
    public static synchronized File[] getAdditionalBootStrapPaths() {
        return additionalBootStrapPaths != null ? additionalBootStrapPaths :
                new File[0];
    }


    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;
                Launcher.flushBootstrapClassPath();
           }
       }
    }


    /**
     * 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 File[] getAdditionalBootstrapPaths() {
        return DownloadManager.getAdditionalBootStrapPaths();
    }

    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);
        }
    }
}
