LogStream.java |
package ij.io; import ij.IJ; import java.io.ByteArrayOutputStream; import java.io.PrintStream; /** * This class provides the functionality to divert output sent to the System.out * and System.err streams to ImageJ's log console. The purpose is to allow * use of existing Java classes or writing new generic Java classes that only * output to System.out and are thus less dependent on ImageJ. * See the ImageJ plugin Redirect_System_Streams at * http://staff.fh-hagenberg.at/burger/imagej/ * for usage examples. * * @author Wilhelm Burger (wilbur at ieee.org) * See Also: Redirect_System_Streams (http://staff.fh-hagenberg.at/burger/imagej/) */ public class LogStream extends PrintStream { private static String outPrefix = "out> "; // prefix string for System.out private static String errPrefix = "err >"; // prefix string for System.err private static PrintStream originalSystemOut = null; private static PrintStream originalSystemErr = null; private static PrintStream temporarySystemOut = null; private static PrintStream temporarySystemErr = null; /** * Redirects all output sent to <code>System.out</code> and <code>System.err</code> to ImageJ's log console * using the default prefixes. */ public static void redirectSystem(boolean redirect) { if (redirect) redirectSystem(); else revertSystem(); } /** * Redirects all output sent to <code>System.out</code> and <code>System.err</code> to ImageJ's log console * using the default prefixes. * Alternatively use * {@link #redirectSystemOut(String)} and {@link #redirectSystemErr(String)} * to redirect the streams separately and to specify individual prefixes. */ public static void redirectSystem() { redirectSystemOut(outPrefix); redirectSystemErr(errPrefix); } /** * Redirects all output sent to <code>System.out</code> to ImageJ's log console. * @param prefix The prefix string inserted at the start of each output line. * Pass <code>null</code> to use the default prefix or an empty string to * remove the prefix. */ public static void redirectSystemOut(String prefix) { if (originalSystemOut == null) { // has no effect if System.out is already replaced originalSystemOut = System.out; // remember the original System.out stream temporarySystemOut = new LogStream(prefix); System.setOut(temporarySystemOut); } } /** * Redirects all output sent to <code>System.err</code> to ImageJ's log console. * @param prefix The prefix string inserted at the start of each output line. * Pass <code>null</code> to use the default prefix or an empty string to * remove the prefix. */ public static void redirectSystemErr(String prefix) { if (originalSystemErr == null) { // has no effect if System.out is already replaced originalSystemErr = System.err; // remember the original System.out stream temporarySystemErr = new LogStream(prefix); System.setErr(temporarySystemErr); } } /** * Returns the redirection stream for {@code System.out} if it exists. * Note that a reference to the current output stream can also be obtained directly from * the {@code System.out} field. * @return A reference to the {@code PrintStream} object currently substituting {@code System.out} * or {@code null} of if {@code System.out} is currently not redirected. */ public static PrintStream getCurrentOutStream() { return temporarySystemOut; } /** * Returns the redirection stream for {@code System.err} if it exists. * Note that a reference to the current output stream can also be obtained directly from * the {@code System.err} field. * @return A reference to the {@code PrintStream} object currently substituting {@code System.err} * or {@code null} of if {@code System.err} is currently not redirected. */ public static PrintStream getCurrentErrStream() { return temporarySystemErr; } /** * Use this method to revert both <code>System.out</code> and <code>System.err</code> * to their original output streams. */ public static void revertSystem() { revertSystemOut(); revertSystemErr(); } /** * Use this method to revert<code>System.out</code> * to the original output stream. */ public static void revertSystemOut() { if (originalSystemOut != null && temporarySystemOut != null) { temporarySystemOut.flush(); temporarySystemOut.close(); System.setOut(originalSystemOut); originalSystemOut = null; temporarySystemOut = null; } } /** * Use this method to revert<code>System.err</code> * to the original output stream. */ public static void revertSystemErr() { if (originalSystemErr != null && temporarySystemErr != null) { temporarySystemErr.flush(); temporarySystemErr.close(); System.setErr(originalSystemErr); originalSystemErr = null; temporarySystemErr = null; } } // ---------------------------------------------------------------- private final String endOfLineSystem = System.getProperty("line.separator"); private final String endOfLineShort = String.format("\n"); private final ByteArrayOutputStream byteStream; private final String prefix; public LogStream() { super(new ByteArrayOutputStream()); this.byteStream = (ByteArrayOutputStream) this.out; this.prefix = ""; } private LogStream(String prefix) { super(new ByteArrayOutputStream()); this.byteStream = (ByteArrayOutputStream) this.out; this.prefix = (prefix == null) ? "" : prefix; } @Override // ever called? public void write(byte[] b) { this.write(b, 0, b.length); } @Override public void write(byte[] b, int off, int len) { String msg = new String(b, off, len); if (msg.equals(endOfLineSystem) || msg.equals(endOfLineShort)) { // this is a newline sequence only ejectBuffer(); } else { byteStream.write(b, off, len); // append message to buffer if (msg.endsWith(endOfLineSystem) || msg.endsWith(endOfLineShort)) { // line terminated by Newline // note that this does not seem to happen ever (even with format)!? ejectBuffer(); } } } @Override // ever called? public void write(int b) { byteStream.write(b); } @Override public void flush() { if (byteStream.size() > 0) { String msg = byteStream.toString(); if (msg.endsWith(endOfLineSystem) || msg.endsWith(endOfLineShort)) ejectBuffer(); } super.flush(); } @Override public void close() { super.close(); } private void ejectBuffer() { IJ.log(prefix + byteStream.toString()); byteStream.reset(); } }