/*
 * 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.*;

/**
 * Invoked by DownloadManager to begin (in a new JRE) the process of downloading
 * all remaining JRE components in the background.  A mutex is used to ensure
 * that only one BackgroundDownloader can be active at a time.
 *
 */
public class BackgroundDownloader {
    public static final String BACKGROUND_DOWNLOAD_PROPERTY = "kernel.background.download";
    // relative to the bundle directory
    public static final String PID_PATH = "tmp" + File.separator + "background.pid";

    // Time to wait before beginning to download components.  Gives the JRE
    // which spawned this one a chance to get its downloads going.
    private static final int WAIT_TIME = 10000;

    private static Mutex backgroundMutex;

    static synchronized Mutex getBackgroundMutex() {
        if (backgroundMutex == null)
            backgroundMutex = Mutex.create(DownloadManager.MUTEX_PREFIX + "background");
        return backgroundMutex;
    }

    private static void doBackgroundDownloads() {
        if (DownloadManager.isJREComplete())
            return;
        if (getBackgroundMutex().acquire(0)) { // give up and exit immediately if we can't acquire mutex
            try {
                writePid();
                Thread.sleep(WAIT_TIME);
                DownloadManager.doBackgroundDownloads(false);
                DownloadManager.performCompletionIfNeeded();
            }
            catch (InterruptedException e) {
            }
            finally {
                getBackgroundMutex().release();
            }
        }
        else {
            System.err.println("Unable to acquire background download mutex.");
            System.exit(1);
        }
    }


    /**
     * Writes the current process ID to a file, so that the uninstaller can
     * find and kill this process if needed.
     */
    private static void writePid() {
        try {
            File pid = new File(DownloadManager.getBundlePath(), PID_PATH);
            pid.getParentFile().mkdirs();
            PrintStream out = new PrintStream(new FileOutputStream(pid));
            pid.deleteOnExit();
            out.println(DownloadManager.getCurrentProcessId());
            out.close();
        }
        catch (IOException e) {
            e.printStackTrace();
            System.exit(1);
        }
    }


    /**
     * Reads from an InputStream until exhausted, writing all data to the
     * specified OutputStream.
     */
    private static void send(InputStream in, OutputStream out)
                                throws IOException {
        int c;
        byte[] buffer = new byte[2048];
        while ((c = in.read(buffer)) > 0)
            out.write(buffer, 0, c);
    }

     /*
      * Returns the value of the BACKGROUND_DOWNLOAD_PROPERTY.
      * Checks if system property has been set first
      * then checks if registry key to disable background download
      * has been set.
      */
     public static boolean  getBackgroundDownloadProperty(){
         /*
          * Check registry key value
          */
         boolean bgDownloadEnabled = getBackgroundDownloadKey();

         /*
          * Check system property - it should override the registry
          * key value.
          */
         if (System.getProperty(BACKGROUND_DOWNLOAD_PROPERTY) != null){
             bgDownloadEnabled = Boolean.valueOf(
                      System.getProperty(BACKGROUND_DOWNLOAD_PROPERTY));
         }
         return bgDownloadEnabled;

    }

    // This method is to retrieve the value of registry key
    // that disables background download.
    static native boolean getBackgroundDownloadKey();


    static void startBackgroundDownloads() {
        if (!getBackgroundDownloadProperty()){
            // If getBackgroundDownloadProperty() returns false
            // we're doing the downloads from this VM; we don't want to
            // spawn another one
            return;
        }

        // if System.err isn't initialized yet, it means the charsets aren't
        // available yet and we're going to run into trouble down below.  Wait
        // until it's ready.
        while (System.err == null) {
            try {
                Thread.sleep(1000);
            }
            catch (InterruptedException e) {
                return;
            }
        }

        try {
            String args = "-D" + BACKGROUND_DOWNLOAD_PROPERTY + "=false -Xmx256m";
            String backgroundDownloadURL = DownloadManager.getBaseDownloadURL();

            // only set KERNEL_DOWNLOAD_URL_PROPERTY if we override
            // the default download url
            if (backgroundDownloadURL != null &&
                    backgroundDownloadURL.equals(
                    DownloadManager.DEFAULT_DOWNLOAD_URL) == false) {
                args += " -D" + DownloadManager.KERNEL_DOWNLOAD_URL_PROPERTY +
                        "=" + backgroundDownloadURL;
            };
            args += " sun.jkernel.BackgroundDownloader";
            final Process jvm = Runtime.getRuntime().exec("\"" + new File(System.getProperty("java.home"), "bin" +
                   File.separator + "java.exe") + "\" " + args);
            Thread outputReader = new Thread("kernelOutputReader") {
                public void run() {
                    try {
                        InputStream in = jvm.getInputStream();
                        send(in, new PrintStream(new ByteArrayOutputStream()));
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            outputReader.setDaemon(true);
            outputReader.start();

            Thread errorReader = new Thread("kernelErrorReader") {
                public void run() {
                    try {
                        InputStream in = jvm.getErrorStream();
                        send(in, new PrintStream(new ByteArrayOutputStream()));
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            };
            errorReader.setDaemon(true);
            errorReader.start();
        }
        catch (Exception e) {
            e.printStackTrace();
            // TODO: error handling
        }
    }


    public static void main(String[] arg) {
        doBackgroundDownloads();
    }
}
