langtools/src/jdk.compiler/share/classes/com/sun/tools/sjavac/JavacState.java
changeset 26107 a4a156a33c94
parent 26098 32588700060b
parent 25874 83c19f00452c
child 27225 8369cde9152a
equal deleted inserted replaced
25876:d06a6d3c66c0 26107:a4a156a33c94
    24  */
    24  */
    25 
    25 
    26 package com.sun.tools.sjavac;
    26 package com.sun.tools.sjavac;
    27 
    27 
    28 import java.io.*;
    28 import java.io.*;
    29 import java.nio.file.Path;
       
    30 import java.util.Collections;
    29 import java.util.Collections;
    31 import java.util.Date;
    30 import java.util.Date;
    32 import java.util.Set;
    31 import java.util.Set;
    33 import java.util.HashSet;
    32 import java.util.HashSet;
    34 import java.util.List;
    33 import java.util.List;
    37 import java.text.SimpleDateFormat;
    36 import java.text.SimpleDateFormat;
    38 import java.net.URI;
    37 import java.net.URI;
    39 import java.util.*;
    38 import java.util.*;
    40 
    39 
    41 import com.sun.tools.sjavac.options.Options;
    40 import com.sun.tools.sjavac.options.Options;
    42 import com.sun.tools.sjavac.options.SourceLocation;
    41 import com.sun.tools.sjavac.server.Sjavac;
    43 import com.sun.tools.sjavac.server.JavacService;
       
    44 
    42 
    45 /**
    43 /**
    46  * The javac state class maintains the previous (prev) and the current (now)
    44  * The javac state class maintains the previous (prev) and the current (now)
    47  * build states and everything else that goes into the javac_state file.
    45  * build states and everything else that goes into the javac_state file.
    48  *
    46  *
    49  * <p><b>This is NOT part of any supported API.
    47  *  <p><b>This is NOT part of any supported API.
    50  * If you write code that depends on this, you do so at your own
    48  *  If you write code that depends on this, you do so at your own risk.
    51  * risk.  This code and its internal interfaces are subject to change
    49  *  This code and its internal interfaces are subject to change or
    52  * or deletion without notice.</b></p>
    50  *  deletion without notice.</b>
    53  */
    51  */
    54 public class JavacState
    52 public class JavacState {
    55 {
       
    56     // The arguments to the compile. If not identical, then it cannot
    53     // The arguments to the compile. If not identical, then it cannot
    57     // be an incremental build!
    54     // be an incremental build!
    58     String theArgs;
    55     String theArgs;
    59     // The number of cores limits how many threads are used for heavy concurrent work.
    56     // The number of cores limits how many threads are used for heavy concurrent work.
    60     int numCores;
    57     int numCores;
    61 
    58 
    62     // The bin_dir/javac_state
    59     // The bin_dir/javac_state
    63     private String javacStateFilename;
       
    64     private File javacState;
    60     private File javacState;
    65 
    61 
    66     // The previous build state is loaded from javac_state
    62     // The previous build state is loaded from javac_state
    67     private BuildState prev;
    63     private BuildState prev;
    68     // The current build state is constructed during the build,
    64     // The current build state is constructed during the build,
    97     // Copy over the javac_state for the packages that did not need recompilation,
    93     // Copy over the javac_state for the packages that did not need recompilation,
    98     // verbatim from the previous (prev) to the new (now) build state.
    94     // verbatim from the previous (prev) to the new (now) build state.
    99     private Set<String> recompiledPackages;
    95     private Set<String> recompiledPackages;
   100 
    96 
   101     // The output directories filled with tasty artifacts.
    97     // The output directories filled with tasty artifacts.
   102     private File binDir, gensrcDir, headerDir;
    98     private File binDir, gensrcDir, headerDir, stateDir;
   103 
    99 
   104     // The current status of the file system.
   100     // The current status of the file system.
   105     private Set<File> binArtifacts;
   101     private Set<File> binArtifacts;
   106     private Set<File> gensrcArtifacts;
   102     private Set<File> gensrcArtifacts;
   107     private Set<File> headerArtifacts;
   103     private Set<File> headerArtifacts;
   126     private CompileJavaPackages compileJavaPackages = new CompileJavaPackages();
   122     private CompileJavaPackages compileJavaPackages = new CompileJavaPackages();
   127 
   123 
   128     // Where to send stdout and stderr.
   124     // Where to send stdout and stderr.
   129     private PrintStream out, err;
   125     private PrintStream out, err;
   130 
   126 
   131     JavacState(Options options, boolean removeJavacState, PrintStream o, PrintStream e) {
   127     // Command line options.
       
   128     private Options options;
       
   129 
       
   130     JavacState(Options op, boolean removeJavacState, PrintStream o, PrintStream e) {
       
   131         options = op;
   132         out = o;
   132         out = o;
   133         err = e;
   133         err = e;
   134         numCores = options.getNumCores();
   134         numCores = options.getNumCores();
   135         theArgs = options.getStateArgsString();
   135         theArgs = options.getStateArgsString();
   136         binDir = Util.pathToFile(options.getDestDir());
   136         binDir = Util.pathToFile(options.getDestDir());
   137         gensrcDir = Util.pathToFile(options.getGenSrcDir());
   137         gensrcDir = Util.pathToFile(options.getGenSrcDir());
   138         headerDir = Util.pathToFile(options.getHeaderDir());
   138         headerDir = Util.pathToFile(options.getHeaderDir());
   139         javacStateFilename = binDir.getPath()+File.separator+"javac_state";
   139         stateDir = Util.pathToFile(options.getStateDir());
   140         javacState = new File(javacStateFilename);
   140         javacState = new File(stateDir, "javac_state");
   141         if (removeJavacState && javacState.exists()) {
   141         if (removeJavacState && javacState.exists()) {
   142             javacState.delete();
   142             javacState.delete();
   143         }
   143         }
   144         newJavacState = false;
   144         newJavacState = false;
   145         if (!javacState.exists()) {
   145         if (!javacState.exists()) {
   146             newJavacState = true;
   146             newJavacState = true;
   147             // If there is no javac_state then delete the contents of all the artifact dirs!
   147             // If there is no javac_state then delete the contents of all the artifact dirs!
   148             // We do not want to risk building a broken incremental build.
   148             // We do not want to risk building a broken incremental build.
   149             // BUT since the makefiles still copy things straight into the bin_dir et al,
   149             // BUT since the makefiles still copy things straight into the bin_dir et al,
   150             // we avoid deleting files here, if the option --permit-unidentified-classes was supplied.
   150             // we avoid deleting files here, if the option --permit-unidentified-classes was supplied.
   151             if (!options.isUnidentifiedArtifactPermitted()) {
   151             if (!options.areUnidentifiedArtifactsPermitted()) {
   152                 deleteContents(binDir);
   152                 deleteContents(binDir);
   153                 deleteContents(gensrcDir);
   153                 deleteContents(gensrcDir);
   154                 deleteContents(headerDir);
   154                 deleteContents(headerDir);
   155             }
   155             }
   156             needsSaving = true;
   156             needsSaving = true;
   266     /**
   266     /**
   267      * Save the javac_state file.
   267      * Save the javac_state file.
   268      */
   268      */
   269     public void save() throws IOException {
   269     public void save() throws IOException {
   270         if (!needsSaving) return;
   270         if (!needsSaving) return;
   271         try (FileWriter out = new FileWriter(javacStateFilename)) {
   271         try (FileWriter out = new FileWriter(javacState)) {
   272             StringBuilder b = new StringBuilder();
   272             StringBuilder b = new StringBuilder();
   273             long millisNow = System.currentTimeMillis();
   273             long millisNow = System.currentTimeMillis();
   274             Date d = new Date(millisNow);
   274             Date d = new Date(millisNow);
   275             SimpleDateFormat df =
   275             SimpleDateFormat df =
   276                 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
   276                 new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");
   309         boolean noFileFound = false;
   309         boolean noFileFound = false;
   310         boolean foundCorrectVerNr = false;
   310         boolean foundCorrectVerNr = false;
   311         boolean newCommandLine = false;
   311         boolean newCommandLine = false;
   312         boolean syntaxError = false;
   312         boolean syntaxError = false;
   313 
   313 
   314         try (BufferedReader in = new BufferedReader(new FileReader(db.javacStateFilename))) {
   314         try (BufferedReader in = new BufferedReader(new FileReader(db.javacState))) {
   315             for (;;) {
   315             for (;;) {
   316                 String l = in.readLine();
   316                 String l = in.readLine();
   317                 if (l==null) break;
   317                 if (l==null) break;
   318                 if (l.length()>=3 && l.charAt(1) == ' ') {
   318                 if (l.length()>=3 && l.charAt(1) == ' ') {
   319                     char c = l.charAt(0);
   319                     char c = l.charAt(0);
   510         }
   510         }
   511         // Do not forget about javac_state....
   511         // Do not forget about javac_state....
   512         allKnownArtifacts.add(javacState);
   512         allKnownArtifacts.add(javacState);
   513 
   513 
   514         for (File f : binArtifacts) {
   514         for (File f : binArtifacts) {
   515             if (!allKnownArtifacts.contains(f)) {
   515             if (!allKnownArtifacts.contains(f) &&
       
   516                 !options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) {
   516                 Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state.");
   517                 Log.debug("Removing "+f.getPath()+" since it is unknown to the javac_state.");
   517                 f.delete();
   518                 f.delete();
   518             }
   519             }
   519         }
   520         }
   520         for (File f : headerArtifacts) {
   521         for (File f : headerArtifacts) {
   603     }
   604     }
   604 
   605 
   605     /**
   606     /**
   606      * Recursively delete a directory and all its contents.
   607      * Recursively delete a directory and all its contents.
   607      */
   608      */
   608     private static void deleteContents(File dir) {
   609     private void deleteContents(File dir) {
   609         if (dir != null && dir.exists()) {
   610         if (dir != null && dir.exists()) {
   610             for (File f : dir.listFiles()) {
   611             for (File f : dir.listFiles()) {
   611                 if (f.isDirectory()) {
   612                 if (f.isDirectory()) {
   612                     deleteContents(f);
   613                     deleteContents(f);
   613                 }
   614                 }
   614                 f.delete();
   615                 if (!options.isUnidentifiedArtifactPermitted(f.getAbsolutePath())) {
       
   616                     Log.debug("Removing "+f.getAbsolutePath());
       
   617                     f.delete();
       
   618                 }
   615             }
   619             }
   616         }
   620         }
   617     }
   621     }
   618 
   622 
   619     /**
   623     /**
   646     }
   650     }
   647 
   651 
   648     /**
   652     /**
   649      * Compile all the java sources. Return true, if it needs to be called again!
   653      * Compile all the java sources. Return true, if it needs to be called again!
   650      */
   654      */
   651     public boolean performJavaCompilations(JavacService javacService,
   655     public boolean performJavaCompilations(Sjavac sjavac,
   652                                            Options args,
   656                                            Options args,
   653                                            Set<String> recentlyCompiled,
   657                                            Set<String> recentlyCompiled,
   654                                            boolean[] rcValue) {
   658                                            boolean[] rcValue) {
   655         Map<String,Transformer> suffixRules = new HashMap<>();
   659         Map<String,Transformer> suffixRules = new HashMap<>();
   656         suffixRules.put(".java", compileJavaPackages);
   660         suffixRules.put(".java", compileJavaPackages);
   657         compileJavaPackages.setExtra(args);
   661         compileJavaPackages.setExtra(args);
   658 
   662 
   659         rcValue[0] = perform(javacService, binDir, suffixRules);
   663         rcValue[0] = perform(sjavac, binDir, suffixRules);
   660         recentlyCompiled.addAll(taintedPackages());
   664         recentlyCompiled.addAll(taintedPackages());
   661         clearTaintedPackages();
   665         clearTaintedPackages();
   662         boolean again = !packagesWithChangedPublicApis.isEmpty();
   666         boolean again = !packagesWithChangedPublicApis.isEmpty();
   663         taintPackagesDependingOnChangedPackages(packagesWithChangedPublicApis, recentlyCompiled);
   667         taintPackagesDependingOnChangedPackages(packagesWithChangedPublicApis, recentlyCompiled);
   664         packagesWithChangedPublicApis = new HashSet<>();
   668         packagesWithChangedPublicApis = new HashSet<>();
   684 
   688 
   685     /**
   689     /**
   686      * For all packages, find all sources belonging to the package, group the sources
   690      * For all packages, find all sources belonging to the package, group the sources
   687      * based on their transformers and apply the transformers on each source code group.
   691      * based on their transformers and apply the transformers on each source code group.
   688      */
   692      */
   689     private boolean perform(JavacService javacService,
   693     private boolean perform(Sjavac sjavac,
   690                             File outputDir,
   694                             File outputDir,
   691                             Map<String,Transformer> suffixRules)
   695                             Map<String,Transformer> suffixRules) {
   692     {
       
   693         boolean rc = true;
   696         boolean rc = true;
   694         // Group sources based on transforms. A source file can only belong to a single transform.
   697         // Group sources based on transforms. A source file can only belong to a single transform.
   695         Map<Transformer,Map<String,Set<URI>>> groupedSources = new HashMap<>();
   698         Map<Transformer,Map<String,Set<URI>>> groupedSources = new HashMap<>();
   696         for (Source src : now.sources().values()) {
   699         for (Source src : now.sources().values()) {
   697             Transformer t = suffixRules.get(src.suffix());
   700             Transformer t = suffixRules.get(src.suffix());
   711             Map<String,Set<String>> packageDependencies =
   714             Map<String,Set<String>> packageDependencies =
   712                     Collections.synchronizedMap(new HashMap<String,Set<String>>());
   715                     Collections.synchronizedMap(new HashMap<String,Set<String>>());
   713             Map<String,String> packagePublicApis =
   716             Map<String,String> packagePublicApis =
   714                     Collections.synchronizedMap(new HashMap<String, String>());
   717                     Collections.synchronizedMap(new HashMap<String, String>());
   715 
   718 
   716             boolean  r = t.transform(javacService,
   719             boolean  r = t.transform(sjavac,
   717                                      srcs,
   720                                      srcs,
   718                                      visibleSrcs,
   721                                      visibleSrcs,
   719                                      visibleClasses,
   722                                      visibleClasses,
   720                                      prev.dependents(),
   723                                      prev.dependents(),
   721                                      outputDir.toURI(),
   724                                      outputDir.toURI(),
   789     /**
   792     /**
   790      * Compare the calculate source list, with an explicit list, usually supplied from the makefile.
   793      * Compare the calculate source list, with an explicit list, usually supplied from the makefile.
   791      * Used to detect bugs where the makefile and sjavac have different opinions on which files
   794      * Used to detect bugs where the makefile and sjavac have different opinions on which files
   792      * should be compiled.
   795      * should be compiled.
   793      */
   796      */
   794     public void compareWithMakefileList(File makefileSourceList)
   797     public void compareWithMakefileList(File makefileSourceList) throws ProblemException {
   795             throws ProblemException
       
   796     {
       
   797         // If we are building on win32 using for example cygwin the paths in the makefile source list
   798         // If we are building on win32 using for example cygwin the paths in the makefile source list
   798         // might be /cygdrive/c/.... which does not match c:\....
   799         // might be /cygdrive/c/.... which does not match c:\....
   799         // We need to adjust our calculated sources to be identical, if necessary.
   800         // We need to adjust our calculated sources to be identical, if necessary.
   800         boolean mightNeedRewriting = File.pathSeparatorChar == ';';
   801         boolean mightNeedRewriting = File.pathSeparatorChar == ';';
   801 
   802