/*
 * Copyright (c) 2012, 2014, 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 com.sun.tools.sjavac;

import java.io.IOException;
import java.io.PrintStream;
import java.util.*;
import java.nio.file.Path;
import java.nio.file.Files;

import com.sun.tools.sjavac.options.Options;
import com.sun.tools.sjavac.options.SourceLocation;
import com.sun.tools.sjavac.server.JavacService;
import com.sun.tools.sjavac.server.JavacServer;
import com.sun.tools.sjavac.server.JavacServiceClient;

/**
 * The main class of the smart javac wrapper tool.
 *
 * <p><b>This is NOT part of any supported API.
 * If you write code that depends on this, you do so at your own
 * risk.  This code and its internal interfaces are subject to change
 * or deletion without notice.</b></p>
 */
public class Main {

    /*  This is a smart javac wrapper primarily used when building the OpenJDK,
        though other projects are welcome to use it too. But please be aware
        that it is not an official api and will change in the future.
        (We really mean it!)

        Goals:

        ** Create a state file, containing information about the build, so
           that incremental builds only rebuild what is necessary. Also the
           state file can be used by make/ant to detect when to trigger
           a call to the smart javac wrapper.

           This file is called bin/javac_state (assuming that you specified "-d bin")
           Thus the simplest makefile is:

           SJAVAC=java -cp .../tools.jar com.sun.tools.sjavac.Main
           SRCS=$(shell find src -name "*.java")
           bin/javac_state : $(SRCS)
                  $(SJAVAC) src -d bin

           This makefile will run very fast and detect properly when Java code needs to
           be recompiled. The smart javac wrapper will then use the information in java_state
           to do an efficient incremental compile.

           Previously it was near enough impossible to write an efficient makefile for Java
           with support for incremental builds and dependency tracking.

        ** Separate java sources to be compiled from java
           sources used >only< for linking. The options:

           "dir" points to root dir with sources to be compiled
           "-sourcepath dir" points to root dir with sources used only for linking
           "-classpath dir" points to dir with classes used only for linking (as before)

        ** Use all cores for compilation by default.
           "-j 4" limit the number of cores to 4.
           For the moment, the sjavac server additionally limits the number of cores to three.
           This will improve in the future when more sharing is performed between concurrent JavaCompilers.

        ** Basic translation support from other sources to java, and then compilation of the generated java.
           This functionality might be moved into annotation processors instead.
           Again this is driven by the OpenJDK sources where properties and a few other types of files
           are converted into Java sources regularily. The javac_state embraces copy and tr, and perform
           incremental recompiles and copying for these as well. META-INF will be a special copy rule
           that will copy any files found below any META-INF dir in src to the bin/META-INF dir.
           "-copy .gif"
           "-copy META-INF"
           "-tr .prop=com.sun.tools.javac.smart.CompileProperties
           "-tr .propp=com.sun.tools.javac.smart.CompileProperties,java.util.ListResourceBundle
           "-tr .proppp=com.sun.tools.javac.smart.CompileProperties,sun.util.resources.LocaleNamesBundle

        ** Control which classes in the src,sourcepath and classpath that javac is allowed to see.
           Again, this is necessary to deal with the source code structure of the OpenJDK which is
           intricate (read messy).

           "-i tools.*" to include the tools package and all its subpackages in the build.
           "-x tools.net.aviancarrier.*" to exclude the aviancarrier package and all its sources and subpackages.
           "-x tools.net.drums" to exclude the drums package only, keep its subpackages.
           "-xf tools/net/Bar.java" // Do not compile this file...
           "-xf *Bor.java" // Do not compile Bor.java wherever it is found, BUT do compile ABor.java!
           "-if tools/net/Bor.java" // Only compile this file...odd, but sometimes used.

        ** The smart javac wrapper is driven by the modification time on the source files and compared
           to the modification times written into the javac_state file.

           It does not compare the modification time of the source with the modification time of the artifact.
           However it will detect if the modification time of an artifact has changed compared to the java_state,
           and this will trigger a delete of the artifact and a subsequent recompile of the source.

           The smart javac wrapper is not a generic makefile/ant system. Its purpose is to compile java source
           as the final step before the output dir is finalized and immediately jared, or jmodded. The output
           dir should be considered opaque. Do not write into the outputdir yourself!
           Any artifacts found in the outputdir that javac_state does not know of, will be deleted!
           This can however be prevented, using the switch --permit-unidentified-artifacts
           This switch is necessary when build the OpenJDK because its makefiles still write directly to
           the output classes dirs.

           Any makefile/ant rules that want to put contents into the outputdir should put the content
           in one of several source roots. Static content that is under version control, can be put in the same source
           code tree as the Java sources. Dynamic content that is generated by make/ant on the fly, should
           be put in a separate gensrc_stuff root. The smart javac wrapper call will then take the arguments:
           "gensrc_stuff src -d bin"

        The command line:
        java -cp tools.jar com.sun.tools.sjavac.Main \
             -i "com.bar.*" -x "com.bar.foo.*" \
             first_root \
             -i "com.bar.foo.*" \
             second_root \
             -x "org.net.*" \
             -sourcepath link_root_sources \
             -classpath link_root_classes \
             -d bin

        Will compile all sources for package com.bar and its subpackages, found below first_root,
        except the package com.bar.foo (and its subpackages), for which the sources are picked
        from second_root instead. It will link against classes in link_root_classes and against
        sources in link_root_sources, but will not see (try to link against) sources matching org.net.*
        but will link against org.net* classes (if they exist) in link_root_classes.

        (If you want a set of complex filter rules to be applied to several source directories, without
         having to repeat the the filter rules for each root. You can use the explicit -src option. For example:
         sjavac -x "com.foo.*" -src root1:root2:root3  )

        The resulting classes are written into bin.
    */

    private JavacState javac_state;

    public static void main(String... args)  {
        if (args.length > 0 && args[0].startsWith("--startserver:")) {
            if (args.length>1) {
                Log.error("When spawning a background server, only a single --startserver argument is allowed.");
                return;
            }
            // Spawn a background server.
            int rc = JavacServer.startServer(args[0], System.err);
            System.exit(rc);
        }
        Main main = new Main();
        int rc = main.go(args, System.out, System.err);
        // Remove the portfile, but only if this background=false was used.
        JavacServer.cleanup(args);
        System.exit(rc);
    }

    private void printHelp() {
        System.out.println("Usage: sjavac <options>\n"+
                           "where required options are:\n"+
                           "dir                        Compile all sources in dir recursively\n"+
                           "-d dir                     Store generated classes here and the javac_state file\n"+
                           "--server:portfile=/tmp/abc Use a background sjavac server\n\n"+
                           "All other arguments as javac, except -implicit:none which is forced by default.\n"+
                           "No java source files can be supplied on the command line, nor can an @file be supplied.\n\n"+
                           "Warning!\n"+
                           "This tool might disappear at any time, and its command line options might change at any time!");
    }

    public int go(String[] args, PrintStream out, PrintStream err) {

        Log.initializeLog(out, err);

        Options options;
        try {
            options = Options.parseArgs(args);
        } catch (IllegalArgumentException e) {
            Log.error(e.getMessage());
            return -1;
        }

        Log.setLogLevel(options.getLogLevel());

        if (!validateOptions(options))
            return -1;

        if (!createIfMissing(options.getDestDir()))
            return -1;

        Path gensrc = options.getGenSrcDir();
        if (gensrc != null && !createIfMissing(gensrc))
            return -1;

        Path hdrdir = options.getHeaderDir();
        if (hdrdir != null && !createIfMissing(hdrdir))
            return -1;

        // Load the prev build state database.
        javac_state = JavacState.load(options, out, err);

        // Setup the suffix rules from the command line.
        Map<String, Transformer> suffixRules = new HashMap<>();

        // Handling of .java-compilation
        suffixRules.putAll(javac_state.getJavaSuffixRule());

        // Handling of -copy and -tr
        suffixRules.putAll(options.getTranslationRules());

        // All found modules are put here.
        Map<String,Module> modules = new HashMap<>();
        // We start out in the legacy empty no-name module.
        // As soon as we stumble on a module-info.java file we change to that module.
        Module current_module = new Module("", "");
        modules.put("", current_module);

        // Find all sources, use the suffix rules to know which files are sources.
        Map<String,Source> sources = new HashMap<>();

        // Find the files, this will automatically populate the found modules
        // with found packages where the sources are found!
        findSourceFiles(options.getSources(),
                        suffixRules.keySet(),
                        sources,
                        modules,
                        current_module,
                        options.isDefaultPackagePermitted(),
                        false);

        if (sources.isEmpty()) {
            Log.error("Found nothing to compile!");
            return -1;
        }

        // Create a map of all source files that are available for linking. Both -src and
        // -sourcepath point to such files. It is possible to specify multiple
        // -sourcepath options to enable different filtering rules. If the
        // filters are the same for multiple sourcepaths, they may be concatenated
        // using :(;). Before sending the list of sourcepaths to javac, they are
        // all concatenated. The list created here is used by the SmartFileWrapper to
        // make sure only the correct sources are actually available.
        // We might find more modules here as well.
        Map<String,Source> sources_to_link_to = new HashMap<>();

        List<SourceLocation> sourceResolutionLocations = new ArrayList<>();
        sourceResolutionLocations.addAll(options.getSources());
        sourceResolutionLocations.addAll(options.getSourceSearchPaths());
        findSourceFiles(sourceResolutionLocations,
                        Collections.singleton(".java"),
                        sources_to_link_to,
                        modules,
                        current_module,
                        options.isDefaultPackagePermitted(),
                        true);

        // Find all class files allowable for linking.
        // And pickup knowledge of all modules found here.
        // This cannot currently filter classes inside jar files.
//      Map<String,Source> classes_to_link_to = new HashMap<String,Source>();
//      findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true);

        // Find all module sources allowable for linking.
//      Map<String,Source> modules_to_link_to = new HashMap<String,Source>();
//      findFiles(args, "-modulepath", Util.set(".class"), modules_to_link_to, modules, current_module, true);

        // Add the set of sources to the build database.
        javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
        javac_state.now().checkInternalState("checking sources", false, sources);
        javac_state.now().checkInternalState("checking linked sources", true, sources_to_link_to);
        javac_state.setVisibleSources(sources_to_link_to);

        // If there is any change in the source files, taint packages
        // and mark the database in need of saving.
        javac_state.checkSourceStatus(false);

        // Find all existing artifacts. Their timestamp will match the last modified timestamps stored
        // in javac_state, simply because loading of the JavacState will clean out all artifacts
        // that do not match the javac_state database.
        javac_state.findAllArtifacts();

        // Remove unidentified artifacts from the bin, gensrc and header dirs.
        // (Unless we allow them to be there.)
        // I.e. artifacts that are not known according to the build database (javac_state).
        // For examples, files that have been manually copied into these dirs.
        // Artifacts with bad timestamps (ie the on disk timestamp does not match the timestamp
        // in javac_state) have already been removed when the javac_state was loaded.
        if (!options.isUnidentifiedArtifactPermitted()) {
            javac_state.removeUnidentifiedArtifacts();
        }
        // Go through all sources and taint all packages that miss artifacts.
        javac_state.taintPackagesThatMissArtifacts();

        // Now clean out all known artifacts belonging to tainted packages.
        javac_state.deleteClassArtifactsInTaintedPackages();
        // Copy files, for example property files, images files, xml files etc etc.
        javac_state.performCopying(Util.pathToFile(options.getDestDir()), suffixRules);
        // Translate files, for example compile properties or compile idls.
        javac_state.performTranslation(Util.pathToFile(gensrc), suffixRules);
        // Add any potentially generated java sources to the tobe compiled list.
        // (Generated sources must always have a package.)
        Map<String,Source> generated_sources = new HashMap<>();

        try {

            Source.scanRoot(Util.pathToFile(options.getGenSrcDir()), Util.set(".java"), null, null, null, null,
                    generated_sources, modules, current_module, false, true, false);
            javac_state.now().flattenPackagesSourcesAndArtifacts(modules);
            // Recheck the the source files and their timestamps again.
            javac_state.checkSourceStatus(true);

            // Now do a safety check that the list of source files is identical
            // to the list Make believes we are compiling. If we do not get this
            // right, then incremental builds will fail with subtility.
            // If any difference is detected, then we will fail hard here.
            // This is an important safety net.
            javac_state.compareWithMakefileList(Util.pathToFile(options.getSourceReferenceList()));

            // Do the compilations, repeatedly until no tainted packages exist.
            boolean again;
            // Collect the name of all compiled packages.
            Set<String> recently_compiled = new HashSet<>();
            boolean[] rc = new boolean[1];
            do {
                // Clean out artifacts in tainted packages.
                javac_state.deleteClassArtifactsInTaintedPackages();
                // Create a JavacService to delegate the actual compilation to.
                // Currently sjavac always connects to a server through a socket
                // regardless if sjavac runs as a background service or not.
                // This will most likely change in the future.
                JavacService javacService = new JavacServiceClient(options.getServerConf());
                again = javac_state.performJavaCompilations(javacService, options, recently_compiled, rc);
                if (!rc[0]) break;
            } while (again);
            // Only update the state if the compile went well.
            if (rc[0]) {
                javac_state.save();
                // Reflatten only the artifacts.
                javac_state.now().flattenArtifacts(modules);
                // Remove artifacts that were generated during the last compile, but not this one.
                javac_state.removeSuperfluousArtifacts(recently_compiled);
            }
            return rc[0] ? 0 : -1;
        } catch (ProblemException e) {
            Log.error(e.getMessage());
            return -1;
        } catch (Exception e) {
            e.printStackTrace(err);
            return -1;
        }
    }

    private static boolean validateOptions(Options options) {

        String err = null;

        if (options.getDestDir() == null) {
            err = "Please specify output directory.";
        } else if (options.isJavaFilesAmongJavacArgs()) {
            err = "Sjavac does not handle explicit compilation of single .java files.";
        } else if (options.isAtFilePresent()) {
            err = "Sjavac does not handle @-files.";
        } else if (options.getServerConf() == null) {
            err = "No server configuration provided.";
        } else if (!options.getImplicitPolicy().equals("none")) {
            err = "The only allowed setting for sjavac is -implicit:none";
        } else if (options.getSources().isEmpty()) {
            err = "You have to specify -src.";
        } else if (options.getTranslationRules().size() > 1
                && options.getGenSrcDir() == null) {
            err = "You have translators but no gensrc dir (-s) specified!";
        }

        if (err != null)
            Log.error(err);

        return err == null;

    }

    private static boolean createIfMissing(Path dir) {

        if (Files.isDirectory(dir))
            return true;

        if (Files.exists(dir)) {
            Log.error(dir + " is not a directory.");
            return false;
        }

        try {
            Files.createDirectories(dir);
        } catch (IOException e) {
            Log.error("Could not create directory: " + e.getMessage());
            return false;
        }

        return true;
    }


    /** Find source files in the given source locations. */
    public static void findSourceFiles(List<SourceLocation> sourceLocations,
                                       Set<String> sourceTypes,
                                       Map<String,Source> foundFiles,
                                       Map<String, Module> foundModules,
                                       Module currentModule,
                                       boolean permitSourcesInDefaultPackage,
                                       boolean inLinksrc) {

        for (SourceLocation source : sourceLocations) {
            source.findSourceFiles(sourceTypes,
                                   foundFiles,
                                   foundModules,
                                   currentModule,
                                   permitSourcesInDefaultPackage,
                                   inLinksrc);
        }
    }
}
