RedirectConsole.java
package gov.usgs.util.logging;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.PrintStream;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
/**
* Console redirection utility.
*
* Replaces system.out and system.err with
* printstreams that log all writes when flushed.
*/
public class RedirectConsole {
/** Logger to handle writes to system.err. */
private static final Logger SYSTEM_ERR_LOGGER = Logger
.getLogger("system.err");
/** Logger to handle writes to system.out. */
private static final Logger SYSTEM_OUT_LOGGER = Logger
.getLogger("system.out");
/** The previous system.err stream. */
private static PrintStream PREVIOUS_SYSTEM_ERR;
/** The previous system.out.stream. */
private static PrintStream PREVIOUS_SYSTEM_OUT;
/**
* Redirect System.out and System.err to java.util.logging.Logger objects.
*
* System.out is redirected to logger "system.out". System.err is redirected
* to logger "system.err".
*
* Use the cancel method to undo this redirection.
*/
public static void redirect() {
if (PREVIOUS_SYSTEM_ERR != null || PREVIOUS_SYSTEM_OUT != null) {
cancel();
}
PREVIOUS_SYSTEM_OUT = System.out;
System.setOut(new LoggerPrintStream("STDOUT", SYSTEM_OUT_LOGGER));
PREVIOUS_SYSTEM_ERR = System.err;
System.setErr(new LoggerPrintStream("STDERR", SYSTEM_ERR_LOGGER));
}
/**
* Undo a redirection previously setup using redirect().
*
* Restores System.out and System.err to their state before redirect was
* called.
*/
public static void cancel() {
if (PREVIOUS_SYSTEM_OUT != null) {
// flush any pending output
System.out.flush();
// restore previous output stream
System.setOut(PREVIOUS_SYSTEM_OUT);
PREVIOUS_SYSTEM_OUT = null;
}
if (PREVIOUS_SYSTEM_ERR != null) {
// flush any pending output
System.err.flush();
// restore previous error stream
System.setErr(PREVIOUS_SYSTEM_ERR);
PREVIOUS_SYSTEM_ERR = null;
}
}
/**
* A PrintStream that writes messages to a Logger object.
*/
private static class LoggerPrintStream extends PrintStream {
/** Name for output, prepended to LogRecord. */
private String name;
/** Logger used when flush is called. */
private Logger logger;
public LoggerPrintStream(final String name, final Logger logger) {
// true is for autoflush
super(new ByteArrayOutputStream(), true);
this.name = name;
this.logger = logger;
}
/**
* Override to force synchronization.
*/
@Override
public synchronized void write(final byte[] b) throws IOException {
super.write(b);
}
/**
* Override to force synchronization.
*/
@Override
public synchronized void write(final int b) {
super.write(b);
}
/**
* Override to force synchronization.
*/
@Override
public synchronized void write(final byte[] buf, final int off,
final int len) {
super.write(buf, off, len);
}
/**
* Flush forces message to be written to log file.
*/
@Override
public synchronized void flush() {
ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
try {
logger.log(new LogRecord(Level.INFO, this.name + " "
+ baos.toString().trim()));
} finally {
// tried to write at least, clear buffer...
out = new ByteArrayOutputStream();
}
}
}
}