/* * Copyright 2010-2012 napile.org * * 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.napile.thermit.idea.runner; import java.io.PrintStream; import java.io.PrintWriter; import java.io.StringWriter; import org.napile.thermit.BuildEvent; import org.napile.thermit.DefaultLogger; import org.napile.thermit.Project; import com.intellij.rt.execution.junit.segments.PacketWriter; import com.intellij.rt.execution.junit.segments.SegmentedOutputStream; public final class IdeaThermitLogger2 extends DefaultLogger { static SegmentedOutputStream ourErr; public static final char MESSAGE_CONTENT = 'M'; public static final char EXCEPTION_CONTENT = 'X'; public static final char INPUT_REQUEST = 'I'; public static final char BUILD_END = 'b'; public static final char BUILD = 'B'; public static final char TARGET = 'G'; public static final char TARGET_END = 'g'; public static final char TASK = 'T'; public static final char TASK_END = 't'; public static final char MESSAGE = 'M'; public static final char ERROR = 'E'; public static final char EXCEPTION = 'X'; public static final char EXCEPTION_LINE_SEPARATOR = 0; /** * @noinspection HardCodedStringLiteral */ public static final String OUTPUT_PREFIX = "IDEA_ANT_INTEGRATION"; private final Priority myMessagePriority = new MessagePriority(); private final Priority myTargetPriority = new StatePriority(Project.MSG_INFO); private final Priority myTaskPriority = new StatePriority(Project.MSG_INFO); private final Priority myAlwaysSend = new Priority() { public void setPriority(int level) { } protected boolean shouldSend(int priority) { return true; } }; public IdeaThermitLogger2() { guardStreams(); } public synchronized void setMessageOutputLevel(int level) { super.setMessageOutputLevel(level); myMessagePriority.setPriority(level); myTargetPriority.setPriority(level); myTaskPriority.setPriority(level); myAlwaysSend.setPriority(level); } public synchronized void buildStarted(BuildEvent event) { myAlwaysSend.sendMessage(BUILD, event.getPriority(), ""); } public synchronized void buildFinished(BuildEvent event) { myAlwaysSend.sendMessage(BUILD_END, event.getPriority(), event.getException()); } public synchronized void targetStarted(BuildEvent event) { myTargetPriority.sendMessage(TARGET, event.getPriority(), event.getTarget().getName()); } public synchronized void targetFinished(BuildEvent event) { sendException(event); myTargetPriority.sendMessage(TARGET_END, event.getPriority(), event.getException()); } public synchronized void taskStarted(BuildEvent event) { myTaskPriority.sendMessage(TASK, event.getPriority(), event.getTask().getTaskName()); } public synchronized void taskFinished(BuildEvent event) { sendException(event); myTaskPriority.sendMessage(TASK_END, event.getPriority(), event.getException()); } public synchronized void messageLogged(BuildEvent event) { if(sendException(event)) return; int priority = event.getPriority(); String message = event.getMessage(); if(priority == Project.MSG_ERR) myMessagePriority.sendMessage(ERROR, priority, message); else myMessagePriority.sendMessage(MESSAGE, priority, message); } private boolean sendException(BuildEvent event) { Throwable exception = event.getException(); if(exception != null) { myAlwaysSend.sendMessage(EXCEPTION, event.getPriority(), exception); return true; } return false; } public static void guardStreams() { if(ourErr != null) { return; } PrintStream err = System.err; ourErr = new SegmentedOutputStream(err); System.setErr(new PrintStream(ourErr)); ourErr.sendStart(); } private void send(PacketWriter packet) { packet.sendThrough(ourErr); } private PacketWriter createPacket(char id, int priority) { PacketWriter packet = PacketFactory.ourInstance.createPacket(id); packet.appendLong(priority); return packet; } private abstract class Priority { protected void peformSendMessage(char id, int priority, String text) { PacketWriter packet = createPacket(id, priority); packet.appendChar(MESSAGE_CONTENT); packet.appendLimitedString(text); send(packet); } protected void peformSendMessage(char id, int priority, Throwable throwable) { if(throwable != null) { PacketWriter packet = createPacket(id, priority); StringWriter stackTrace = new StringWriter(); throwable.printStackTrace(new PrintWriter(stackTrace)); packet.appendChar(EXCEPTION_CONTENT); packet.appendLimitedString(stackTrace.toString()); send(packet); } else { peformSendMessage(id, priority, ""); } } public void sendMessage(char id, int priority, String text) { if(shouldSend(priority)) peformSendMessage(id, priority, text); } public void sendMessage(char id, int priority, Throwable throwable) { if(shouldSend(priority)) peformSendMessage(id, priority, throwable); } public abstract void setPriority(int level); protected abstract boolean shouldSend(int priority); } private class MessagePriority extends Priority { private int myPriority = Project.MSG_ERR; public void setPriority(int level) { myPriority = level; } protected boolean shouldSend(int priority) { return priority <= myPriority; } } private class StatePriority extends Priority { private boolean myEnabled = true; private final int myMinLevel; public StatePriority(int minLevel) { myMinLevel = minLevel; } public void setPriority(int level) { myEnabled = myMinLevel <= level; } protected boolean shouldSend(int priority) { return myEnabled; } } }