/*
 * Copyright 1999-2006 Sun Microsystems, Inc.  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.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package sun.applet;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.net.MalformedURLException;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Vector;
import sun.net.www.ParseUtil;

/**
 * The main entry point into AppletViewer.
 */
public class Main {
    /**
     * The file which contains all of the AppletViewer specific properties.
     */
    static File theUserPropertiesFile;

    /**
     * The default key/value pairs for the required user-specific properties.
     */
    static final String [][] avDefaultUserProps = {
        // There's a bootstrapping problem here.  If we don't have a proxyHost,
        // then we will not be able to connect to a URL outside the firewall;
        // however, there's no way for us to set the proxyHost without starting
        // AppletViewer.  This problem existed before the re-write.
        {"http.proxyHost", ""},
        {"http.proxyPort", "80"},
        {"package.restrict.access.sun", "true"}
    };

    static {
        File userHome = new File(System.getProperty("user.home"));
        // make sure we can write to this location
        userHome.canWrite();

        theUserPropertiesFile = new File(userHome, ".appletviewer");
    }

    // i18n
    private static AppletMessageHandler amh = new AppletMessageHandler("appletviewer");

    /**
     * Member variables set according to options passed in to AppletViewer.
     */
    private boolean debugFlag = false;
    private boolean helpFlag  = false;
    private String  encoding  = null;
    private boolean noSecurityFlag  = false;
    private static boolean cmdLineTestFlag = false;

    /**
     * The list of valid URLs passed in to AppletViewer.
     */
    private static Vector urlList = new Vector(1);

    // This is used in init().  Getting rid of this is desirable but depends
    // on whether the property that uses it is necessary/standard.
    public static final String theVersion = System.getProperty("java.version");

    /**
     * The main entry point into AppletViewer.
     */
    public static void main(String [] args) {
        Main m = new Main();
        int ret = m.run(args);

        // Exit immediately if we got some sort of error along the way.
        // For debugging purposes, if we have passed in "-XcmdLineTest" we
        // force a premature exit.
        if ((ret != 0) || (cmdLineTestFlag))
            System.exit(ret);
    }

    private int run(String [] args) {
        // DECODE ARGS
        try {
            if (args.length == 0) {
                usage();
                return 0;
            }
            for (int i = 0; i < args.length; ) {
                int j = decodeArg(args, i);
                if (j == 0) {
                    throw new ParseException(lookup("main.err.unrecognizedarg",
                                                    args[i]));
                }
                i += j;
            }
        } catch (ParseException e) {
            System.err.println(e.getMessage());
            return 1;
        }

        // CHECK ARGUMENTS
        if (helpFlag) {
            usage();
            return 0;
        }

        if (urlList.size() == 0) {
            System.err.println(lookup("main.err.inputfile"));
            return 1;
        }

        if (debugFlag) {
            // START A DEBUG SESSION
            // Given the current architecture, we will end up decoding the
            // arguments again, but at least we are guaranteed to have
            // arguments which are valid.
            return invokeDebugger(args);
        }

        // INSTALL THE SECURITY MANAGER (if necessary)
        if (!noSecurityFlag && (System.getSecurityManager() == null))
            init();

        // LAUNCH APPLETVIEWER FOR EACH URL
        for (int i = 0; i < urlList.size(); i++) {
            try {
                // XXX 5/17 this parsing method should be changed/fixed so that
                // it doesn't do both parsing of the html file and launching of
                // the AppletPanel
                AppletViewer.parse((URL) urlList.elementAt(i), encoding);
            } catch (IOException e) {
                System.err.println(lookup("main.err.io", e.getMessage()));
                return 1;
            }
        }
        return 0;
    }

    private static void usage() {
        System.out.println(lookup("usage"));
    }

    /**
     * Decode a single argument in an array and return the number of elements
     * used.
     *
     * @param args The array of arguments.
     * @param i    The argument to decode.
     * @return     The number of array elements used when the argument was
     *             decoded.
     * @exception ParseException
     *             Thrown when there is a problem with something in the
     *             argument array.
     */
    private int decodeArg(String [] args, int i) throws ParseException {
        String arg = args[i];
        int argc = args.length;

        if ("-help".equalsIgnoreCase(arg) || "-?".equals(arg)) {
            helpFlag = true;
            return 1;
        } else if ("-encoding".equals(arg) && (i < argc - 1)) {
            if (encoding != null)
                throw new ParseException(lookup("main.err.dupoption", arg));
            encoding = args[++i];
            return 2;
        } else if ("-debug".equals(arg)) {
            debugFlag = true;
            return 1;
        } else if ("-Xnosecurity".equals(arg)) {
            // This is an undocumented (and, in the future, unsupported)
            // flag which prevents AppletViewer from installing its own
            // SecurityManager.

            System.err.println();
            System.err.println(lookup("main.warn.nosecmgr"));
            System.err.println();

            noSecurityFlag = true;
            return 1;
        } else if ("-XcmdLineTest".equals(arg)) {
            // This is an internal flag which should be used for command-line
            // testing.  It instructs AppletViewer to force a premature exit
            // immediately after the applet has been launched.
            cmdLineTestFlag = true;
            return 1;
        } else if (arg.startsWith("-")) {
            throw new ParseException(lookup("main.err.unsupportedopt", arg));
        } else {
            // we found what we hope is a url
            URL url = parseURL(arg);
            if (url != null) {
                urlList.addElement(url);
                return 1;
            }
        }
        return 0;
    }

    /**
     * Following the relevant RFC, construct a valid URL based on the passed in
     * string.
     *
     * @param url  a string which represents either a relative or absolute URL.
     * @return     a URL when the passed in string can be interpreted according
     *             to the RFC, <code>null</code> otherwise.
     * @exception  ParseException
     *             Thrown when we are unable to construct a proper URL from the
     *             passed in string.
     */
    private URL parseURL(String url) throws ParseException {
        URL u = null;
        // prefix of the urls with 'file' scheme
        String prefix = "file:";

        try {
            if (url.indexOf(':') <= 1)
            {
                // appletviewer accepts only unencoded filesystem paths
                u = ParseUtil.fileToEncodedURL(new File(url));
            } else if (url.startsWith(prefix) &&
                       url.length() != prefix.length() &&
                       !(new File(url.substring(prefix.length())).isAbsolute()))
            {
                // relative file URL, like this "file:index.html"
                // ensure that this file URL is absolute
                // ParseUtil.fileToEncodedURL should be done last (see 6329251)
                String path = ParseUtil.fileToEncodedURL(new File(System.getProperty("user.dir"))).getPath() +
                    url.substring(prefix.length());
                u = new URL("file", "", path);
            } else {
                // appletviewer accepts only encoded urls
                u = new URL(url);
            }
        } catch (MalformedURLException e) {
            throw new ParseException(lookup("main.err.badurl",
                                            url, e.getMessage()));
        }

        return u;
    }

    /**
     * Invoke the debugger with the arguments passed in to appletviewer.
     *
     * @param args The arguments passed into the debugger.
     * @return     <code>0</code> if the debugger is invoked successfully,
     *             <code>1</code> otherwise.
     */
    private int invokeDebugger(String [] args) {
        // CONSTRUCT THE COMMAND LINE
        String [] newArgs = new String[args.length + 1];
        int current = 0;

        // Add a -classpath argument that prevents
        // the debugger from launching appletviewer with the default of
        // ".". appletviewer's classpath should never contain valid
        // classes since they will result in security exceptions.
        // Ideally, the classpath should be set to "", but the VM won't
        // allow an empty classpath, so a phony directory name is used.
        String phonyDir = System.getProperty("java.home") +
                          File.separator + "phony";
        newArgs[current++] = "-Djava.class.path=" + phonyDir;

        // Appletviewer's main class is the debuggee
        newArgs[current++] = "sun.applet.Main";

        // Append all the of the original appletviewer arguments,
        // leaving out the "-debug" option.
        for (int i = 0; i < args.length; i++) {
            if (!("-debug".equals(args[i]))) {
                newArgs[current++] = args[i];
            }
        }

        // LAUNCH THE DEBUGGER
        // Reflection is used for two reasons:
        // 1) The debugger classes are on classpath and thus must be loaded
        // by the application class loader. (Currently, appletviewer are
        // loaded through the boot class path out of rt.jar.)
        // 2) Reflection removes any build dependency between appletviewer
        // and jdb.
        try {
            Class c = Class.forName("com.sun.tools.example.debug.tty.TTY", true,
                                    ClassLoader.getSystemClassLoader());
            Method m = c.getDeclaredMethod("main",
                                           new Class[] { String[].class });
            m.invoke(null, new Object[] { newArgs });
        } catch (ClassNotFoundException cnfe) {
            System.err.println(lookup("main.debug.cantfinddebug"));
            return 1;
        } catch (NoSuchMethodException nsme) {
            System.err.println(lookup("main.debug.cantfindmain"));
            return 1;
        } catch (InvocationTargetException ite) {
            System.err.println(lookup("main.debug.exceptionindebug"));
            return 1;
        } catch (IllegalAccessException iae) {
            System.err.println(lookup("main.debug.cantaccess"));
            return 1;
        }
        return 0;
    }

    private void init() {
        // GET APPLETVIEWER USER-SPECIFIC PROPERTIES
        Properties avProps = getAVProps();

        // ADD OTHER RANDOM PROPERTIES
        // XXX 5/18 need to revisit why these are here, is there some
        // standard for what is available?

        // Standard browser properties
        avProps.put("browser", "sun.applet.AppletViewer");
        avProps.put("browser.version", "1.06");
        avProps.put("browser.vendor", "Sun Microsystems Inc.");
        avProps.put("http.agent", "Java(tm) 2 SDK, Standard Edition v" + theVersion);

        // Define which packages can be extended by applets
        // XXX 5/19 probably not needed, not checked in AppletSecurity
        avProps.put("package.restrict.definition.java", "true");
        avProps.put("package.restrict.definition.sun", "true");

        // Define which properties can be read by applets.
        // A property named by "key" can be read only when its twin
        // property "key.applet" is true.  The following ten properties
        // are open by default.  Any other property can be explicitly
        // opened up by the browser user by calling appletviewer with
        // -J-Dkey.applet=true
        avProps.put("java.version.applet", "true");
        avProps.put("java.vendor.applet", "true");
        avProps.put("java.vendor.url.applet", "true");
        avProps.put("java.class.version.applet", "true");
        avProps.put("os.name.applet", "true");
        avProps.put("os.version.applet", "true");
        avProps.put("os.arch.applet", "true");
        avProps.put("file.separator.applet", "true");
        avProps.put("path.separator.applet", "true");
        avProps.put("line.separator.applet", "true");

        // Read in the System properties.  If something is going to be
        // over-written, warn about it.
        Properties sysProps = System.getProperties();
        for (Enumeration e = sysProps.propertyNames(); e.hasMoreElements(); ) {
            String key = (String) e.nextElement();
            String val = (String) sysProps.getProperty(key);
            String oldVal;
            if ((oldVal = (String) avProps.setProperty(key, val)) != null)
                System.err.println(lookup("main.warn.prop.overwrite", key,
                                          oldVal, val));
        }

        // INSTALL THE PROPERTY LIST
        System.setProperties(avProps);

        // Create and install the security manager
        if (!noSecurityFlag) {
            System.setSecurityManager(new AppletSecurity());
        } else {
            System.err.println(lookup("main.nosecmgr"));
        }

        // REMIND: Create and install a socket factory!
    }

    /**
     * Read the AppletViewer user-specific properties.  Typically, these
     * properties should reside in the file $USER/.appletviewer.  If this file
     * does not exist, one will be created.  Information for this file will
     * be gleaned from $USER/.hotjava/properties.  If that file does not exist,
     * then default values will be used.
     *
     * @return     A Properties object containing all of the AppletViewer
     *             user-specific properties.
     */
    private Properties getAVProps() {
        Properties avProps = new Properties();

        File dotAV = theUserPropertiesFile;
        if (dotAV.exists()) {
            // we must have already done the conversion
            if (dotAV.canRead()) {
                // just read the file
                avProps = getAVProps(dotAV);
            } else {
                // send out warning and use defaults
                System.err.println(lookup("main.warn.cantreadprops",
                                          dotAV.toString()));
                avProps = setDefaultAVProps();
            }
        } else {
            // create the $USER/.appletviewer file

            // see if $USER/.hotjava/properties exists
            File userHome = new File(System.getProperty("user.home"));
            File dotHJ = new File(userHome, ".hotjava");
            dotHJ = new File(dotHJ, "properties");
            if (dotHJ.exists()) {
                // just read the file
                avProps = getAVProps(dotHJ);
            } else {
                // send out warning and use defaults
                System.err.println(lookup("main.warn.cantreadprops",
                                          dotHJ.toString()));
                avProps = setDefaultAVProps();
            }

            // SAVE THE FILE
            try {
                FileOutputStream out = new FileOutputStream(dotAV);
                avProps.store(out, lookup("main.prop.store"));
                out.close();
            } catch (IOException e) {
                System.err.println(lookup("main.err.prop.cantsave",
                                          dotAV.toString()));
            }
        }
        return avProps;
    }

    /**
     * Set the AppletViewer user-specific properties to be the default values.
     *
     * @return     A Properties object containing all of the AppletViewer
     *             user-specific properties, set to the default values.
     */
    private Properties setDefaultAVProps() {
        Properties avProps = new Properties();
        for (int i = 0; i < avDefaultUserProps.length; i++) {
            avProps.setProperty(avDefaultUserProps[i][0],
                                avDefaultUserProps[i][1]);
        }
        return avProps;
    }

    /**
     * Given a file, find only the properties that are setable by AppletViewer.
     *
     * @param inFile A Properties file from which we select the properties of
     *             interest.
     * @return     A Properties object containing all of the AppletViewer
     *             user-specific properties.
     */
    private Properties getAVProps(File inFile) {
        Properties avProps  = new Properties();

        // read the file
        Properties tmpProps = new Properties();
        try {
            FileInputStream in = new FileInputStream(inFile);
            tmpProps.load(new BufferedInputStream(in));
            in.close();
        } catch (IOException e) {
            System.err.println(lookup("main.err.prop.cantread",
                                      inFile.toString()));
        }

        // pick off the properties we care about
        for (int i = 0; i < avDefaultUserProps.length; i++) {
            String value = tmpProps.getProperty(avDefaultUserProps[i][0]);
            if (value != null) {
                // the property exists in the file, so replace the default
                avProps.setProperty(avDefaultUserProps[i][0], value);
            } else {
                // just use the default
                avProps.setProperty(avDefaultUserProps[i][0],
                                    avDefaultUserProps[i][1]);
            }
        }
        return avProps;
    }

    /**
     * Methods for easier i18n handling.
     */

    private static String lookup(String key) {
        return amh.getMessage(key);
    }

    private static String lookup(String key, String arg0) {
        return amh.getMessage(key, arg0);
    }

    private static String lookup(String key, String arg0, String arg1) {
        return amh.getMessage(key, arg0, arg1);
    }

    private static String lookup(String key, String arg0, String arg1,
                                 String arg2) {
        return amh.getMessage(key, arg0, arg1, arg2);
    }

    class ParseException extends RuntimeException
    {
        public ParseException(String msg) {
            super(msg);
        }

        public ParseException(Throwable t) {
            super(t.getMessage());
            this.t = t;
        }

        Throwable t = null;
    }
}
