Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
io.takari.maven.plugins.compile.javac.CompilerJavacForked Maven / Gradle / Ivy
/**
* Copyright (c) 2014 Takari, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package io.takari.maven.plugins.compile.javac;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Writer;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;
import javax.tools.Diagnostic;
import javax.tools.Diagnostic.Kind;
import javax.tools.DiagnosticCollector;
import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import io.takari.incrementalbuild.MessageSeverity;
public class CompilerJavacForked {
private static final String EOL = "\n";
private static final String ENCODING = "UTF-8";
public static class CompilerConfiguration {
private final Charset encoding;
private final Iterable options;
private final Iterable sources;
public CompilerConfiguration(Charset encoding, Iterable options, Iterable sources) {
this.encoding = encoding;
this.options = options;
this.sources = sources;
}
public Charset getSourceEncoding() {
return encoding;
}
public Iterable getCompilerOptions() {
return options;
}
public Iterable getSources() {
return sources;
}
public void write(File file) throws IOException {
Writer writer = newWriter(file);
try {
// encoding
if (encoding != null) {
writer.write('C');
writer.write(encoding.name());
writer.write(EOL);
}
// options
for (String option : options) {
writer.write('O');
writer.write(option);
writer.write(EOL);
}
// sources
for (File source : sources) {
writer.write('S');
writer.write(source.getCanonicalPath());
writer.write(EOL);
}
} finally {
writer.close();
}
}
public static CompilerConfiguration read(File file) throws IOException {
Charset encoding = null;
List options = new ArrayList();
List sources = new ArrayList();
BufferedReader reader = newBufferedReader(file);
try {
String str;
while ((str = reader.readLine()) != null) {
String value = str.substring(1);
switch (str.charAt(0)) {
case 'C':
encoding = Charset.forName(value);
break;
case 'O':
options.add(value);
break;
case 'S':
sources.add(new File(value));
break;
}
}
} finally {
reader.close();
}
return new CompilerConfiguration(encoding, options, sources);
}
}
public static class CompilerOutput {
private final Writer writer;
public CompilerOutput(File file) throws IOException {
this.writer = newWriter(file);
}
public void processOutput(File inputFile, File outputFile) {
try {
writer.write('O');
writer.write(inputFile != null ? URLEncoder.encode(inputFile.getCanonicalPath(), ENCODING) : ".");
writer.write(' ');
writer.write(URLEncoder.encode(outputFile.getCanonicalPath(), ENCODING));
writer.write(EOL);
} catch (IOException e) {
handleException(e);
}
}
public void addMessage(String path, int line, int column, String message, Kind kind) {
try {
writer.write('M');
writer.write(URLEncoder.encode(path, ENCODING));
writer.write(' ');
writer.write(Integer.toString(line));
writer.write(' ');
writer.write(Integer.toString(column));
writer.write(' ');
switch (kind) {
case ERROR:
writer.write('E');
break;
case NOTE:
writer.write('I');
break;
default:
writer.write('W');
break;
}
writer.write(' ');
writer.write(URLEncoder.encode(message, ENCODING));
writer.write(EOL);
} catch (IOException e) {
handleException(e);
}
}
public void addLogMessage(String message) {
try {
writer.write('L');
writer.write(message);
writer.write(EOL);
} catch (IOException e) {
handleException(e);
}
}
public void close() throws IOException {
writer.close();
}
private void handleException(IOException e) {
e.printStackTrace();
System.exit(1); // this will trigger ExecutionException in Maven plugin
}
public static void process(File file, CompilerOutputProcessor callback) throws IOException {
BufferedReader reader = newBufferedReader(file);
try {
String str;
while ((str = reader.readLine()) != null) {
String value = str.substring(1);
switch (str.charAt(0)) {
case 'O': {
StringTokenizer st = new StringTokenizer(value, " ");
String inputPath = URLDecoder.decode(st.nextToken(), ENCODING);
String outputPath = URLDecoder.decode(st.nextToken(), ENCODING);
callback.processOutput(!".".equals(inputPath) ? new File(inputPath) : null, new File(outputPath));
break;
}
case 'M': {
StringTokenizer st = new StringTokenizer(value, " ");
String path = URLDecoder.decode(st.nextToken(), ENCODING);
int line = Integer.parseInt(st.nextToken());
int column = Integer.parseInt(st.nextToken());
MessageSeverity severity = toSeverity(st.nextToken());
String message = URLDecoder.decode(st.nextToken(), ENCODING);
callback.addMessage(path, line, column, message, severity);
break;
}
case 'L': {
callback.addLogMessage(value);
break;
}
default:
throw new IllegalArgumentException();
}
}
} finally {
reader.close();
}
}
private static MessageSeverity toSeverity(String token) {
switch (token) {
case "E":
return MessageSeverity.ERROR;
case "I":
return MessageSeverity.INFO;
default:
return MessageSeverity.WARNING;
}
}
}
public static interface CompilerOutputProcessor {
public void processOutput(File inputFile, File outputFile);
public void addMessage(String path, int line, int column, String message, MessageSeverity kind);
public void addLogMessage(String message);
}
static Writer newWriter(File file) throws IOException {
return new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), ENCODING));
}
static BufferedReader newBufferedReader(File file) throws IOException {
return new BufferedReader(new InputStreamReader(new FileInputStream(file), ENCODING));
}
public static void main(String[] args) throws IOException {
final CompilerConfiguration config = CompilerConfiguration.read(new File(args[0]));
final CompilerOutput output = new CompilerOutput(new File(args[1]));
try {
compile(config, output);
} finally {
output.close();
}
}
private static void compile(final CompilerConfiguration config, final CompilerOutput output) {
final JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
if (compiler == null) {
output.addMessage(".", 0, 0, "No compiler is provided in this environment. " + "Perhaps you are running on a JRE rather than a JDK?", Kind.ERROR);
return;
}
final Charset sourceEncoding = config.getSourceEncoding();
final DiagnosticCollector diagnosticCollector = new DiagnosticCollector();
final StandardJavaFileManager standardFileManager = compiler.getStandardFileManager(diagnosticCollector, null, sourceEncoding);
final Iterable extends JavaFileObject> fileObjects = standardFileManager.getJavaFileObjectsFromFiles(config.getSources());
final Iterable options = config.getCompilerOptions();
final RecordingJavaFileManager recordingFileManager = new RecordingJavaFileManager(standardFileManager, sourceEncoding) {
@Override
protected void record(File inputFile, File outputFile) {
output.processOutput(inputFile, outputFile);
}
};
Writer stdout = new PrintWriter(System.out, true);
final JavaCompiler.CompilationTask task = compiler.getTask(stdout, // Writer out
recordingFileManager, // file manager
diagnosticCollector, // diagnostic listener
options, //
null, // Iterable classes to process by annotation processor(s)
fileObjects);
boolean success = task.call();
for (Diagnostic extends JavaFileObject> diagnostic : diagnosticCollector.getDiagnostics()) {
JavaFileObject source = diagnostic.getSource();
// when doing annotation processing, javac 6 reports errors when handwritten sources
// depend on generated sources even when overall compilation is reported as success
// to prevent false build failures, never issue ERROR messages after successful compilation
Kind kind = diagnostic.getKind();
if (success && kind == Kind.ERROR) {
kind = Kind.WARNING;
}
if (source != null) {
File file = FileObjects.toFile(source);
if (file != null) {
output.addMessage(file.getAbsolutePath(), (int) diagnostic.getLineNumber(), (int) diagnostic.getColumnNumber(), diagnostic.getMessage(null), kind);
} else {
output.addLogMessage(String.format("Unsupported compiler message on %s resource %s: %s", source.getKind(), source.toUri(), diagnostic.getMessage(null)));
}
} else {
output.addMessage(".", 0, 0, diagnostic.getMessage(null), kind);
}
}
}
}