# HG changeset patch # User alundblad # Date 1440508481 -7200 # Node ID adba44f6b471d10afbb898b4cd03f21d0aab9ff8 # Parent 24d08e405e5b887dfc3069fecc610c04c7b565a1 8048318: Refactor sjavac as a thin client Summary: Moved compilation logic from client to server. Reviewed-by: jlahoda diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CleanProperties.java Tue Aug 25 15:14:41 2015 +0200 @@ -42,9 +42,9 @@ import java.util.Properties; import java.util.Set; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.Sjavac; /** * The clean properties transform should not be necessary. @@ -64,7 +64,7 @@ // Any extra information is ignored for clean properties. } - public boolean transform(Sjavac sjavac, + public boolean transform(CompilationService sjavac, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileJavaPackages.java Tue Aug 25 15:14:41 2015 +0200 @@ -32,12 +32,13 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Random; import java.util.Set; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.CompilationResult; -import com.sun.tools.sjavac.server.Sjavac; +import com.sun.tools.sjavac.server.CompilationSubResult; import com.sun.tools.sjavac.server.SysInfo; /** @@ -68,7 +69,7 @@ args = a; } - public boolean transform(final Sjavac sjavac, + public boolean transform(final CompilationService sjavac, Map> pkgSrcs, final Set visibleSources, final Map> visibleClasses, @@ -91,16 +92,11 @@ boolean concurrentCompiles = true; // Fetch the id. - final String id = Util.extractStringOption("id", sjavac.serverSettings()); + final String id = String.valueOf(new Random().nextInt()); // Only keep portfile and sjavac settings.. //String psServerSettings = Util.cleanSubOptions(Util.set("portfile","sjavac","background","keepalive"), sjavac.serverSettings()); - // Get maximum heap size from the server! SysInfo sysinfo = sjavac.getSysInfo(); - if (sysinfo == null) { - Log.error("Could not query server for sysinfo!"); - return false; - } int numMBytes = (int)(sysinfo.maxMemory / ((long)(1024*1024))); Log.debug("Server reports "+numMBytes+"MiB of memory and "+sysinfo.numCores+" cores"); @@ -205,7 +201,7 @@ } // The return values for each chunked compile. - final CompilationResult[] rn = new CompilationResult[numCompiles]; + final CompilationSubResult[] rn = new CompilationSubResult[numCompiles]; // The requets, might or might not run as a background thread. final Thread[] requests = new Thread[numCompiles]; diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CompileProperties.java Tue Aug 25 15:14:41 2015 +0200 @@ -44,9 +44,9 @@ import java.util.Properties; import java.util.Set; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.Sjavac; /** * Compile properties transform a properties file into a Java source file. @@ -71,7 +71,7 @@ public void setExtra(Options a) { } - public boolean transform(Sjavac sjavac, + public boolean transform(CompilationService compilationService, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/CopyFile.java Tue Aug 25 15:14:41 2015 +0200 @@ -37,9 +37,9 @@ import java.util.Map; import java.util.Set; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.Sjavac; /** * The copy file transform simply copies a matching file from -src to -d . @@ -58,7 +58,7 @@ public void setExtra(Options a) { } - public boolean transform(Sjavac sjavac, + public boolean transform(CompilationService compilationService, Map> pkgSrcs, Set visibleSrcs, Map> visibleClasses, diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java Tue Aug 25 15:14:41 2015 +0200 @@ -45,9 +45,9 @@ import java.util.Set; import java.util.stream.Collectors; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.Sjavac; /** * The javac state class maintains the previous (prev) and the current (now) @@ -748,7 +748,7 @@ /** * Compile all the java sources. Return true, if it needs to be called again! */ - public boolean performJavaCompilations(Sjavac sjavac, + public boolean performJavaCompilations(CompilationService sjavac, Options args, Set recentlyCompiled, boolean[] rcValue) { @@ -790,7 +790,7 @@ * For all packages, find all sources belonging to the package, group the sources * based on their transformers and apply the transformers on each source code group. */ - private boolean perform(Sjavac sjavac, + private boolean perform(CompilationService sjavac, File outputDir, Map suffixRules) { boolean rc = true; diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/Transformer.java Tue Aug 25 15:14:41 2015 +0200 @@ -30,9 +30,9 @@ import java.util.Map; import java.util.Set; +import com.sun.tools.sjavac.comp.CompilationService; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.pubapi.PubApi; -import com.sun.tools.sjavac.server.Sjavac; /** * The transform interface is used to transform content inside a package, from one form to another. @@ -83,7 +83,7 @@ * If num_cores is set to a non-zero value. The transform should attempt to use no more than these * number of threads for heavy work. */ - boolean transform(Sjavac sjavac, + boolean transform(CompilationService sjavac, Map> pkgSrcs, Set visibleSources, Map> visibleClasses, diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/ClientMain.java Tue Aug 25 15:14:41 2015 +0200 @@ -25,29 +25,13 @@ package com.sun.tools.sjavac.client; -import java.io.IOException; import java.io.PrintStream; -import java.nio.file.Files; -import java.nio.file.Path; -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 com.sun.tools.sjavac.JavacState; import com.sun.tools.sjavac.Log; -import com.sun.tools.sjavac.Module; -import com.sun.tools.sjavac.ProblemException; -import com.sun.tools.sjavac.Source; -import com.sun.tools.sjavac.Transformer; import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.comp.SjavacImpl; import com.sun.tools.sjavac.options.Options; -import com.sun.tools.sjavac.options.SourceLocation; +import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.Sjavac; /** @@ -74,282 +58,34 @@ return -1; } - Log.setLogLevel(options.getLogLevel()); - - if (!validateOptions(options)) - return -1; - - if (!createIfMissing(options.getDestDir())) - return -1; - - if (!createIfMissing(options.getStateDir())) - return -1; - - Path gensrc = options.getGenSrcDir(); - if (gensrc != null && !createIfMissing(gensrc)) - return -1; - - Path hdrdir = options.getHeaderDir(); - if (hdrdir != null && !createIfMissing(hdrdir)) - return -1; - Log.debug("=========================================================="); Log.debug("Launching sjavac client with the following parameters:"); Log.debug(" " + options.getStateArgsString()); Log.debug("=========================================================="); - // Load the prev build state database. - JavacState javac_state = JavacState.load(options, out, err); - - // Setup the suffix rules from the command line. - Map 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 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 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; + // Prepare sjavac object + boolean background = Util.extractBooleanOption("background", options.getServerConf(), true); + Sjavac sjavac; + // Create an sjavac implementation to be used for compilation + if (background) { + try { + sjavac = new SjavacClient(options); + } catch (PortFileInaccessibleException e) { + Log.error("Port file inaccessible."); + return -1; + } + } else { + sjavac = new SjavacImpl(); } - // 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 sources_to_link_to = new HashMap<>(); - - List 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 classes_to_link_to = new HashMap(); -// findFiles(args, "-classpath", Util.set(".class"), classes_to_link_to, modules, current_module, true); - - // Find all module sources allowable for linking. -// Map modules_to_link_to = new HashMap(); -// 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); - - int round = 0; - printRound(round); - - // 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(); + CompilationResult cr = sjavac.compile(args); - // 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.areUnidentifiedArtifactsPermitted()) { - javac_state.removeUnidentifiedArtifacts(); - } - // Go through all sources and taint all packages that miss artifacts. - javac_state.taintPackagesThatMissArtifacts(); - - // Check recorded classpath public apis. Taint packages that depend on - // classpath classes whose public apis have changed. - javac_state.taintPackagesDependingOnChangedClasspathPackages(); - - // 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 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 recently_compiled = new HashSet<>(); - boolean[] rc = new boolean[1]; - boolean background = Util.extractBooleanOption("background", options.getServerConf(), true); - Sjavac sjavac; - // Create an sjavac implementation to be used for compilation - if (background) { - sjavac = new SjavacClient(options); - } else { - int poolsize = Util.extractIntOption("poolsize", options.getServerConf()); - if (poolsize <= 0) - poolsize = Runtime.getRuntime().availableProcessors(); - sjavac = new PooledSjavac(new SjavacImpl(), poolsize); - } + out.print(cr.stdout); + err.print(cr.stderr); - do { - if (round > 0) - printRound(round); - // Clean out artifacts in tainted packages. - javac_state.deleteClassArtifactsInTaintedPackages(); - again = javac_state.performJavaCompilations(sjavac, options, recently_compiled, rc); - if (!rc[0]) { - Log.debug("Compilation failed."); - break; - } - if (!again) { - Log.debug("Nothing left to do."); - } - round++; - } while (again); - Log.debug("No need to do another round."); - - // 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); - } - if (!background) - sjavac.shutdown(); - - 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 (!background) + sjavac.shutdown(); - 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.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; - + return cr.returnCode; } - - 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 sourceLocations, - Set sourceTypes, - Map foundFiles, - Map foundModules, - Module currentModule, - boolean permitSourcesInDefaultPackage, - boolean inLinksrc) { - - for (SourceLocation source : sourceLocations) { - source.findSourceFiles(sourceTypes, - foundFiles, - foundModules, - currentModule, - permitSourcesInDefaultPackage, - inLinksrc); - } - } - - private static void printRound(int round) { - Log.debug("****************************************"); - Log.debug("* Round " + round + " *"); - Log.debug("****************************************"); - } - } diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/PortFileInaccessibleException.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/PortFileInaccessibleException.java Tue Aug 25 15:14:41 2015 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015, 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.client; + +import java.io.IOException; + +public class PortFileInaccessibleException extends IOException { + + private static final long serialVersionUID = -4755261881545398973L; + + public PortFileInaccessibleException(Throwable cause) { + super(cause); + } +} diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/client/SjavacClient.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -26,32 +26,27 @@ package com.sun.tools.sjavac.client; import java.io.File; -import java.io.FileNotFoundException; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintStream; -import java.io.PrintWriter; -import java.io.StringWriter; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; -import java.net.URI; import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Scanner; -import java.util.Set; import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.Util; import com.sun.tools.sjavac.options.OptionHelper; import com.sun.tools.sjavac.options.Options; +import com.sun.tools.sjavac.server.CompilationSubResult; import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.PortFile; import com.sun.tools.sjavac.server.Sjavac; import com.sun.tools.sjavac.server.SjavacServer; -import com.sun.tools.sjavac.server.SysInfo; /** * Sjavac implementation that delegates requests to a SjavacServer. @@ -89,9 +84,7 @@ // Store the server conf settings here. private final String settings; - // This constructor should not throw FileNotFoundException (to be resolved - // in JDK-8060030) - public SjavacClient(Options options) throws FileNotFoundException { + public SjavacClient(Options options) throws PortFileInaccessibleException { String tmpServerConf = options.getServerConf(); String serverConf = (tmpServerConf!=null)? tmpServerConf : ""; String tmpId = Util.extractStringOption("id", serverConf); @@ -103,8 +96,7 @@ String portfileName = Util.extractStringOption("portfile", serverConf, defaultPortfile); try { portFile = SjavacServer.getPortFile(portfileName); - } catch (FileNotFoundException e) { - // Reached for instance if directory of port file does not exist + } catch (PortFileInaccessibleException e) { Log.error("Port file inaccessable: " + e); throw e; } @@ -126,40 +118,8 @@ return settings; } - /** - * Make a request to the server only to get the maximum possible heap size to use for compilations. - */ @Override - public SysInfo getSysInfo() { - try (Socket socket = tryConnect()) { - // The ObjectInputStream constructor will block until the - // corresponding ObjectOutputStream has written and flushed the - // header, so it is important that the ObjectOutputStreams on server - // and client are opened before the ObjectInputStreams. - ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream()); - ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); - oos.writeObject(id); - oos.writeObject(SjavacServer.CMD_SYS_INFO); - oos.flush(); - return (SysInfo) ois.readObject(); - } catch (IOException | ClassNotFoundException ex) { - Log.error("[CLIENT] Exception caught: " + ex); - Log.debug(Util.getStackTrace(ex)); - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); // Restore interrupt - Log.error("[CLIENT] getSysInfo interrupted."); - Log.debug(Util.getStackTrace(ie)); - } - return null; - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { + public CompilationResult compile(String[] args) { CompilationResult result; try (Socket socket = tryConnect()) { // The ObjectInputStream constructor will block until the @@ -170,22 +130,17 @@ ObjectInputStream ois = new ObjectInputStream(socket.getInputStream()); oos.writeObject(id); oos.writeObject(SjavacServer.CMD_COMPILE); - oos.writeObject(protocolId); - oos.writeObject(invocationId); oos.writeObject(args); - oos.writeObject(explicitSources); - oos.writeObject(sourcesToCompile); - oos.writeObject(visibleSources); oos.flush(); result = (CompilationResult) ois.readObject(); } catch (IOException | ClassNotFoundException ex) { Log.error("[CLIENT] Exception caught: " + ex); - result = new CompilationResult(CompilationResult.ERROR_FATAL); + result = new CompilationResult(CompilationSubResult.ERROR_FATAL); result.stderr = Util.getStackTrace(ex); } catch (InterruptedException ie) { Thread.currentThread().interrupt(); // Restore interrupt Log.error("[CLIENT] compile interrupted."); - result = new CompilationResult(CompilationResult.ERROR_FATAL); + result = new CompilationResult(CompilationSubResult.ERROR_FATAL); result.stderr = Util.getStackTrace(ie); } return result; diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/CompilationService.java Tue Aug 25 15:14:41 2015 +0200 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015, 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.comp; + +import java.io.File; +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.URI; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.StandardLocation; +import javax.tools.ToolProvider; + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.api.JavacTool; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Dependencies; +import com.sun.tools.javac.util.ListBuffer; +import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.comp.dependencies.NewDependencyCollector; +import com.sun.tools.sjavac.comp.dependencies.PublicApiCollector; +import com.sun.tools.sjavac.server.CompilationSubResult; +import com.sun.tools.sjavac.server.SysInfo; + +/** + *

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. + */ +public class CompilationService { + + public SysInfo getSysInfo() { + return new SysInfo(Runtime.getRuntime().availableProcessors(), + Runtime.getRuntime().maxMemory()); + } + + public CompilationSubResult compile(String protocolId, + String invocationId, + String[] args, + List explicitSources, + Set sourcesToCompile, + Set visibleSources) { + + JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler(); + try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { + SmartFileManager sfm = new SmartFileManager(fm); + Context context = new Context(); + + Dependencies.GraphDependencies.preRegister(context); + + // Now setup the actual compilation + CompilationSubResult compilationResult = new CompilationSubResult(0); + + // First deal with explicit source files on cmdline and in at file + ListBuffer explicitJFOs = new ListBuffer<>(); + for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(explicitSources)) { + explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); + } + // Now deal with sources supplied as source_to_compile + ListBuffer sourcesToCompileFiles = new ListBuffer<>(); + for (URI u : sourcesToCompile) + sourcesToCompileFiles.append(new File(u)); + + for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) + explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); + + // Create a new logger + StringWriter stdoutLog = new StringWriter(); + StringWriter stderrLog = new StringWriter(); + PrintWriter stdout = new PrintWriter(stdoutLog); + PrintWriter stderr = new PrintWriter(stderrLog); + com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; + PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); + PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); + NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs); + try { + if (explicitJFOs.size() > 0) { + sfm.setVisibleSources(visibleSources); + sfm.cleanArtifacts(); + sfm.setLog(stdout); + + // Do the compilation! + JavacTaskImpl task = + (JavacTaskImpl) compiler.getTask(stderr, + sfm, + null, + Arrays.asList(args), + null, + explicitJFOs, + context); + sfm.setSymbolFileEnabled(!com.sun.tools.javac.util.Options.instance(context).isSet("ignore.symbol.file")); + task.addTaskListener(depsCollector); + task.addTaskListener(pubApiCollector); + task.addTaskListener(papVerifier); + logJavacInvocation(args); + rc = task.doCall(); + Log.debug("javac returned with code " + rc); + sfm.flush(); + } + } catch (Exception e) { + Log.error(Util.getStackTrace(e)); + stderrLog.append(Util.getStackTrace(e)); + rc = com.sun.tools.javac.main.Main.Result.ERROR; + } + + compilationResult.packageArtifacts = sfm.getPackageArtifacts(); + + if (papVerifier.errorsDiscovered()) + rc = com.sun.tools.javac.main.Main.Result.ERROR; + + compilationResult.packageDependencies = depsCollector.getDependencies(false); + compilationResult.packageCpDependencies = depsCollector.getDependencies(true); + + compilationResult.packagePubapis = pubApiCollector.getPubApis(true); + compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); + compilationResult.stdout = stdoutLog.toString(); + compilationResult.stderr = stderrLog.toString(); + compilationResult.returnCode = rc.exitCode; + + return compilationResult; + } catch (IOException e) { + throw new Error(e); + } + } + + private void logJavacInvocation(String[] args) { + Log.debug("Invoking javac with args"); + Iterator argIter = Arrays.asList(args).iterator(); + while (argIter.hasNext()) { + String arg = argIter.next(); + String line = " " + arg; + if (arg.matches("\\-(d|cp|classpath|sourcepath|source|target)") + && argIter.hasNext()) { + line += " " + argIter.next(); + } + Log.debug(line); + } + } + +} diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/PooledSjavac.java Tue Aug 25 15:14:41 2015 +0200 @@ -24,11 +24,7 @@ */ package com.sun.tools.sjavac.comp; -import java.io.File; -import java.net.URI; -import java.util.List; import java.util.Objects; -import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @@ -36,7 +32,6 @@ import com.sun.tools.sjavac.Log; import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.Sjavac; -import com.sun.tools.sjavac.server.SysInfo; /** * An sjavac implementation that limits the number of concurrent calls by @@ -59,30 +54,10 @@ } @Override - public SysInfo getSysInfo() { - try { - return pool.submit(() -> delegate.getSysInfo()).get(); - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException("Error during getSysInfo", e); - } - } - - @Override - public CompilationResult compile(final String protocolId, - final String invocationId, - final String[] args, - final List explicitSources, - final Set sourcesToCompile, - final Set visibleSources) { + public CompilationResult compile(String[] args) { try { return pool.submit(() -> { - return delegate.compile(protocolId, - invocationId, - args, - explicitSources, - sourcesToCompile, - visibleSources); + return delegate.compile(args); }).get(); } catch (Exception e) { e.printStackTrace(); @@ -112,8 +87,4 @@ delegate.shutdown(); } - @Override - public String serverSettings() { - return delegate.serverSettings(); - } } diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/comp/SjavacImpl.java Tue Aug 25 15:14:41 2015 +0200 @@ -24,34 +24,33 @@ */ package com.sun.tools.sjavac.comp; -import java.io.File; +import static com.sun.tools.sjavac.server.CompilationResult.ERROR_FATAL; +import static java.nio.charset.StandardCharsets.UTF_8; + +import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.net.URI; -import java.util.Arrays; -import java.util.Iterator; +import java.io.PrintStream; +import java.nio.file.Files; +import java.nio.file.Path; +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 javax.tools.JavaFileObject; -import javax.tools.StandardJavaFileManager; -import javax.tools.StandardLocation; -import javax.tools.ToolProvider; - -import com.sun.tools.javac.api.JavacTaskImpl; -import com.sun.tools.javac.api.JavacTool; -import com.sun.tools.javac.util.Context; -import com.sun.tools.javac.util.Dependencies; -import com.sun.tools.javac.util.ListBuffer; -import com.sun.tools.javac.util.Options; +import com.sun.tools.sjavac.JavacState; import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.Module; +import com.sun.tools.sjavac.ProblemException; +import com.sun.tools.sjavac.Source; +import com.sun.tools.sjavac.Transformer; import com.sun.tools.sjavac.Util; -import com.sun.tools.sjavac.comp.dependencies.NewDependencyCollector; -import com.sun.tools.sjavac.comp.dependencies.PublicApiCollector; +import com.sun.tools.sjavac.options.Options; +import com.sun.tools.sjavac.options.SourceLocation; import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.Sjavac; -import com.sun.tools.sjavac.server.SysInfo; /** * The sjavac implementation that interacts with javac and performs the actual @@ -65,123 +64,282 @@ public class SjavacImpl implements Sjavac { @Override - public SysInfo getSysInfo() { - return new SysInfo(Runtime.getRuntime().availableProcessors(), - Runtime.getRuntime().maxMemory()); - } + public CompilationResult compile(String[] args) { + + ByteArrayOutputStream outBaos = new ByteArrayOutputStream(); + ByteArrayOutputStream errBaos = new ByteArrayOutputStream(); + PrintStream out = new PrintStream(outBaos); + PrintStream err = new PrintStream(errBaos); + + Options options; + try { + options = Options.parseArgs(args); + } catch (IllegalArgumentException e) { + Log.error(e.getMessage()); + return new CompilationResult(ERROR_FATAL); + } + + Log.setLogLevel(options.getLogLevel()); + + if (!validateOptions(options)) + return new CompilationResult(ERROR_FATAL); - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { + if (!createIfMissing(options.getDestDir())) + return new CompilationResult(ERROR_FATAL); + + if (!createIfMissing(options.getStateDir())) + return new CompilationResult(ERROR_FATAL); + + Path gensrc = options.getGenSrcDir(); + if (gensrc != null && !createIfMissing(gensrc)) + return new CompilationResult(ERROR_FATAL); - JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler(); - try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) { - SmartFileManager sfm = new SmartFileManager(fm); - Context context = new Context(); + Path hdrdir = options.getHeaderDir(); + if (hdrdir != null && !createIfMissing(hdrdir)) + return new CompilationResult(ERROR_FATAL); + + // Load the prev build state database. + JavacState javac_state = JavacState.load(options, out, err); + + // Setup the suffix rules from the command line. + Map suffixRules = new HashMap<>(); - Dependencies.GraphDependencies.preRegister(context); + // Handling of .java-compilation + suffixRules.putAll(javac_state.getJavaSuffixRule()); + + // Handling of -copy and -tr + suffixRules.putAll(options.getTranslationRules()); - // Now setup the actual compilation - CompilationResult compilationResult = new CompilationResult(0); + // All found modules are put here. + Map 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 sources = new HashMap<>(); - // First deal with explicit source files on cmdline and in at file - ListBuffer explicitJFOs = new ListBuffer<>(); - for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(explicitSources)) { - explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); - } - // Now deal with sources supplied as source_to_compile - ListBuffer sourcesToCompileFiles = new ListBuffer<>(); - for (URI u : sourcesToCompile) - sourcesToCompileFiles.append(new File(u)); + // 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); - for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles)) - explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH)); + if (sources.isEmpty()) { + Log.error("Found nothing to compile!"); + return new CompilationResult(CompilationResult.ERROR_FATAL, + new String(outBaos.toByteArray(), UTF_8), + new String(errBaos.toByteArray(), UTF_8)); + } + + + // 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 sources_to_link_to = new HashMap<>(); - // Create a new logger - StringWriter stdoutLog = new StringWriter(); - StringWriter stderrLog = new StringWriter(); - PrintWriter stdout = new PrintWriter(stdoutLog); - PrintWriter stderr = new PrintWriter(stderrLog); - com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK; - PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs); - PathAndPackageVerifier papVerifier = new PathAndPackageVerifier(); - NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs); - try { - if (explicitJFOs.size() > 0) { - sfm.setVisibleSources(visibleSources); - sfm.cleanArtifacts(); - sfm.setLog(stdout); + List 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); + + // 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); + + int round = 0; + printRound(round); + + // 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.areUnidentifiedArtifactsPermitted()) { + javac_state.removeUnidentifiedArtifacts(); + } + // Go through all sources and taint all packages that miss artifacts. + javac_state.taintPackagesThatMissArtifacts(); + + // Check recorded classpath public apis. Taint packages that depend on + // classpath classes whose public apis have changed. + javac_state.taintPackagesDependingOnChangedClasspathPackages(); - // Do the compilation! - JavacTaskImpl task = - (JavacTaskImpl) compiler.getTask(stderr, - sfm, - null, - Arrays.asList(args), - null, - explicitJFOs, - context); - sfm.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file")); - task.addTaskListener(depsCollector); - task.addTaskListener(pubApiCollector); - task.addTaskListener(papVerifier); - logJavacInvocation(args); - rc = task.doCall(); - Log.debug("javac returned with code " + rc); - sfm.flush(); + // 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 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 recently_compiled = new HashSet<>(); + boolean[] rc = new boolean[1]; + + CompilationService compilationService = new CompilationService(); + do { + if (round > 0) + printRound(round); + // Clean out artifacts in tainted packages. + javac_state.deleteClassArtifactsInTaintedPackages(); + again = javac_state.performJavaCompilations(compilationService, options, recently_compiled, rc); + if (!rc[0]) { + Log.debug("Compilation failed."); + break; } - } catch (Exception e) { - Log.error(Util.getStackTrace(e)); - stderrLog.append(Util.getStackTrace(e)); - rc = com.sun.tools.javac.main.Main.Result.ERROR; + if (!again) { + Log.debug("Nothing left to do."); + } + round++; + } while (again); + Log.debug("No need to do another round."); + + // 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); } - compilationResult.packageArtifacts = sfm.getPackageArtifacts(); - - if (papVerifier.errorsDiscovered()) - rc = com.sun.tools.javac.main.Main.Result.ERROR; - - compilationResult.packageDependencies = depsCollector.getDependencies(false); - compilationResult.packageCpDependencies = depsCollector.getDependencies(true); - - compilationResult.packagePubapis = pubApiCollector.getPubApis(true); // pubApis.getPubapis(explicitJFOs, true); - compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false); // pubApis.getPubapis(explicitJFOs, false); - compilationResult.stdout = stdoutLog.toString(); - compilationResult.stderr = stderrLog.toString(); - compilationResult.returnCode = rc.exitCode; - - return compilationResult; - } catch (IOException e) { - throw new Error(e); + return new CompilationResult(rc[0] ? 0 : ERROR_FATAL, + new String(outBaos.toByteArray(), UTF_8), + new String(errBaos.toByteArray(), UTF_8)); + } catch (ProblemException e) { + Log.error(e.getMessage()); + return new CompilationResult(ERROR_FATAL, + new String(outBaos.toByteArray(), UTF_8), + new String(errBaos.toByteArray(), UTF_8)); + } catch (Exception e) { + e.printStackTrace(err); + return new CompilationResult(ERROR_FATAL, + new String(outBaos.toByteArray(), UTF_8), + new String(errBaos.toByteArray(), UTF_8)); } } @Override public void shutdown() { // Nothing to clean up - // ... maybe we should wait for any current request to finish? } - @Override - public String serverSettings() { - return ""; + 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.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 void logJavacInvocation(String[] args) { - Log.debug("Invoking javac with args"); - Iterator argIter = Arrays.asList(args).iterator(); - while (argIter.hasNext()) { - String arg = argIter.next(); - String line = " " + arg; - if (arg.matches("\\-(d|cp|classpath|sourcepath|source|target)") - && argIter.hasNext()) { - line += " " + argIter.next(); - } - Log.debug(line); + 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 sourceLocations, + Set sourceTypes, + Map foundFiles, + Map foundModules, + Module currentModule, + boolean permitSourcesInDefaultPackage, + boolean inLinksrc) { + + for (SourceLocation source : sourceLocations) { + source.findSourceFiles(sourceTypes, + foundFiles, + foundModules, + currentModule, + permitSourcesInDefaultPackage, + inLinksrc); } } + + private static void printRound(int round) { + Log.debug("****************************************"); + Log.debug("* Round " + round + " *"); + Log.debug("****************************************"); + } } diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationResult.java Tue Aug 25 15:14:41 2015 +0200 @@ -26,15 +26,8 @@ package com.sun.tools.sjavac.server; import java.io.Serializable; -import java.net.URI; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; - -import com.sun.tools.sjavac.pubapi.PubApi; /** - * *

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 @@ -47,17 +40,18 @@ // Return code constants public final static int ERROR_FATAL = -1; + public String stdout; + public String stderr; public int returnCode; - public Map> packageArtifacts = new HashMap<>(); - public Map>> packageDependencies = new HashMap<>(); - public Map>> packageCpDependencies = new HashMap<>(); - public Map packagePubapis = new HashMap<>(); - public Map dependencyPubapis = new HashMap<>(); - public String stdout = ""; - public String stderr = ""; public CompilationResult(int returnCode) { + this(returnCode, "", ""); + } + + public CompilationResult(int returnCode, String stdout, String stderr) { this.returnCode = returnCode; + this.stdout = stdout; + this.stderr = stderr; } public void setReturnCode(int returnCode) { diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/CompilationSubResult.java Tue Aug 25 15:14:41 2015 +0200 @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2014, 2015, 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.server; + +import java.io.Serializable; +import java.net.URI; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import com.sun.tools.sjavac.pubapi.PubApi; + +/** + * + *

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. + */ +public class CompilationSubResult implements Serializable { + + static final long serialVersionUID = 46739181113L; + + // Return code constants + public final static int ERROR_FATAL = -1; + + public int returnCode; + public Map> packageArtifacts = new HashMap<>(); + public Map>> packageDependencies = new HashMap<>(); + public Map>> packageCpDependencies = new HashMap<>(); + public Map packagePubapis = new HashMap<>(); + public Map dependencyPubapis = new HashMap<>(); + public String stdout = ""; + public String stderr = ""; + + public CompilationSubResult(int returnCode) { + this.returnCode = returnCode; + } + + public void setReturnCode(int returnCode) { + this.returnCode = returnCode; + } +} diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/IdleResetSjavac.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -24,10 +24,6 @@ */ package com.sun.tools.sjavac.server; -import java.io.File; -import java.net.URI; -import java.util.List; -import java.util.Set; import java.util.Timer; import java.util.TimerTask; @@ -64,30 +60,10 @@ } @Override - public SysInfo getSysInfo() { + public CompilationResult compile(String[] args) { startCall(); try { - return delegate.getSysInfo(); - } finally { - endCall(); - } - } - - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - startCall(); - try { - return delegate.compile(protocolId, - invocationId, - args, - explicitSources, - sourcesToCompile, - visibleSources); + return delegate.compile(args); } finally { endCall(); } @@ -129,8 +105,4 @@ delegate.shutdown(); } - @Override - public String serverSettings() { - return delegate.serverSettings(); - } } diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/PortFile.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2015, 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 @@ -37,6 +37,7 @@ import com.sun.tools.javac.util.Assert; import com.sun.tools.sjavac.Log; +import com.sun.tools.sjavac.client.PortFileInaccessibleException; /** * The PortFile class mediates access to a short binary file containing the tcp/ip port (for the localhost) @@ -80,11 +81,16 @@ * Create a new portfile. * @param fn is the path to the file. */ - public PortFile(String fn) throws FileNotFoundException { + public PortFile(String fn) throws PortFileInaccessibleException { filename = fn; file = new File(filename); stopFile = new File(filename+".stop"); - rwfile = new RandomAccessFile(file, "rw"); + try { + rwfile = new RandomAccessFile(file, "rw"); + } catch (FileNotFoundException e) { + // Reached if file for instance already exists and is a directory + throw new PortFileInaccessibleException(e); + } // The rwfile should only be readable by the owner of the process // and no other! How do we do that on a RandomAccessFile? channel = rwfile.getChannel(); diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/RequestHandler.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -24,16 +24,12 @@ */ package com.sun.tools.sjavac.server; -import java.io.File; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.PrintWriter; import java.io.StringWriter; import java.net.Socket; -import java.net.URI; -import java.util.List; -import java.util.Set; import com.sun.tools.sjavac.Log; @@ -71,8 +67,7 @@ String cmd = (String) oin.readObject(); Log.info("Handling request, id: " + id + " cmd: " + cmd); switch (cmd) { - case SjavacServer.CMD_SYS_INFO: handleSysInfoRequest(oin, oout); break; - case SjavacServer.CMD_COMPILE: handleCompileRequest(oin, oout); break; + case SjavacServer.CMD_COMPILE: handleCompileRequest(oin, oout); break; default: Log.error("Unknown command: " + cmd); } } catch (Exception ex) { @@ -85,31 +80,15 @@ } } - private void handleSysInfoRequest(ObjectInputStream oin, - ObjectOutputStream oout) throws IOException { - oout.writeObject(sjavac.getSysInfo()); - oout.flush(); - } - - @SuppressWarnings("unchecked") private void handleCompileRequest(ObjectInputStream oin, ObjectOutputStream oout) throws IOException { try { // Read request arguments - String protocolId = (String) oin.readObject(); - String invocationId = (String) oin.readObject(); String[] args = (String[]) oin.readObject(); - List explicitSources = (List) oin.readObject(); - Set sourcesToCompile = (Set) oin.readObject(); - Set visibleSources = (Set) oin.readObject(); // Perform compilation - CompilationResult cr = sjavac.compile(protocolId, - invocationId, - args, - explicitSources, - sourcesToCompile, - visibleSources); + CompilationResult cr = sjavac.compile(args); + // Write request response oout.writeObject(cr); oout.flush(); diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/Sjavac.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, 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 @@ -24,10 +24,6 @@ */ package com.sun.tools.sjavac.server; -import java.io.File; -import java.net.URI; -import java.util.List; -import java.util.Set; /** * Interface of the SjavacImpl, the sjavac client and all wrappers such as @@ -39,16 +35,6 @@ * deletion without notice. */ public interface Sjavac { - - SysInfo getSysInfo(); - - CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources); - + CompilationResult compile(String[] args); void shutdown(); - String serverSettings(); } diff -r 24d08e405e5b -r adba44f6b471 src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java --- a/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Mon Aug 24 13:15:12 2015 +0100 +++ b/src/jdk.compiler/share/classes/com/sun/tools/sjavac/server/SjavacServer.java Tue Aug 25 15:14:41 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2015, 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 @@ -39,6 +39,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import com.sun.tools.sjavac.Util; +import com.sun.tools.sjavac.client.PortFileInaccessibleException; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.comp.SjavacImpl; @@ -54,7 +55,6 @@ // Used in protocol to indicate which method to invoke public final static String CMD_COMPILE = "compile"; - public final static String CMD_SYS_INFO = "sys-info"; final private String portfilename; final private String logfile; @@ -122,7 +122,7 @@ /** * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. */ - public static synchronized PortFile getPortFile(String filename) throws FileNotFoundException { + public static synchronized PortFile getPortFile(String filename) throws PortFileInaccessibleException { if (allPortFiles == null) { allPortFiles = new HashMap<>(); } diff -r 24d08e405e5b -r adba44f6b471 test/tools/sjavac/IdleShutdown.java --- a/test/tools/sjavac/IdleShutdown.java Mon Aug 24 13:15:12 2015 +0100 +++ b/test/tools/sjavac/IdleShutdown.java Tue Aug 25 15:14:41 2015 +0200 @@ -31,17 +31,11 @@ * @build Wrapper * @run main Wrapper IdleShutdown */ -import java.io.File; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import java.util.Set; import java.util.concurrent.atomic.AtomicLong; import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.IdleResetSjavac; import com.sun.tools.sjavac.server.Sjavac; -import com.sun.tools.sjavac.server.SysInfo; import com.sun.tools.sjavac.server.Terminable; @@ -70,35 +64,14 @@ if (timeoutTimestamp.get() != -1) throw new AssertionError("Premature timeout detected."); - // Call various methods and wait less than TIMEOUT_MS in between - Thread.sleep(TIMEOUT_MS - 1000); - log("Getting sys info"); - service.getSysInfo(); - + // Use Sjavac object and wait less than TIMEOUT_MS in between calls Thread.sleep(TIMEOUT_MS - 1000); - log("Getting sys info"); - service.getSysInfo(); - - if (timeoutTimestamp.get() != -1) - throw new AssertionError("Premature timeout detected."); + log("Compiling"); + service.compile(new String[0]); Thread.sleep(TIMEOUT_MS - 1000); log("Compiling"); - service.compile("", - "", - new String[0], - Collections.emptyList(), - Collections.emptySet(), - Collections.emptySet()); - - Thread.sleep(TIMEOUT_MS - 1000); - log("Compiling"); - service.compile("", - "", - new String[0], - Collections.emptyList(), - Collections.emptySet(), - Collections.emptySet()); + service.compile(new String[0]); if (timeoutTimestamp.get() != -1) throw new AssertionError("Premature timeout detected."); @@ -129,7 +102,10 @@ private static class NoopJavacService implements Sjavac { @Override - public SysInfo getSysInfo() { + public void shutdown() { + } + @Override + public CompilationResult compile(String[] args) { // Attempt to trigger idle timeout during a call by sleeping try { Thread.sleep(TIMEOUT_MS + 1000); @@ -137,21 +113,5 @@ } return null; } - @Override - public void shutdown() { - } - @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { - return null; - } - @Override - public String serverSettings() { - return ""; - } } } diff -r 24d08e405e5b -r adba44f6b471 test/tools/sjavac/OptionDecoding.java --- a/test/tools/sjavac/OptionDecoding.java Mon Aug 24 13:15:12 2015 +0100 +++ b/test/tools/sjavac/OptionDecoding.java Tue Aug 25 15:14:41 2015 +0200 @@ -51,10 +51,10 @@ import java.util.Map; import com.sun.tools.sjavac.CopyFile; -import com.sun.tools.sjavac.Main; import com.sun.tools.sjavac.Module; import com.sun.tools.sjavac.Source; import com.sun.tools.sjavac.client.ClientMain; +import com.sun.tools.sjavac.comp.SjavacImpl; import com.sun.tools.sjavac.options.Options; import com.sun.tools.sjavac.options.SourceLocation; @@ -136,7 +136,7 @@ Options options = Options.parseArgs("-if", "root/pkg1/ClassA1.java", "root"); Map foundFiles = new HashMap<>(); - ClientMain.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, + SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, new HashMap(), new Module("", ""), false, true); checkFilesFound(foundFiles.keySet(), a1); @@ -148,7 +148,7 @@ Options options = Options.parseArgs("-i", "pkg1/*", "root"); Map foundFiles = new HashMap<>(); - ClientMain.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, + SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, new HashMap(), new Module("", ""), false, true); checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2); @@ -160,7 +160,7 @@ Options options = Options.parseArgs("-xf", "root/pkg1/ClassA1.java", "root"); Map foundFiles = new HashMap<>(); - ClientMain.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, + SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, new HashMap(), new Module("", ""), false, true); checkFilesFound(foundFiles.keySet(), a2, b1, b2, c1, c2); @@ -171,7 +171,7 @@ Options options = Options.parseArgs("-i", "pkg1/*", "root"); Map foundFiles = new HashMap<>(); - ClientMain.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, + SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, new HashMap(), new Module("", ""), false, true); checkFilesFound(foundFiles.keySet(), a1, a2, b1, b2); @@ -182,7 +182,7 @@ Options options = Options.parseArgs("-i", "pkg1/*", "-x", "pkg1/pkg2/*", "root"); Map foundFiles = new HashMap<>(); - ClientMain.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, + SjavacImpl.findSourceFiles(options.getSources(), Collections.singleton(".java"), foundFiles, new HashMap(), new Module("", ""), false, true); checkFilesFound(foundFiles.keySet(), a1, a2); diff -r 24d08e405e5b -r adba44f6b471 test/tools/sjavac/PooledExecution.java --- a/test/tools/sjavac/PooledExecution.java Mon Aug 24 13:15:12 2015 +0100 +++ b/test/tools/sjavac/PooledExecution.java Tue Aug 25 15:14:41 2015 +0200 @@ -32,18 +32,12 @@ * @build Wrapper * @run main Wrapper PooledExecution */ -import java.io.File; -import java.net.URI; -import java.util.Collections; -import java.util.List; -import java.util.Set; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; import com.sun.tools.sjavac.comp.PooledSjavac; import com.sun.tools.sjavac.server.CompilationResult; import com.sun.tools.sjavac.server.Sjavac; -import com.sun.tools.sjavac.server.SysInfo; public class PooledExecution { @@ -75,12 +69,7 @@ for (int i = 0; i < NUM_REQUESTS; i++) { tasks[i] = new Thread() { public void run() { - service.compile("", - "", - new String[0], - Collections.emptyList(), - Collections.emptySet(), - Collections.emptySet()); + service.compile(new String[0]); tasksFinished.incrementAndGet(); } }; @@ -122,12 +111,7 @@ AtomicInteger activeRequests = new AtomicInteger(0); @Override - public CompilationResult compile(String protocolId, - String invocationId, - String[] args, - List explicitSources, - Set sourcesToCompile, - Set visibleSources) { + public CompilationResult compile(String[] args) { leftToStart.countDown(); int numActiveRequests = activeRequests.incrementAndGet(); System.out.printf("Left to start: %2d / Currently active: %2d%n", @@ -145,18 +129,8 @@ } @Override - public SysInfo getSysInfo() { - return null; - } - - @Override public void shutdown() { } - - @Override - public String serverSettings() { - return ""; - } } } }