/*
 * Copyright 2003-2005 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.rmi.rmic.newrmic;

import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.RootDoc;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import sun.rmi.rmic.newrmic.jrmp.JrmpGenerator;
import sun.tools.util.CommandLine;

/**
 * The rmic front end.  This class contains the "main" method for rmic
 * command line invocation.
 *
 * A Main instance contains the stream to output error messages and
 * other diagnostics to.
 *
 * An rmic compilation batch (for example, one rmic command line
 * invocation) is executed by invoking the "compile" method of a Main
 * instance.
 *
 * WARNING: The contents of this source file are not part of any
 * supported API.  Code that depends on them does so at its own risk:
 * they are subject to change or removal without notice.
 *
 * NOTE: If and when there is a J2SE API for invoking SDK tools, this
 * class should be updated to support that API.
 *
 * NOTE: This class is the front end for a "new" rmic implementation,
 * which uses javadoc and the doclet API for reading class files and
 * javac for compiling generated source files.  This implementation is
 * incomplete: it lacks any CORBA-based back end implementations, and
 * thus the command line options "-idl", "-iiop", and their related
 * options are not yet supported.  The front end for the "old",
 * oldjavac-based rmic implementation is sun.rmi.rmic.Main.
 *
 * @author Peter Jones
 **/
public class Main {

    /*
     * Implementation note:
     *
     * In order to use the doclet API to read class files, much of
     * this implementation of rmic executes as a doclet within an
     * invocation of javadoc.  This class is used as the doclet class
     * for such javadoc invocations, via its static "start" and
     * "optionLength" methods.  There is one javadoc invocation per
     * rmic compilation batch.
     *
     * The only guaranteed way to pass data to a doclet through a
     * javadoc invocation is through doclet-specific options on the
     * javadoc "command line".  Rather than passing numerous pieces of
     * individual data in string form as javadoc options, we use a
     * single doclet-specific option ("-batchID") to pass a numeric
     * identifier that uniquely identifies the rmic compilation batch
     * that the javadoc invocation is for, and that identifier can
     * then be used as a key in a global table to retrieve an object
     * containing all of batch-specific data (rmic command line
     * arguments, etc.).
     */

    /** guards "batchCount" */
    private static final Object batchCountLock = new Object();

    /** number of batches run; used to generated batch IDs */
    private static long batchCount = 0;

    /** maps batch ID to batch data */
    private static final Map<Long,Batch> batchTable =
        Collections.synchronizedMap(new HashMap<Long,Batch>());

    /** stream to output error messages and other diagnostics to */
    private final PrintStream out;

    /** name of this program, to use in error messages */
    private final String program;

    /**
     * Command line entry point.
     **/
    public static void main(String[] args) {
        Main rmic = new Main(System.err, "rmic");
        System.exit(rmic.compile(args) ? 0 : 1);
    }

    /**
     * Creates a Main instance that writes output to the specified
     * stream.  The specified program name is used in error messages.
     **/
    public Main(OutputStream out, String program) {
        this.out = out instanceof PrintStream ?
            (PrintStream) out : new PrintStream(out);
        this.program = program;
    }

    /**
     * Compiles a batch of input classes, as given by the specified
     * command line arguments.  Protocol-specific generators are
     * determined by the choice options on the command line.  Returns
     * true if successful, or false if an error occurred.
     *
     * NOTE: This method is retained for transitional consistency with
     * previous implementations.
     **/
    public boolean compile(String[] args) {
        long startTime = System.currentTimeMillis();

        long batchID;
        synchronized (batchCountLock) {
            batchID = batchCount++;     // assign batch ID
        }

        // process command line
        Batch batch = parseArgs(args);
        if (batch == null) {
            return false;               // terminate if error occurred
        }

        /*
         * With the batch data retrievable in the global table, run
         * javadoc to continue the rest of the batch's compliation as
         * a doclet.
         */
        boolean status;
        try {
            batchTable.put(batchID, batch);
            status = invokeJavadoc(batch, batchID);
        } finally {
            batchTable.remove(batchID);
        }

        if (batch.verbose) {
            long deltaTime = System.currentTimeMillis() - startTime;
            output(Resources.getText("rmic.done_in",
                                     Long.toString(deltaTime)));
        }

        return status;
    }

    /**
     * Prints the specified string to the output stream of this Main
     * instance.
     **/
    public void output(String msg) {
        out.println(msg);
    }

    /**
     * Prints an error message to the output stream of this Main
     * instance.  The first argument is used as a key in rmic's
     * resource bundle, and the rest of the arguments are used as
     * arguments in the formatting of the resource string.
     **/
    public void error(String msg, String... args) {
        output(Resources.getText(msg, args));
    }

    /**
     * Prints rmic's usage message to the output stream of this Main
     * instance.
     *
     * This method is public so that it can be used by the "parseArgs"
     * methods of Generator implementations.
     **/
    public void usage() {
        error("rmic.usage", program);
    }

    /**
     * Processes rmic command line arguments.  Returns a Batch object
     * representing the command line arguments if successful, or null
     * if an error occurred.  Processed elements of the args array are
     * set to null.
     **/
    private Batch parseArgs(String[] args) {
        Batch batch = new Batch();

        /*
         * Pre-process command line for @file arguments.
         */
        try {
            args = CommandLine.parse(args);
        } catch (FileNotFoundException e) {
            error("rmic.cant.read", e.getMessage());
            return null;
        } catch (IOException e) {
            e.printStackTrace(out);
            return null;
        }

        for (int i = 0; i < args.length; i++) {

            if (args[i] == null) {
                // already processed by a generator
                continue;

            } else if (args[i].equals("-Xnew")) {
                // we're already using the "new" implementation
                args[i] = null;

            } else if (args[i].equals("-show")) {
                // obselete: fail
                error("rmic.option.unsupported", args[i]);
                usage();
                return null;

            } else if (args[i].equals("-O")) {
                // obselete: warn but tolerate
                error("rmic.option.unsupported", args[i]);
                args[i] = null;

            } else if (args[i].equals("-debug")) {
                // obselete: warn but tolerate
                error("rmic.option.unsupported", args[i]);
                args[i] = null;

            } else if (args[i].equals("-depend")) {
                // obselete: warn but tolerate
                // REMIND: should this fail instead?
                error("rmic.option.unsupported", args[i]);
                args[i] = null;

            } else if (args[i].equals("-keep") ||
                       args[i].equals("-keepgenerated"))
            {
                batch.keepGenerated = true;
                args[i] = null;

            } else if (args[i].equals("-g")) {
                batch.debug = true;
                args[i] = null;

            } else if (args[i].equals("-nowarn")) {
                batch.noWarn = true;
                args[i] = null;

            } else if (args[i].equals("-nowrite")) {
                batch.noWrite = true;
                args[i] = null;

            } else if (args[i].equals("-verbose")) {
                batch.verbose = true;
                args[i] = null;

            } else if (args[i].equals("-Xnocompile")) {
                batch.noCompile = true;
                batch.keepGenerated = true;
                args[i] = null;

            } else if (args[i].equals("-bootclasspath")) {
                if ((i + 1) >= args.length) {
                    error("rmic.option.requires.argument", args[i]);
                    usage();
                    return null;
                }
                if (batch.bootClassPath != null) {
                    error("rmic.option.already.seen", args[i]);
                    usage();
                    return null;
                }
                args[i] = null;
                batch.bootClassPath = args[++i];
                assert batch.bootClassPath != null;
                args[i] = null;

            } else if (args[i].equals("-extdirs")) {
                if ((i + 1) >= args.length) {
                    error("rmic.option.requires.argument", args[i]);
                    usage();
                    return null;
                }
                if (batch.extDirs != null) {
                    error("rmic.option.already.seen", args[i]);
                    usage();
                    return null;
                }
                args[i] = null;
                batch.extDirs = args[++i];
                assert batch.extDirs != null;
                args[i] = null;

            } else if (args[i].equals("-classpath")) {
                if ((i + 1) >= args.length) {
                    error("rmic.option.requires.argument", args[i]);
                    usage();
                    return null;
                }
                if (batch.classPath != null) {
                    error("rmic.option.already.seen", args[i]);
                    usage();
                    return null;
                }
                args[i] = null;
                batch.classPath = args[++i];
                assert batch.classPath != null;
                args[i] = null;

            } else if (args[i].equals("-d")) {
                if ((i + 1) >= args.length) {
                    error("rmic.option.requires.argument", args[i]);
                    usage();
                    return null;
                }
                if (batch.destDir != null) {
                    error("rmic.option.already.seen", args[i]);
                    usage();
                    return null;
                }
                args[i] = null;
                batch.destDir = new File(args[++i]);
                assert batch.destDir != null;
                args[i] = null;
                if (!batch.destDir.exists()) {
                    error("rmic.no.such.directory", batch.destDir.getPath());
                    usage();
                    return null;
                }

            } else if (args[i].equals("-v1.1") ||
                       args[i].equals("-vcompat") ||
                       args[i].equals("-v1.2"))
            {
                Generator gen = new JrmpGenerator();
                batch.generators.add(gen);
                // JrmpGenerator only requires base BatchEnvironment class
                if (!gen.parseArgs(args, this)) {
                    return null;
                }

            } else if (args[i].equalsIgnoreCase("-iiop")) {
                error("rmic.option.unimplemented", args[i]);
                return null;

                // Generator gen = new IiopGenerator();
                // batch.generators.add(gen);
                // if (!batch.envClass.isAssignableFrom(gen.envClass())) {
                //   error("rmic.cannot.use.both",
                //         batch.envClass.getName(), gen.envClass().getName());
                //   return null;
                // }
                // batch.envClass = gen.envClass();
                // if (!gen.parseArgs(args, this)) {
                //   return null;
                // }

            } else if (args[i].equalsIgnoreCase("-idl")) {
                error("rmic.option.unimplemented", args[i]);
                return null;

                // see implementation sketch above

            } else if (args[i].equalsIgnoreCase("-xprint")) {
                error("rmic.option.unimplemented", args[i]);
                return null;

                // see implementation sketch above
            }
        }

        /*
         * At this point, all that remains non-null in the args
         * array are input class names or illegal options.
         */
        for (int i = 0; i < args.length; i++) {
            if (args[i] != null) {
                if (args[i].startsWith("-")) {
                    error("rmic.no.such.option", args[i]);
                    usage();
                    return null;
                } else {
                    batch.classes.add(args[i]);
                }
            }
        }
        if (batch.classes.isEmpty()) {
            usage();
            return null;
        }

        /*
         * If options did not specify at least one protocol-specific
         * generator, then JRMP is the default.
         */
        if (batch.generators.isEmpty()) {
            batch.generators.add(new JrmpGenerator());
        }
        return batch;
    }

    /**
     * Doclet class entry point.
     **/
    public static boolean start(RootDoc rootDoc) {

        /*
         * Find batch ID among javadoc options, and retrieve
         * corresponding batch data from global table.
         */
        long batchID = -1;
        for (String[] option : rootDoc.options()) {
            if (option[0].equals("-batchID")) {
                try {
                    batchID = Long.parseLong(option[1]);
                } catch (NumberFormatException e) {
                    throw new AssertionError(e);
                }
            }
        }
        Batch batch = batchTable.get(batchID);
        assert batch != null;

        /*
         * Construct batch environment using class agreed upon by
         * generator implementations.
         */
        BatchEnvironment env;
        try {
            Constructor<? extends BatchEnvironment> cons =
                batch.envClass.getConstructor(new Class[] { RootDoc.class });
            env = cons.newInstance(rootDoc);
        } catch (NoSuchMethodException e) {
            throw new AssertionError(e);
        } catch (IllegalAccessException e) {
            throw new AssertionError(e);
        } catch (InstantiationException e) {
            throw new AssertionError(e);
        } catch (InvocationTargetException e) {
            throw new AssertionError(e);
        }

        env.setVerbose(batch.verbose);

        /*
         * Determine the destination directory (the top of the package
         * hierarchy) for the output of this batch; if no destination
         * directory was specified on the command line, then the
         * default is the current working directory.
         */
        File destDir = batch.destDir;
        if (destDir == null) {
            destDir = new File(System.getProperty("user.dir"));
        }

        /*
         * Run each input class through each generator.
         */
        for (String inputClassName : batch.classes) {
            ClassDoc inputClass = rootDoc.classNamed(inputClassName);
            try {
                for (Generator gen : batch.generators) {
                    gen.generate(env, inputClass, destDir);
                }
            } catch (NullPointerException e) {
                /*
                 * We assume that this means that some class that was
                 * needed (perhaps even a bootstrap class) was not
                 * found, and that javadoc has already reported this
                 * as an error.  There is nothing for us to do here
                 * but try to continue with the next input class.
                 *
                 * REMIND: More explicit error checking throughout
                 * would be preferable, however.
                 */
            }
        }

        /*
         * Compile any generated source files, if configured to do so.
         */
        boolean status = true;
        List<File> generatedFiles = env.generatedFiles();
        if (!batch.noCompile && !batch.noWrite && !generatedFiles.isEmpty()) {
            status = batch.enclosingMain().invokeJavac(batch, generatedFiles);
        }

        /*
         * Delete any generated source files, if configured to do so.
         */
        if (!batch.keepGenerated) {
            for (File file : generatedFiles) {
                file.delete();
            }
        }

        return status;
    }

    /**
     * Doclet class method that indicates that this doclet class
     * recognizes (only) the "-batchID" option on the javadoc command
     * line, and that the "-batchID" option comprises two arguments on
     * the javadoc command line.
     **/
    public static int optionLength(String option) {
        if (option.equals("-batchID")) {
            return 2;
        } else {
            return 0;
        }
    }

    /**
     * Runs the javadoc tool to invoke this class as a doclet, passing
     * command line options derived from the specified batch data and
     * indicating the specified batch ID.
     *
     * NOTE: This method currently uses a J2SE-internal API to run
     * javadoc.  If and when there is a J2SE API for invoking SDK
     * tools, this method should be updated to use that API instead.
     **/
    private boolean invokeJavadoc(Batch batch, long batchID) {
        List<String> javadocArgs = new ArrayList<String>();

        // include all types, regardless of language-level access
        javadocArgs.add("-private");

        // inputs are class names, not source files
        javadocArgs.add("-Xclasses");

        // reproduce relevant options from rmic invocation
        if (batch.verbose) {
            javadocArgs.add("-verbose");
        }
        if (batch.bootClassPath != null) {
            javadocArgs.add("-bootclasspath");
            javadocArgs.add(batch.bootClassPath);
        }
        if (batch.extDirs != null) {
            javadocArgs.add("-extdirs");
            javadocArgs.add(batch.extDirs);
        }
        if (batch.classPath != null) {
            javadocArgs.add("-classpath");
            javadocArgs.add(batch.classPath);
        }

        // specify batch ID
        javadocArgs.add("-batchID");
        javadocArgs.add(Long.toString(batchID));

        /*
         * Run javadoc on union of rmic input classes and all
         * generators' bootstrap classes, so that they will all be
         * available to the doclet code.
         */
        Set<String> classNames = new HashSet<String>();
        for (Generator gen : batch.generators) {
            classNames.addAll(gen.bootstrapClassNames());
        }
        classNames.addAll(batch.classes);
        for (String s : classNames) {
            javadocArgs.add(s);
        }

        // run javadoc with our program name and output stream
        int status = com.sun.tools.javadoc.Main.execute(
            program,
            new PrintWriter(out, true),
            new PrintWriter(out, true),
            new PrintWriter(out, true),
            this.getClass().getName(),          // doclet class is this class
            javadocArgs.toArray(new String[javadocArgs.size()]));
        return status == 0;
    }

    /**
     * Runs the javac tool to compile the specified source files,
     * passing command line options derived from the specified batch
     * data.
     *
     * NOTE: This method currently uses a J2SE-internal API to run
     * javac.  If and when there is a J2SE API for invoking SDK tools,
     * this method should be updated to use that API instead.
     **/
    private boolean invokeJavac(Batch batch, List<File> files) {
        List<String> javacArgs = new ArrayList<String>();

        // rmic never wants to display javac warnings
        javacArgs.add("-nowarn");

        // reproduce relevant options from rmic invocation
        if (batch.debug) {
            javacArgs.add("-g");
        }
        if (batch.verbose) {
            javacArgs.add("-verbose");
        }
        if (batch.bootClassPath != null) {
            javacArgs.add("-bootclasspath");
            javacArgs.add(batch.bootClassPath);
        }
        if (batch.extDirs != null) {
            javacArgs.add("-extdirs");
            javacArgs.add(batch.extDirs);
        }
        if (batch.classPath != null) {
            javacArgs.add("-classpath");
            javacArgs.add(batch.classPath);
        }

        /*
         * For now, rmic still always produces class files that have a
         * class file format version compatible with JDK 1.1.
         */
        javacArgs.add("-source");
        javacArgs.add("1.3");
        javacArgs.add("-target");
        javacArgs.add("1.1");

        // add source files to compile
        for (File file : files) {
            javacArgs.add(file.getPath());
        }

        // run javac with our output stream
        int status = com.sun.tools.javac.Main.compile(
            javacArgs.toArray(new String[javacArgs.size()]),
            new PrintWriter(out, true));
        return status == 0;
    }

    /**
     * The data for an rmic compliation batch: the processed command
     * line arguments.
     **/
    private class Batch {
        boolean keepGenerated = false;  // -keep or -keepgenerated
        boolean debug = false;          // -g
        boolean noWarn = false;         // -nowarn
        boolean noWrite = false;        // -nowrite
        boolean verbose = false;        // -verbose
        boolean noCompile = false;      // -Xnocompile
        String bootClassPath = null;    // -bootclasspath
        String extDirs = null;          // -extdirs
        String classPath = null;        // -classpath
        File destDir = null;            // -d
        List<Generator> generators = new ArrayList<Generator>();
        Class<? extends BatchEnvironment> envClass = BatchEnvironment.class;
        List<String> classes = new ArrayList<String>();

        Batch() { }

        /**
         * Returns the Main instance for this batch.
         **/
        Main enclosingMain() {
            return Main.this;
        }
    }
}
