blob: 54c8f51019c7f7c3a06431a78d676d638804d740 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* 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 vogar;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.List;
import java.util.logging.ConsoleHandler;
import java.util.logging.Formatter;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
/**
* Controls, formats and emits output to the command line. Command line output
* can be generated both by java.util.logging and by direct calls to this class.
*/
public class Console {
private final boolean stream;
private final boolean color;
private final String indent;
private String currentName;
private CurrentLine currentLine = CurrentLine.NEW;
private final StringBuilder bufferedOutput = new StringBuilder();
public Console(boolean stream, String indent, boolean color) {
this.stream = stream;
this.indent = indent;
this.color = color;
}
public void configureJavaLogging(boolean verbose) {
ConsoleHandler handler = new ConsoleHandler();
handler.setLevel(Level.ALL);
handler.setFormatter(new Formatter() {
@Override public String format(LogRecord r) {
return logRecordToString(r);
}
});
Logger logger = Logger.getLogger("vogar");
logger.setLevel(verbose ? Level.FINE : Level.INFO);
logger.addHandler(handler);
logger.setUseParentHandlers(false);
}
/**
* Formats a sequence of regular log messages with the output streamed from
* a foreign process.
*/
private String logRecordToString(LogRecord logRecord) {
String message = logRecord.getMessage();
if (logRecord.getThrown() != null) {
StringWriter writer = new StringWriter();
writer.write(message);
writer.write("\n");
logRecord.getThrown().printStackTrace(new PrintWriter(writer));
message = writer.toString();
}
newLine();
return message + "\n";
}
public void action(String name) {
newLine();
System.out.print("Action " + name);
currentName = name;
currentLine = CurrentLine.NAME;
}
/**
* Prints the beginning of the named outcome.
*/
public void outcome(String name) {
// if the outcome and action names are the same, omit the outcome name
if (name.equals(currentName)) {
return;
}
currentName = name;
newLine();
System.out.print(indent + name);
currentLine = CurrentLine.NAME;
}
/**
* Appends the action output immediately to the stream when streaming is on,
* or to a buffer when streaming is off. Buffered output will be held and
* printed only if the outcome is unsuccessful.
*/
public void streamOutput(String output) {
if (stream) {
printOutput(output);
} else {
bufferedOutput.append(output);
}
}
/**
* Writes the action's outcome.
*/
public void printResult(Result result, boolean ok) {
if (ok) {
String prefix = (currentLine == CurrentLine.NAME) ? " " : "\n" + indent;
System.out.println(prefix + green("OK (" + result + ")"));
} else {
if (bufferedOutput.length() > 0) {
printOutput(bufferedOutput.toString());
bufferedOutput.delete(0, bufferedOutput.length());
}
newLine();
System.out.println(indent + red("FAIL (" + result + ")"));
}
currentName = null;
currentLine = CurrentLine.NEW;
}
public void summarizeFailures(List<String> failureNames) {
System.out.println("Failure summary:");
for (String failureName : failureNames) {
System.out.println(red(failureName));
}
}
/**
* Prints the action output with appropriate indentation.
*/
private void printOutput(String streamedOutput) {
String[] lines = messageToLines(streamedOutput);
if (currentLine != CurrentLine.STREAMED_OUTPUT) {
newLine();
System.out.print(indent);
System.out.print(indent);
}
System.out.print(lines[0]);
currentLine = CurrentLine.STREAMED_OUTPUT;
for (int i = 1; i < lines.length; i++) {
newLine();
if (lines[i].length() > 0) {
System.out.print(indent);
System.out.print(indent);
System.out.print(lines[i]);
currentLine = CurrentLine.STREAMED_OUTPUT;
}
}
}
/**
* Inserts a linebreak if necessary.
*/
private void newLine() {
if (currentLine == CurrentLine.NEW) {
return;
}
System.out.println();
currentLine = CurrentLine.NEW;
}
/**
* Status of a currently-in-progress line of output.
*/
enum CurrentLine {
/**
* The line is blank.
*/
NEW,
/**
* The line contains streamed application output. Additional streamed
* output may be appended without additional line separators or
* indentation.
*/
STREAMED_OUTPUT,
/**
* The line contains the name of an action or outcome. The outcome's
* result (such as "OK") can be appended without additional line
* separators or indentation.
*/
NAME,
}
/**
* Returns an array containing the lines of the given text.
*/
private String[] messageToLines(String message) {
// pass Integer.MAX_VALUE so split doesn't trim trailing empty strings.
return message.split("\r\n|\r|\n", Integer.MAX_VALUE);
}
private String green(String message) {
return color ? ("\u001b[32;1m" + message + "\u001b[0m") : message;
}
private String red(String message) {
return color ? ("\u001b[31;1m" + message + "\u001b[0m") : message;
}
}