Integrating loggers with some frameworks sometimes requires to wire some stream (OutputStream typically) to the logger itself.
Most of the time you pass to your “LoggerOutputStream” a Logger instance and a Level – or you have some condition in the implementation to select the level.
This is not a hard task but for some loggers you need a big switch to handle the level. Code is quite noisy for pretty much nothing.
With Java 8 the implementation is pretty simple, just use a method reference and that is it!
Nice thing is you can automatically type it “Consumer<String>.
Here is a sample with maven Log API:
import java.io.IOException; import java.io.OutputStream; import java.util.function.Consumer; import static java.util.Optional.of; public class LoggerOutputStream extends OutputStream { private static final int BUFFER_SIZE = 1024; private byte[] buffer; private int count; private int bufferLen; private final Consumer<String> log; public LoggerOutputStream(final Consumer<String> log) { this.log = log; this.bufferLen = BUFFER_SIZE; this.buffer = new byte[bufferLen]; this.count = 0; } @Override public void write(final int b) throws IOException { if (b == 0 || b == '\n') { flush(); return; } if (count == bufferLen) { final byte[] newBuf = new byte[bufferLen + BUFFER_SIZE]; System.arraycopy(buffer, 0, newBuf, 0, bufferLen); buffer = newBuf; bufferLen = newBuf.length; } buffer[count] = (byte) b; count++; } @Override public void flush() { of(count).filter(c -> c > 0).ifPresent(c -> { log.accept(new String(buffer, 0, c)); count = 0; }); } @Override public void close() { flush(); } }
And the usage is then pretty simple as well:
// getLog() is available in a Mojo = maven plugin OutputStream out = new LoggerOutputStream(getLog()::info);
The interesting part is a bit hidden but you need to look for the method ref usage (log.accept(new String(buffer, 0, c));) where actually without it you would get a big switch to handle it so it is a nice win regarding the simplicity of the code and its evolutivity!