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