blob: 49ac0fc20dca1a4a9161917071e514b6dc44d1c0 [file] [log] [blame]
/*
* 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.Optional;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.io.Reader;
public final class InputStreamConsumer implements Runnable {
/**
* Interface to handle a line of input from the stream.
*/
public interface Handler {
public void handleLine(String line);
}
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
private final BufferedReader inputReader;
private final PrintStream printStream;
private final Ansi ansi;
private final boolean flagOutputWrittenToStream;
private final Optional<Handler> handler;
private boolean hasWrittenOutputToPrintStream = false;
/**
* @param shouldFlagOutputWrittenToStream If {@code true}, any output in this stream will be
* flagged in the console using ANSI escape codes, if appropriate.
*/
public InputStreamConsumer(InputStream inputStream,
PrintStream printStream,
Ansi ansi,
boolean shouldFlagOutputWrittenToStream,
Optional<Handler> handler) {
this(
new InputStreamReader(inputStream),
printStream,
ansi,
shouldFlagOutputWrittenToStream,
handler);
}
public InputStreamConsumer(Reader reader,
PrintStream printStream,
Ansi ansi,
boolean flagOutputWrittenToStream,
Optional<Handler> handler) {
this.inputReader = new BufferedReader(reader);
this.printStream = printStream;
this.ansi = ansi;
this.flagOutputWrittenToStream = flagOutputWrittenToStream;
this.handler = handler;
}
@Override
public void run() {
String line;
try {
while ((line = inputReader.readLine()) != null) {
if (handler.isPresent()) {
handler.get().handleLine(line);
}
if (!hasWrittenOutputToPrintStream && flagOutputWrittenToStream) {
printStream.print(ansi.getHighlightedWarningSequence());
hasWrittenOutputToPrintStream = true;
}
// 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(line + LINE_SEPARATOR);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (hasWrittenOutputToPrintStream) {
printStream.print(ansi.getHighlightedResetSequence());
}
}
}
}