< prev index next >

test/langtools/tools/lib/toolbox/JavacTask.java

Print this page
rev 48841 : [mq]: 8187950


  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package toolbox;
  25 
  26 import java.io.File;
  27 import java.io.IOException;
  28 import java.io.PrintWriter;
  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;
  31 import java.util.ArrayList;
  32 import java.util.Arrays;
  33 import java.util.Collections;
  34 import java.util.HashMap;
  35 import java.util.List;
  36 import java.util.Map;

  37 import java.util.stream.Collectors;
  38 import java.util.stream.Stream;
  39 import javax.tools.JavaCompiler;
  40 import javax.tools.JavaFileManager;
  41 import javax.tools.JavaFileObject;
  42 import javax.tools.StandardJavaFileManager;
  43 import javax.tools.StandardLocation;
  44 
  45 import com.sun.tools.javac.api.JavacTaskImpl;
  46 import com.sun.tools.javac.api.JavacTool;
  47 
  48 /**
  49  * A task to configure and run the Java compiler, javac.
  50  */
  51 public class JavacTask extends AbstractTask<JavacTask> {
  52     private boolean includeStandardOptions;
  53     private List<Path> classpath;
  54     private List<Path> sourcepath;
  55     private Path outdir;
  56     private List<String> options;
  57     private List<String> classes;
  58     private List<String> files;
  59     private List<JavaFileObject> fileObjects;
  60     private JavaFileManager fileManager;

  61 
  62     private JavaCompiler compiler;
  63     private StandardJavaFileManager internalFileManager;
  64 
  65     /**
  66      * Creates a task to execute {@code javac} using API mode.
  67      * @param toolBox the {@code ToolBox} to use
  68      */
  69     public JavacTask(ToolBox toolBox) {
  70         super(toolBox, Task.Mode.API);
  71     }
  72 
  73     /**
  74      * Creates a task to execute {@code javac} in a specified mode.
  75      * @param toolBox the {@code ToolBox} to use
  76      * @param mode the mode to be used
  77      */
  78     public JavacTask(ToolBox toolBox, Task.Mode mode) {
  79         super(toolBox, mode);
  80     }


 237      * @return this task object
 238      */
 239     public JavacTask sources(String... sources) {
 240         fileObjects = Stream.of(sources)
 241                 .map(s -> new ToolBox.JavaSource(s))
 242                 .collect(Collectors.toList());
 243         return this;
 244     }
 245 
 246     /**
 247      * Sets the file manager to be used by this task.
 248      * @param fileManager the file manager
 249      * @return this task object
 250      */
 251     public JavacTask fileManager(JavaFileManager fileManager) {
 252         this.fileManager = fileManager;
 253         return this;
 254     }
 255 
 256     /**










 257      * {@inheritDoc}
 258      * @return the name "javac"
 259      */
 260     @Override
 261     public String name() {
 262         return "javac";
 263     }
 264 
 265     /**
 266      * Calls the compiler with the arguments as currently configured.
 267      * @return a Result object indicating the outcome of the compilation
 268      * and the content of any output written to stdout, stderr, or the
 269      * main stream by the compiler.
 270      * @throws TaskError if the outcome of the task is not as expected.
 271      */
 272     @Override
 273     public Task.Result run() {
 274         if (mode == Task.Mode.EXEC)
 275             return runExec();
 276 
 277         AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();
 278         // The following are to catch output to System.out and System.err,
 279         // in case these are used instead of the primary (main) stream
 280         AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);
 281         AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);
 282         int rc;
 283         Map<Task.OutputKind, String> outputMap = new HashMap<>();
 284         try {
 285             switch (mode == null ? Task.Mode.API : mode) {
 286                 case API:
 287                     rc = runAPI(direct.pw);
 288                     break;
 289                 case CMDLINE:
 290                     if (fileManager != null) {
 291                         throw new IllegalStateException("file manager set in CMDLINE mode");
 292                     }



 293                     rc = runCommand(direct.pw);
 294                     break;
 295                 default:
 296                     throw new IllegalStateException("unknown mode " + mode);
 297             }
 298         } catch (IOException e) {
 299             toolBox.out.println("Exception occurred: " + e);
 300             rc = 99;
 301         } finally {
 302             outputMap.put(Task.OutputKind.STDOUT, sysOut.close());
 303             outputMap.put(Task.OutputKind.STDERR, sysErr.close());
 304             outputMap.put(Task.OutputKind.DIRECT, direct.close());
 305         }
 306         return checkExit(new Task.Result(toolBox, this, rc, outputMap));
 307     }
 308 
 309     private int runAPI(PrintWriter pw) throws IOException {
 310         try {
 311 //                if (compiler == null) {
 312                 // TODO: allow this to be set externally


 316 
 317             if (fileManager == null)
 318                 fileManager = internalFileManager = compiler.getStandardFileManager(null, null, null);
 319             if (outdir != null)
 320                 setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outdir));
 321             if (classpath != null)
 322                 setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
 323             if (sourcepath != null)
 324                 setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);
 325             List<String> allOpts = new ArrayList<>();
 326             if (options != null)
 327                 allOpts.addAll(options);
 328 
 329             Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
 330             JavaCompiler.CompilationTask task = compiler.getTask(pw,
 331                     fileManager,
 332                     null,  // diagnostic listener; should optionally collect diags
 333                     allOpts,
 334                     classes,
 335                     allFiles);
 336             return ((JavacTaskImpl) task).doCall().exitCode;




 337         } finally {
 338             if (internalFileManager != null)
 339                 internalFileManager.close();
 340         }
 341     }
 342 
 343     private void setLocationFromPaths(StandardLocation location, List<Path> files) throws IOException {
 344         if (!(fileManager instanceof StandardJavaFileManager))
 345             throw new IllegalStateException("not a StandardJavaFileManager");
 346         ((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
 347     }
 348 
 349     private int runCommand(PrintWriter pw) {
 350         List<String> args = getAllArgs();
 351         String[] argsArray = args.toArray(new String[args.size()]);
 352         return com.sun.tools.javac.Main.compile(argsArray, pw);
 353     }
 354 
 355     private Task.Result runExec() {
 356         List<String> args = new ArrayList<>();




  17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  18  *
  19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  20  * or visit www.oracle.com if you need additional information or have any
  21  * questions.
  22  */
  23 
  24 package toolbox;
  25 
  26 import java.io.File;
  27 import java.io.IOException;
  28 import java.io.PrintWriter;
  29 import java.nio.file.Path;
  30 import java.nio.file.Paths;
  31 import java.util.ArrayList;
  32 import java.util.Arrays;
  33 import java.util.Collections;
  34 import java.util.HashMap;
  35 import java.util.List;
  36 import java.util.Map;
  37 import java.util.function.Consumer;
  38 import java.util.stream.Collectors;
  39 import java.util.stream.Stream;
  40 import javax.tools.JavaCompiler;
  41 import javax.tools.JavaFileManager;
  42 import javax.tools.JavaFileObject;
  43 import javax.tools.StandardJavaFileManager;
  44 import javax.tools.StandardLocation;
  45 
  46 import com.sun.tools.javac.api.JavacTaskImpl;
  47 import com.sun.tools.javac.api.JavacTool;
  48 
  49 /**
  50  * A task to configure and run the Java compiler, javac.
  51  */
  52 public class JavacTask extends AbstractTask<JavacTask> {
  53     private boolean includeStandardOptions;
  54     private List<Path> classpath;
  55     private List<Path> sourcepath;
  56     private Path outdir;
  57     private List<String> options;
  58     private List<String> classes;
  59     private List<String> files;
  60     private List<JavaFileObject> fileObjects;
  61     private JavaFileManager fileManager;
  62     private Consumer<com.sun.source.util.JavacTask> callback;
  63 
  64     private JavaCompiler compiler;
  65     private StandardJavaFileManager internalFileManager;
  66 
  67     /**
  68      * Creates a task to execute {@code javac} using API mode.
  69      * @param toolBox the {@code ToolBox} to use
  70      */
  71     public JavacTask(ToolBox toolBox) {
  72         super(toolBox, Task.Mode.API);
  73     }
  74 
  75     /**
  76      * Creates a task to execute {@code javac} in a specified mode.
  77      * @param toolBox the {@code ToolBox} to use
  78      * @param mode the mode to be used
  79      */
  80     public JavacTask(ToolBox toolBox, Task.Mode mode) {
  81         super(toolBox, mode);
  82     }


 239      * @return this task object
 240      */
 241     public JavacTask sources(String... sources) {
 242         fileObjects = Stream.of(sources)
 243                 .map(s -> new ToolBox.JavaSource(s))
 244                 .collect(Collectors.toList());
 245         return this;
 246     }
 247 
 248     /**
 249      * Sets the file manager to be used by this task.
 250      * @param fileManager the file manager
 251      * @return this task object
 252      */
 253     public JavacTask fileManager(JavaFileManager fileManager) {
 254         this.fileManager = fileManager;
 255         return this;
 256     }
 257 
 258     /**
 259      * Set a callback to be used by this task.
 260      * @param callback the callback
 261      * @return this task object
 262      */
 263     public JavacTask callback(Consumer<com.sun.source.util.JavacTask> callback) {
 264         this.callback = callback;
 265         return this;
 266     }
 267 
 268     /**
 269      * {@inheritDoc}
 270      * @return the name "javac"
 271      */
 272     @Override
 273     public String name() {
 274         return "javac";
 275     }
 276 
 277     /**
 278      * Calls the compiler with the arguments as currently configured.
 279      * @return a Result object indicating the outcome of the compilation
 280      * and the content of any output written to stdout, stderr, or the
 281      * main stream by the compiler.
 282      * @throws TaskError if the outcome of the task is not as expected.
 283      */
 284     @Override
 285     public Task.Result run() {
 286         if (mode == Task.Mode.EXEC)
 287             return runExec();
 288 
 289         AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();
 290         // The following are to catch output to System.out and System.err,
 291         // in case these are used instead of the primary (main) stream
 292         AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);
 293         AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);
 294         int rc;
 295         Map<Task.OutputKind, String> outputMap = new HashMap<>();
 296         try {
 297             switch (mode == null ? Task.Mode.API : mode) {
 298                 case API:
 299                     rc = runAPI(direct.pw);
 300                     break;
 301                 case CMDLINE:
 302                     if (fileManager != null) {
 303                         throw new IllegalStateException("file manager set in CMDLINE mode");
 304                     }
 305                     if (callback != null) {
 306                         throw new IllegalStateException("callback set in CMDLINE mode");
 307                     }
 308                     rc = runCommand(direct.pw);
 309                     break;
 310                 default:
 311                     throw new IllegalStateException("unknown mode " + mode);
 312             }
 313         } catch (IOException e) {
 314             toolBox.out.println("Exception occurred: " + e);
 315             rc = 99;
 316         } finally {
 317             outputMap.put(Task.OutputKind.STDOUT, sysOut.close());
 318             outputMap.put(Task.OutputKind.STDERR, sysErr.close());
 319             outputMap.put(Task.OutputKind.DIRECT, direct.close());
 320         }
 321         return checkExit(new Task.Result(toolBox, this, rc, outputMap));
 322     }
 323 
 324     private int runAPI(PrintWriter pw) throws IOException {
 325         try {
 326 //                if (compiler == null) {
 327                 // TODO: allow this to be set externally


 331 
 332             if (fileManager == null)
 333                 fileManager = internalFileManager = compiler.getStandardFileManager(null, null, null);
 334             if (outdir != null)
 335                 setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outdir));
 336             if (classpath != null)
 337                 setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
 338             if (sourcepath != null)
 339                 setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);
 340             List<String> allOpts = new ArrayList<>();
 341             if (options != null)
 342                 allOpts.addAll(options);
 343 
 344             Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
 345             JavaCompiler.CompilationTask task = compiler.getTask(pw,
 346                     fileManager,
 347                     null,  // diagnostic listener; should optionally collect diags
 348                     allOpts,
 349                     classes,
 350                     allFiles);
 351             JavacTaskImpl taskImpl = (JavacTaskImpl) task;
 352             if (callback != null) {
 353                 callback.accept(taskImpl);
 354             }
 355             return taskImpl.doCall().exitCode;
 356         } finally {
 357             if (internalFileManager != null)
 358                 internalFileManager.close();
 359         }
 360     }
 361 
 362     private void setLocationFromPaths(StandardLocation location, List<Path> files) throws IOException {
 363         if (!(fileManager instanceof StandardJavaFileManager))
 364             throw new IllegalStateException("not a StandardJavaFileManager");
 365         ((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
 366     }
 367 
 368     private int runCommand(PrintWriter pw) {
 369         List<String> args = getAllArgs();
 370         String[] argsArray = args.toArray(new String[args.size()]);
 371         return com.sun.tools.javac.Main.compile(argsArray, pw);
 372     }
 373 
 374     private Task.Result runExec() {
 375         List<String> args = new ArrayList<>();


< prev index next >