1 /*
   2  * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 package com.sun.tools.sjavac.comp;
  26 
  27 import java.io.File;
  28 import java.io.IOException;
  29 import java.io.PrintWriter;
  30 import java.io.StringWriter;
  31 import java.net.URI;
  32 import java.util.Arrays;
  33 import java.util.List;
  34 import java.util.Set;
  35 
  36 import javax.tools.JavaFileObject;
  37 import javax.tools.StandardJavaFileManager;
  38 import javax.tools.ToolProvider;
  39 
  40 import com.sun.tools.javac.api.JavacTaskImpl;
  41 import com.sun.tools.javac.api.JavacTool;
  42 import com.sun.tools.javac.util.Context;
  43 import com.sun.tools.javac.util.ListBuffer;
  44 import com.sun.tools.javac.util.Options;
  45 import com.sun.tools.sjavac.Log;
  46 import com.sun.tools.sjavac.Util;
  47 import com.sun.tools.sjavac.comp.dependencies.DependencyCollector;
  48 import com.sun.tools.sjavac.comp.dependencies.PublicApiCollector;
  49 import com.sun.tools.sjavac.server.CompilationResult;
  50 import com.sun.tools.sjavac.server.Sjavac;
  51 import com.sun.tools.sjavac.server.SysInfo;
  52 
  53 /**
  54  * The sjavac implementation that interacts with javac and performs the actual
  55  * compilation.
  56  *
  57  *  <p><b>This is NOT part of any supported API.
  58  *  If you write code that depends on this, you do so at your own risk.
  59  *  This code and its internal interfaces are subject to change or
  60  *  deletion without notice.</b>
  61  */
  62 public class SjavacImpl implements Sjavac {
  63 static Object lock = new Object();
  64     @Override
  65     public SysInfo getSysInfo() {
  66         return new SysInfo(Runtime.getRuntime().availableProcessors(),
  67                            Runtime.getRuntime().maxMemory());
  68     }
  69 
  70     @Override
  71     public CompilationResult compile(String protocolId,
  72                                      String invocationId,
  73                                      String[] args,
  74                                      List<File> explicitSources,
  75                                      Set<URI> sourcesToCompile,
  76                                      Set<URI> visibleSources) {
  77 
  78         JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler();
  79         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
  80             SmartFileManager sfm = new SmartFileManager(fm);
  81             Context context = new Context();
  82 
  83             // Now setup the actual compilation
  84             CompilationResult compilationResult = new CompilationResult(0);
  85 
  86             // First deal with explicit source files on cmdline and in at file
  87             ListBuffer<JavaFileObject> explicitJFOs = new ListBuffer<>();
  88             for (JavaFileObject i : fm.getJavaFileObjectsFromFiles(explicitSources)) {
  89                 explicitJFOs.append(i);
  90             }
  91             // Now deal with sources supplied as source_to_compile
  92             ListBuffer<File> sourcesToCompileFiles = new ListBuffer<>();
  93             for (URI u : sourcesToCompile)
  94                 sourcesToCompileFiles.append(new File(u));
  95 
  96             for (JavaFileObject i : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles))
  97                 explicitJFOs.append(i);
  98 
  99             // Create a new logger
 100             StringWriter stdoutLog = new StringWriter();
 101             StringWriter stderrLog = new StringWriter();
 102             PrintWriter stdout = new PrintWriter(stdoutLog);
 103             PrintWriter stderr = new PrintWriter(stderrLog);
 104             com.sun.tools.javac.main.Main.Result rc = com.sun.tools.javac.main.Main.Result.OK;
 105             DependencyCollector depsCollector = new DependencyCollector(context);
 106             PublicApiCollector pubApiCollector = new PublicApiCollector(context);
 107             PathAndPackageVerifier papVerifier = new PathAndPackageVerifier();
 108             try {
 109                 if (explicitJFOs.size() > 0) {
 110                     sfm.setVisibleSources(visibleSources);
 111                     sfm.cleanArtifacts();
 112                     sfm.setLog(stdout);
 113 
 114                     // Do the compilation!
 115                     JavacTaskImpl task =
 116                             (JavacTaskImpl) compiler.getTask(stderr,
 117                                                              sfm,
 118                                                              null,
 119                                                              Arrays.asList(args),
 120                                                              null,
 121                                                              explicitJFOs,
 122                                                              context);
 123                     sfm.setSymbolFileEnabled(!Options.instance(context).isSet("ignore.symbol.file"));
 124                     task.addTaskListener(depsCollector);
 125                     task.addTaskListener(pubApiCollector);
 126                     task.addTaskListener(papVerifier);
 127                     Log.debug("Invoking javac with args");
 128                     Arrays.asList(args).forEach(arg -> Log.debug("    " + arg));
 129                     rc = task.doCall();
 130                     Log.debug("javac returned with code " + rc);
 131                     sfm.flush();
 132                 }
 133             } catch (Exception e) {
 134                 Log.error(Util.getStackTrace(e));
 135                 stderrLog.append(Util.getStackTrace(e));
 136                 rc = com.sun.tools.javac.main.Main.Result.ERROR;
 137             }
 138 
 139             compilationResult.packageArtifacts = sfm.getPackageArtifacts();
 140 
 141             if (papVerifier.errorsDiscovered())
 142                 rc = com.sun.tools.javac.main.Main.Result.ERROR;
 143 
 144             Dependencies deps = Dependencies.instance(context);
 145             compilationResult.packageDependencies = deps.getDependencies(explicitJFOs);
 146             compilationResult.packageCpDependencies = deps.getCpDependencies(explicitJFOs);
 147             compilationResult.packagePubapis = deps.getPubapis(explicitJFOs, true);
 148             compilationResult.dependencyPubapis = deps.getPubapis(explicitJFOs, false);
 149             compilationResult.stdout = stdoutLog.toString();
 150             compilationResult.stderr = stderrLog.toString();
 151             compilationResult.returnCode = rc.exitCode;
 152 
 153             return compilationResult;
 154         } catch (IOException e) {
 155             throw new Error(e);
 156         }
 157     }
 158 
 159     @Override
 160     public void shutdown() {
 161         // Nothing to clean up
 162         // ... maybe we should wait for any current request to finish?
 163     }
 164 
 165 
 166     @Override
 167     public String serverSettings() {
 168         return "";
 169     }
 170 
 171 }