/*
* Copyright 2012-present Facebook, Inc.
*
* 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 com.facebook.buck.util;
import com.google.common.base.StandardSystemProperty;
import com.google.common.collect.ImmutableList;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
import java.util.concurrent.Callable;
public final class InputStreamConsumer implements Callable<Void> {
/** Interface to handle a line of input from the stream. */
public interface Handler {
void handleLine(String line);
}
private final LineFetcher inputReader;
private final ImmutableList<Handler> handlers;
public InputStreamConsumer(InputStream inputStream, Handler... handlers) {
this(new InputStreamReader(inputStream), handlers);
}
public InputStreamConsumer(Reader reader, Handler... handlers) {
this.inputReader = new LineFetcher(reader);
this.handlers = ImmutableList.copyOf(handlers);
}
@Override
public Void call() throws IOException {
String line;
while ((line = inputReader.readLine()) != null) {
for (Handler handler : handlers) {
handler.handleLine(line);
}
}
return null;
}
public static Handler createAnsiHighlightingHandler(
boolean flagOutputWrittenToStream, PrintStream printStream, Ansi ansi) {
return new HighlightingOutput(flagOutputWrittenToStream, printStream, ansi);
}
private static class HighlightingOutput implements Handler {
private static final String LINE_SEPARATOR = StandardSystemProperty.LINE_SEPARATOR.value();
private final boolean flagOutputWrittenToStream;
private final PrintStream printStream;
private final Ansi ansi;
public HighlightingOutput(
boolean flagOutputWrittenToStream, PrintStream printStream, Ansi ansi) {
this.flagOutputWrittenToStream = flagOutputWrittenToStream;
this.printStream = printStream;
this.ansi = ansi;
}
@Override
public void handleLine(String line) {
String highlightOn = flagOutputWrittenToStream ? ansi.getHighlightedWarningSequence() : "";
String highlightOff = flagOutputWrittenToStream ? ansi.getHighlightedResetSequence() : "";
// We pass `line + LINE_SEPARATOR` to print() rather than invoke println() because
// we want the line and the separator to be guaranteed to be printed together.
// println() is implemented by calling print() then newLine(). Because those calls could be
// interleaved when stdout and stderr are being consumed simultaneously (and I have seen
// this happen), then you could end up with confusing output when stdout and stderr are
// connected to the same terminal (which is often the case).
printStream.print(highlightOn + line + LINE_SEPARATOR + highlightOff);
}
}
}