Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/langtools/tools/lib/toolbox/JavacTask.java
41149 views
1
/*
2
* Copyright (c) 2013, 2021, 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.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
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.annotation.processing.Processor;
41
import javax.tools.JavaCompiler;
42
import javax.tools.JavaFileManager;
43
import javax.tools.JavaFileObject;
44
import javax.tools.StandardJavaFileManager;
45
import javax.tools.StandardLocation;
46
47
import com.sun.tools.javac.api.JavacTaskImpl;
48
import com.sun.tools.javac.api.JavacTool;
49
50
/**
51
* A task to configure and run the Java compiler, javac.
52
*/
53
public class JavacTask extends AbstractTask<JavacTask> {
54
private boolean includeStandardOptions;
55
private List<Path> classpath;
56
private List<Path> sourcepath;
57
private Path outdir;
58
private List<String> options;
59
private List<String> classes;
60
private List<String> files;
61
private List<JavaFileObject> fileObjects;
62
private JavaFileManager fileManager;
63
private Consumer<com.sun.source.util.JavacTask> callback;
64
private List<Processor> procs;
65
66
private JavaCompiler compiler;
67
private StandardJavaFileManager internalFileManager;
68
69
/**
70
* Creates a task to execute {@code javac} using API mode.
71
* @param toolBox the {@code ToolBox} to use
72
*/
73
public JavacTask(ToolBox toolBox) {
74
super(toolBox, Task.Mode.API);
75
}
76
77
/**
78
* Creates a task to execute {@code javac} in a specified mode.
79
* @param toolBox the {@code ToolBox} to use
80
* @param mode the mode to be used
81
*/
82
public JavacTask(ToolBox toolBox, Task.Mode mode) {
83
super(toolBox, mode);
84
}
85
86
/**
87
* Sets the classpath.
88
* @param classpath the classpath
89
* @return this task object
90
*/
91
public JavacTask classpath(String classpath) {
92
this.classpath = Stream.of(classpath.split(File.pathSeparator))
93
.filter(s -> !s.isEmpty())
94
.map(s -> Paths.get(s))
95
.collect(Collectors.toList());
96
return this;
97
}
98
99
/**
100
* Sets the classpath.
101
* @param classpath the classpath
102
* @return this task object
103
*/
104
public JavacTask classpath(Path... classpath) {
105
this.classpath = Arrays.asList(classpath);
106
return this;
107
}
108
109
/**
110
* Sets the classpath.
111
* @param classpath the classpath
112
* @return this task object
113
*/
114
public JavacTask classpath(List<Path> classpath) {
115
this.classpath = classpath;
116
return this;
117
}
118
119
/**
120
* Sets the sourcepath.
121
* @param sourcepath the sourcepath
122
* @return this task object
123
*/
124
public JavacTask sourcepath(String sourcepath) {
125
this.sourcepath = Stream.of(sourcepath.split(File.pathSeparator))
126
.filter(s -> !s.isEmpty())
127
.map(s -> Paths.get(s))
128
.collect(Collectors.toList());
129
return this;
130
}
131
132
/**
133
* Sets the sourcepath.
134
* @param sourcepath the sourcepath
135
* @return this task object
136
*/
137
public JavacTask sourcepath(Path... sourcepath) {
138
this.sourcepath = Arrays.asList(sourcepath);
139
return this;
140
}
141
142
/**
143
* Sets the sourcepath.
144
* @param sourcepath the sourcepath
145
* @return this task object
146
*/
147
public JavacTask sourcepath(List<Path> sourcepath) {
148
this.sourcepath = sourcepath;
149
return this;
150
}
151
152
/**
153
* Sets the output directory.
154
* @param outdir the output directory
155
* @return this task object
156
*/
157
public JavacTask outdir(String outdir) {
158
this.outdir = Paths.get(outdir);
159
return this;
160
}
161
162
/**
163
* Sets the output directory.
164
* @param outdir the output directory
165
* @return this task object
166
*/
167
public JavacTask outdir(Path outdir) {
168
this.outdir = outdir;
169
return this;
170
}
171
172
/**
173
* Sets the options.
174
* @param options the options
175
* @return this task object
176
*/
177
public JavacTask options(String... options) {
178
this.options = Arrays.asList(options);
179
return this;
180
}
181
182
/**
183
* Sets the options.
184
* @param spaceSeparatedOption the space separated options
185
* @return this task object
186
*/
187
public JavacTask spaceSeparatedOptions(String spaceSeparatedOption) {
188
this.options = Arrays.asList(spaceSeparatedOption.split("\\s+"));
189
return this;
190
}
191
192
/**
193
* Sets the options.
194
* @param options the options
195
* @return this task object
196
*/
197
public JavacTask options(List<String> options) {
198
this.options = options;
199
return this;
200
}
201
202
/**
203
* Sets the classes to be analyzed.
204
* @param classes the classes
205
* @return this task object
206
*/
207
public JavacTask classes(String... classes) {
208
this.classes = Arrays.asList(classes);
209
return this;
210
}
211
212
/**
213
* Sets the files to be compiled or analyzed.
214
* @param files the files
215
* @return this task object
216
*/
217
public JavacTask files(String... files) {
218
this.files = Arrays.asList(files);
219
return this;
220
}
221
222
/**
223
* Sets the files to be compiled or analyzed.
224
* @param files the files
225
* @return this task object
226
*/
227
public JavacTask files(Path... files) {
228
this.files = Stream.of(files)
229
.map(Path::toString)
230
.collect(Collectors.toList());
231
return this;
232
}
233
234
/**
235
* Sets the files to be compiled or analyzed.
236
* @param files the files
237
* @return this task object
238
*/
239
public JavacTask files(List<Path> files) {
240
this.files = files.stream()
241
.map(Path::toString)
242
.collect(Collectors.toList());
243
return this;
244
}
245
246
/**
247
* Sets the sources to be compiled or analyzed.
248
* Each source string is converted into an in-memory object that
249
* can be passed directly to the compiler.
250
* @param sources the sources
251
* @return this task object
252
*/
253
public JavacTask sources(String... sources) {
254
fileObjects = Stream.of(sources)
255
.map(s -> new ToolBox.JavaSource(s))
256
.collect(Collectors.toList());
257
return this;
258
}
259
260
/**
261
* Sets the the annotation processors to be used.
262
*/
263
public JavacTask processors(Processor... procs) {
264
this.procs = List.of(procs);
265
return this;
266
}
267
268
/**
269
* Sets the file manager to be used by this task.
270
* @param fileManager the file manager
271
* @return this task object
272
*/
273
public JavacTask fileManager(JavaFileManager fileManager) {
274
this.fileManager = fileManager;
275
return this;
276
}
277
278
/**
279
* Set a callback to be used by this task.
280
* @param callback the callback
281
* @return this task object
282
*/
283
public JavacTask callback(Consumer<com.sun.source.util.JavacTask> callback) {
284
this.callback = callback;
285
return this;
286
}
287
288
/**
289
* {@inheritDoc}
290
* @return the name "javac"
291
*/
292
@Override
293
public String name() {
294
return "javac";
295
}
296
297
/**
298
* Calls the compiler with the arguments as currently configured.
299
* @return a Result object indicating the outcome of the compilation
300
* and the content of any output written to stdout, stderr, or the
301
* main stream by the compiler.
302
* @throws TaskError if the outcome of the task is not as expected.
303
*/
304
@Override
305
public Task.Result run() {
306
if (mode == Task.Mode.EXEC)
307
return runExec();
308
309
AbstractTask.WriterOutput direct = new AbstractTask.WriterOutput();
310
// The following are to catch output to System.out and System.err,
311
// in case these are used instead of the primary (main) stream
312
AbstractTask.StreamOutput sysOut = new AbstractTask.StreamOutput(System.out, System::setOut);
313
AbstractTask.StreamOutput sysErr = new AbstractTask.StreamOutput(System.err, System::setErr);
314
int rc;
315
Map<Task.OutputKind, String> outputMap = new HashMap<>();
316
try {
317
switch (mode == null ? Task.Mode.API : mode) {
318
case API:
319
rc = runAPI(direct.pw);
320
break;
321
case CMDLINE:
322
if (fileManager != null) {
323
throw new IllegalStateException("file manager set in CMDLINE mode");
324
}
325
if (callback != null) {
326
throw new IllegalStateException("callback set in CMDLINE mode");
327
}
328
rc = runCommand(direct.pw);
329
break;
330
default:
331
throw new IllegalStateException("unknown mode " + mode);
332
}
333
} catch (IOException e) {
334
toolBox.out.println("Exception occurred: " + e);
335
rc = 99;
336
} finally {
337
outputMap.put(Task.OutputKind.STDOUT, sysOut.close());
338
outputMap.put(Task.OutputKind.STDERR, sysErr.close());
339
outputMap.put(Task.OutputKind.DIRECT, direct.close());
340
}
341
return checkExit(new Task.Result(toolBox, this, rc, outputMap));
342
}
343
344
private int runAPI(PrintWriter pw) throws IOException {
345
try {
346
// if (compiler == null) {
347
// TODO: allow this to be set externally
348
// compiler = ToolProvider.getSystemJavaCompiler();
349
compiler = JavacTool.create();
350
// }
351
352
if (fileManager == null)
353
fileManager = internalFileManager = compiler.getStandardFileManager(null, null, null);
354
if (outdir != null)
355
setLocationFromPaths(StandardLocation.CLASS_OUTPUT, Collections.singletonList(outdir));
356
if (classpath != null)
357
setLocationFromPaths(StandardLocation.CLASS_PATH, classpath);
358
if (sourcepath != null)
359
setLocationFromPaths(StandardLocation.SOURCE_PATH, sourcepath);
360
List<String> allOpts = new ArrayList<>();
361
if (options != null)
362
allOpts.addAll(options);
363
364
Iterable<? extends JavaFileObject> allFiles = joinFiles(files, fileObjects);
365
JavaCompiler.CompilationTask task = compiler.getTask(pw,
366
fileManager,
367
null, // diagnostic listener; should optionally collect diags
368
allOpts,
369
classes,
370
allFiles);
371
if (procs != null) {
372
task.setProcessors(procs);
373
}
374
JavacTaskImpl taskImpl = (JavacTaskImpl) task;
375
if (callback != null) {
376
callback.accept(taskImpl);
377
}
378
return taskImpl.doCall().exitCode;
379
} finally {
380
if (internalFileManager != null)
381
internalFileManager.close();
382
}
383
}
384
385
private void setLocationFromPaths(StandardLocation location, List<Path> files) throws IOException {
386
if (!(fileManager instanceof StandardJavaFileManager))
387
throw new IllegalStateException("not a StandardJavaFileManager");
388
((StandardJavaFileManager) fileManager).setLocationFromPaths(location, files);
389
}
390
391
private int runCommand(PrintWriter pw) {
392
List<String> args = getAllArgs();
393
String[] argsArray = args.toArray(new String[args.size()]);
394
return com.sun.tools.javac.Main.compile(argsArray, pw);
395
}
396
397
private Task.Result runExec() {
398
List<String> args = new ArrayList<>();
399
Path javac = toolBox.getJDKTool("javac");
400
args.add(javac.toString());
401
if (includeStandardOptions) {
402
args.addAll(toolBox.split(System.getProperty("test.tool.vm.opts"), " +"));
403
args.addAll(toolBox.split(System.getProperty("test.compiler.opts"), " +"));
404
}
405
args.addAll(getAllArgs());
406
407
String[] argsArray = args.toArray(new String[args.size()]);
408
ProcessBuilder pb = getProcessBuilder();
409
pb.command(argsArray);
410
try {
411
return runProcess(toolBox, this, pb.start());
412
} catch (IOException | InterruptedException e) {
413
throw new Error(e);
414
}
415
}
416
417
private List<String> getAllArgs() {
418
List<String> args = new ArrayList<>();
419
if (options != null)
420
args.addAll(options);
421
if (outdir != null) {
422
args.add("-d");
423
args.add(outdir.toString());
424
}
425
if (classpath != null) {
426
args.add("-classpath");
427
args.add(toSearchPath(classpath));
428
}
429
if (sourcepath != null) {
430
args.add("-sourcepath");
431
args.add(toSearchPath(sourcepath));
432
}
433
if (classes != null)
434
args.addAll(classes);
435
if (files != null)
436
args.addAll(files);
437
438
return args;
439
}
440
441
private String toSearchPath(List<Path> files) {
442
return files.stream()
443
.map(Path::toString)
444
.collect(Collectors.joining(File.pathSeparator));
445
}
446
447
private Iterable<? extends JavaFileObject> joinFiles(
448
List<String> files, List<JavaFileObject> fileObjects) {
449
if (files == null)
450
return fileObjects;
451
if (internalFileManager == null)
452
internalFileManager = compiler.getStandardFileManager(null, null, null);
453
Iterable<? extends JavaFileObject> filesAsFileObjects =
454
internalFileManager.getJavaFileObjectsFromStrings(files);
455
if (fileObjects == null)
456
return filesAsFileObjects;
457
List<JavaFileObject> combinedList = new ArrayList<>();
458
for (JavaFileObject o : filesAsFileObjects)
459
combinedList.add(o);
460
combinedList.addAll(fileObjects);
461
return combinedList;
462
}
463
}
464
465