diff options
Diffstat (limited to 'jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacMessageHandler.java')
-rw-r--r-- | jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacMessageHandler.java | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacMessageHandler.java b/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacMessageHandler.java new file mode 100644 index 000000000000..fd5bc65d1e5b --- /dev/null +++ b/jps/jps-builders/src/org/jetbrains/jps/javac/ExternalJavacMessageHandler.java @@ -0,0 +1,230 @@ +/* + * Copyright 2000-2014 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.jetbrains.jps.javac; + +import com.google.protobuf.ByteString; +import com.google.protobuf.MessageLite; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jps.incremental.BinaryContent; + +import javax.tools.*; +import java.io.File; +import java.net.URI; +import java.util.Collection; +import java.util.Locale; + +/** + * @author Eugene Zhuravlev + * Date: 1/22/12 + */ +public class ExternalJavacMessageHandler { + private final DiagnosticOutputConsumer myDiagnosticSink; + private final OutputFileConsumer myOutputSink; + @Nullable + private final String myEncodingName; + private volatile boolean myTerminatedSuccessfully; + + public ExternalJavacMessageHandler(DiagnosticOutputConsumer diagnosticSink, + OutputFileConsumer outputSink, + @Nullable final String encodingName) { + myDiagnosticSink = diagnosticSink; + myOutputSink = outputSink; + myEncodingName = encodingName; + } + + public boolean handleMessage(MessageLite message) { + try { + final JavacRemoteProto.Message msg = (JavacRemoteProto.Message)message; + final JavacRemoteProto.Message.Type messageType = msg.getMessageType(); + + if (messageType == JavacRemoteProto.Message.Type.RESPONSE) { + final JavacRemoteProto.Message.Response response = msg.getResponse(); + final JavacRemoteProto.Message.Response.Type responseType = response.getResponseType(); + + if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_MESSAGE) { + final JavacRemoteProto.Message.Response.CompileMessage compileMessage = response.getCompileMessage(); + final JavacRemoteProto.Message.Response.CompileMessage.Kind messageKind = compileMessage.getKind(); + + if (messageKind == JavacRemoteProto.Message.Response.CompileMessage.Kind.STD_OUT) { + if (compileMessage.hasText()) { + myDiagnosticSink.outputLineAvailable(compileMessage.getText()); + } + } + else { + final String sourceUri = compileMessage.hasSourceUri()? compileMessage.getSourceUri() : null; + final JavaFileObject srcFileObject = sourceUri != null? new DummyJavaFileObject(URI.create(sourceUri)) : null; + myDiagnosticSink.report(new DummyDiagnostic(convertKind(messageKind), srcFileObject, compileMessage)); + } + + return false; + } + + if (responseType == JavacRemoteProto.Message.Response.Type.OUTPUT_OBJECT) { + final JavacRemoteProto.Message.Response.OutputObject outputObject = response.getOutputObject(); + final JavacRemoteProto.Message.Response.OutputObject.Kind kind = outputObject.getKind(); + + final String outputRoot = outputObject.hasOutputRoot()? outputObject.getOutputRoot() : null; + final File outputRootFile = outputRoot != null? new File(outputRoot) : null; + + final BinaryContent fileObjectContent; + final ByteString content = outputObject.hasContent()? outputObject.getContent() : null; + if (content != null) { + final byte[] bytes = content.toByteArray(); + fileObjectContent = new BinaryContent(bytes, 0, bytes.length); + } + else { + fileObjectContent = null; + } + + final String sourceUri = outputObject.hasSourceUri()? outputObject.getSourceUri() : null; + final URI srcUri = sourceUri != null? URI.create(sourceUri) : null; + final OutputFileObject fileObject = new OutputFileObject( + null, + outputRootFile, + outputObject.hasRelativePath()? outputObject.getRelativePath() : null, + new File(outputObject.getFilePath()), + convertKind(kind), + outputObject.hasClassName()? outputObject.getClassName() : null, + srcUri, + myEncodingName, fileObjectContent + ); + + myOutputSink.save(fileObject); + return false; + } + + if (responseType == JavacRemoteProto.Message.Response.Type.SRC_FILE_LOADED) { + final JavacRemoteProto.Message.Response.OutputObject outputObject = response.getOutputObject(); + final File file = new File(outputObject.getFilePath()); + myDiagnosticSink.javaFileLoaded(file); + return false; + } + + if (responseType == JavacRemoteProto.Message.Response.Type.CLASS_DATA) { + final JavacRemoteProto.Message.Response.ClassData data = response.getClassData(); + final String className = data.getClassName(); + final Collection<String> imports = data.getImportStatementList(); + final Collection<String> staticImports = data.getStaticImportList(); + myDiagnosticSink.registerImports(className, imports, staticImports); + return false; + } + + if (responseType == JavacRemoteProto.Message.Response.Type.BUILD_COMPLETED) { + if (response.hasCompletionStatus()) { + myTerminatedSuccessfully = response.getCompletionStatus(); + } + return true; + } + + throw new Exception("Unsupported response type: " + responseType.name()); + } + + if (messageType == JavacRemoteProto.Message.Type.FAILURE) { + final JavacRemoteProto.Message.Failure failure = msg.getFailure(); + final StringBuilder buf = new StringBuilder(); + if (failure.hasDescription()) { + buf.append(failure.getDescription()); + } + if (failure.hasStacktrace()) { + if (buf.length() > 0) { + buf.append("\n"); + } + buf.append(failure.getStacktrace()); + } + myDiagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, buf.toString())); + return true; + } + + throw new Exception("Unsupported message type: " + messageType.name()); + } + catch (Throwable e) { + myDiagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage())); + return true; + } + } + + public boolean isTerminatedSuccessfully() { + return myTerminatedSuccessfully; + } + + private static Diagnostic.Kind convertKind(JavacRemoteProto.Message.Response.CompileMessage.Kind kind) { + switch (kind) { + case ERROR: return Diagnostic.Kind.ERROR; + case WARNING: return Diagnostic.Kind.WARNING; + case MANDATORY_WARNING: return Diagnostic.Kind.MANDATORY_WARNING; + case NOTE: return Diagnostic.Kind.NOTE; + default : return Diagnostic.Kind.OTHER; + } + } + + private static OutputFileObject.Kind convertKind(JavacRemoteProto.Message.Response.OutputObject.Kind kind) { + switch (kind) { + case CLASS: return JavaFileObject.Kind.CLASS; + case HTML: return JavaFileObject.Kind.HTML; + case SOURCE: return JavaFileObject.Kind.SOURCE; + default : return JavaFileObject.Kind.OTHER; + } + } + + private static class DummyDiagnostic implements Diagnostic<JavaFileObject> { + + private final Kind myMessageKind; + private final JavaFileObject mySrcFileObject; + private final JavacRemoteProto.Message.Response.CompileMessage myCompileMessage; + + public DummyDiagnostic(final Kind messageKind, JavaFileObject srcFileObject, JavacRemoteProto.Message.Response.CompileMessage compileMessage) { + myMessageKind = messageKind; + mySrcFileObject = srcFileObject; + myCompileMessage = compileMessage; + } + + public Kind getKind() { + return myMessageKind; + } + + public JavaFileObject getSource() { + return mySrcFileObject; + } + + public long getPosition() { + return myCompileMessage.hasProblemLocationOffset()? myCompileMessage.getProblemLocationOffset() : -1; + } + + public long getStartPosition() { + return myCompileMessage.hasProblemBeginOffset()? myCompileMessage.getProblemBeginOffset() : -1; + } + + public long getEndPosition() { + return myCompileMessage.hasProblemEndOffset()? myCompileMessage.getProblemEndOffset() : -1; + } + + public long getLineNumber() { + return myCompileMessage.hasLine()? myCompileMessage.getLine() : -1; + } + + public long getColumnNumber() { + return myCompileMessage.hasColumn()? myCompileMessage.getColumn() : -1; + } + + public String getCode() { + return null; + } + + public String getMessage(Locale locale) { + return myCompileMessage.hasText()? myCompileMessage.getText() : null; + } + } +} |