1 /*
2  * Copyright (c) 2015, 2016, 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 
26 package com.sun.tools.sjavac.comp;
27 
28 import java.io.File;
29 import java.io.IOException;
30 import java.io.PrintWriter;
31 import java.io.StringWriter;
32 import java.net.URI;
33 import java.util.Arrays;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Set;
37 
38 import javax.tools.JavaFileObject;
39 import javax.tools.StandardJavaFileManager;
40 import javax.tools.StandardLocation;
41 import javax.tools.ToolProvider;
42 
43 import com.sun.tools.javac.api.JavacTaskImpl;
44 import com.sun.tools.javac.api.JavacTool;
45 import com.sun.tools.javac.main.Main;
46 import com.sun.tools.javac.main.Main.Result;
47 import com.sun.tools.javac.util.Context;
48 import com.sun.tools.javac.util.Dependencies;
49 import com.sun.tools.javac.util.ListBuffer;
50 import com.sun.tools.sjavac.Log;
51 import com.sun.tools.sjavac.Util;
52 import com.sun.tools.sjavac.comp.dependencies.NewDependencyCollector;
53 import com.sun.tools.sjavac.comp.dependencies.PublicApiCollector;
54 import com.sun.tools.sjavac.server.CompilationSubResult;
55 import com.sun.tools.sjavac.server.SysInfo;
56 
57 /**
58  *  <p><b>This is NOT part of any supported API.
59  *  If you write code that depends on this, you do so at your own risk.
60  *  This code and its internal interfaces are subject to change or
61  *  deletion without notice.</b>
62  */
63 public class CompilationService {
64 
getSysInfo()65     public SysInfo getSysInfo() {
66         return new SysInfo(Runtime.getRuntime().availableProcessors(),
67                            Runtime.getRuntime().maxMemory());
68     }
69 
compile(String protocolId, String invocationId, String[] args, List<File> explicitSources, Set<URI> sourcesToCompile, Set<URI> visibleSources)70     public CompilationSubResult compile(String protocolId,
71                                      String invocationId,
72                                      String[] args,
73                                      List<File> explicitSources,
74                                      Set<URI> sourcesToCompile,
75                                      Set<URI> visibleSources) {
76 
77         JavacTool compiler = (JavacTool) ToolProvider.getSystemJavaCompiler();
78         try (StandardJavaFileManager fm = compiler.getStandardFileManager(null, null, null)) {
79             SmartFileManager sfm = new SmartFileManager(fm);
80             Context context = new Context();
81 
82             Dependencies.GraphDependencies.preRegister(context);
83 
84             // Now setup the actual compilation
85             CompilationSubResult compilationResult = new CompilationSubResult(Result.OK);
86 
87             // First deal with explicit source files on cmdline and in at file
88             ListBuffer<JavaFileObject> explicitJFOs = new ListBuffer<>();
89             for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(explicitSources)) {
90                 explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH));
91             }
92             // Now deal with sources supplied as source_to_compile
93             ListBuffer<File> sourcesToCompileFiles = new ListBuffer<>();
94             for (URI u : sourcesToCompile)
95                 sourcesToCompileFiles.append(new File(u));
96 
97             for (JavaFileObject jfo : fm.getJavaFileObjectsFromFiles(sourcesToCompileFiles))
98                 explicitJFOs.append(SmartFileManager.locWrap(jfo, StandardLocation.SOURCE_PATH));
99 
100             // Create a log to capture compiler output
101             StringWriter stderrLog = new StringWriter();
102             Result result;
103             PublicApiCollector pubApiCollector = new PublicApiCollector(context, explicitJFOs);
104             PathAndPackageVerifier papVerifier = new PathAndPackageVerifier();
105             NewDependencyCollector depsCollector = new NewDependencyCollector(context, explicitJFOs);
106             try {
107                 if (explicitJFOs.size() > 0) {
108                     sfm.setVisibleSources(visibleSources);
109                     sfm.cleanArtifacts();
110 
111                     // Do the compilation!
112                     JavacTaskImpl task =
113                             (JavacTaskImpl) compiler.getTask(new PrintWriter(stderrLog),
114                                                              sfm,
115                                                              null,
116                                                              Arrays.asList(args),
117                                                              null,
118                                                              explicitJFOs,
119                                                              context);
120                     sfm.setSymbolFileEnabled(!com.sun.tools.javac.util.Options.instance(context).isSet("ignore.symbol.file"));
121                     task.addTaskListener(depsCollector);
122                     task.addTaskListener(pubApiCollector);
123                     task.addTaskListener(papVerifier);
124                     logJavacInvocation(args);
125                     result = task.doCall();
126                     Log.debug("javac result: " + result);
127                     sfm.flush();
128                 } else {
129                     result = Result.ERROR;
130                 }
131             } catch (Exception e) {
132                 Log.error(Util.getStackTrace(e));
133                 stderrLog.append(Util.getStackTrace(e));
134                 result = Result.ERROR;
135             }
136 
137             compilationResult.packageArtifacts = sfm.getPackageArtifacts();
138 
139             if (papVerifier.errorsDiscovered()) {
140                 result = Result.ERROR;
141             }
142 
143             compilationResult.packageDependencies = depsCollector.getDependencies(false);
144             compilationResult.packageCpDependencies = depsCollector.getDependencies(true);
145 
146             compilationResult.packagePubapis = pubApiCollector.getPubApis(true);
147             compilationResult.dependencyPubapis = pubApiCollector.getPubApis(false);
148             compilationResult.stderr = stderrLog.toString();
149             compilationResult.result = result;
150 
151             return compilationResult;
152         } catch (IOException e) {
153             throw new Error(e);
154         }
155     }
156 
logJavacInvocation(String[] args)157     private void logJavacInvocation(String[] args) {
158         Log.debug("Invoking javac with args");
159         Iterator<String> argIter = Arrays.asList(args).iterator();
160         while (argIter.hasNext()) {
161             String arg = argIter.next();
162             String line = "    " + arg;
163             if (arg.matches("\\-(d|cp|classpath|sourcepath|source|target)")
164                     && argIter.hasNext()) {
165                 line += " " + argIter.next();
166             }
167             Log.debug(line);
168         }
169     }
170 
171 }
172