RedirectConsole.java

  1. package gov.usgs.util.logging;

  2. import java.io.ByteArrayOutputStream;
  3. import java.io.IOException;
  4. import java.io.PrintStream;
  5. import java.util.logging.Level;
  6. import java.util.logging.LogRecord;
  7. import java.util.logging.Logger;

  8. /**
  9.  * Console redirection utility.
  10.  *
  11.  * Replaces system.out and system.err with printstreams that log all writes when
  12.  * flushed.
  13.  */
  14. public class RedirectConsole {

  15.   /** Logger to handle writes to system.err. */
  16.   private static final Logger SYSTEM_ERR_LOGGER = Logger.getLogger("system.err");

  17.   /** Logger to handle writes to system.out. */
  18.   private static final Logger SYSTEM_OUT_LOGGER = Logger.getLogger("system.out");

  19.   /** The previous system.err stream. */
  20.   private static PrintStream PREVIOUS_SYSTEM_ERR;

  21.   /** The previous system.out.stream. */
  22.   private static PrintStream PREVIOUS_SYSTEM_OUT;

  23.   /**
  24.    * Redirect System.out and System.err to java.util.logging.Logger objects.
  25.    *
  26.    * System.out is redirected to logger "system.out". System.err is redirected to
  27.    * logger "system.err".
  28.    *
  29.    * Use the cancel method to undo this redirection.
  30.    */
  31.   public static void redirect() {
  32.     if (PREVIOUS_SYSTEM_ERR != null || PREVIOUS_SYSTEM_OUT != null) {
  33.       cancel();
  34.     }

  35.     PREVIOUS_SYSTEM_OUT = System.out;
  36.     System.setOut(new LoggerPrintStream("STDOUT", SYSTEM_OUT_LOGGER));

  37.     PREVIOUS_SYSTEM_ERR = System.err;
  38.     System.setErr(new LoggerPrintStream("STDERR", SYSTEM_ERR_LOGGER));
  39.   }

  40.   /**
  41.    * Undo a redirection previously setup using redirect().
  42.    *
  43.    * Restores System.out and System.err to their state before redirect was called.
  44.    */
  45.   public static void cancel() {
  46.     if (PREVIOUS_SYSTEM_OUT != null) {
  47.       // flush any pending output
  48.       System.out.flush();
  49.       // restore previous output stream
  50.       System.setOut(PREVIOUS_SYSTEM_OUT);
  51.       PREVIOUS_SYSTEM_OUT = null;
  52.     }
  53.     if (PREVIOUS_SYSTEM_ERR != null) {
  54.       // flush any pending output
  55.       System.err.flush();
  56.       // restore previous error stream
  57.       System.setErr(PREVIOUS_SYSTEM_ERR);
  58.       PREVIOUS_SYSTEM_ERR = null;
  59.     }
  60.   }

  61.   /**
  62.    * A PrintStream that writes messages to a Logger object.
  63.    */
  64.   private static class LoggerPrintStream extends PrintStream {

  65.     /** Name for output, prepended to LogRecord. */
  66.     private String name;

  67.     /** Logger used when flush is called. */
  68.     private Logger logger;

  69.     public LoggerPrintStream(final String name, final Logger logger) {
  70.       // true is for autoflush
  71.       super(new ByteArrayOutputStream(), true);
  72.       this.name = name;
  73.       this.logger = logger;
  74.     }

  75.     /**
  76.      * Override to force synchronization.
  77.      */
  78.     @Override
  79.     public synchronized void write(final byte[] b) throws IOException {
  80.       super.write(b);
  81.     }

  82.     /**
  83.      * Override to force synchronization.
  84.      */
  85.     @Override
  86.     public synchronized void write(final int b) {
  87.       super.write(b);
  88.     }

  89.     /**
  90.      * Override to force synchronization.
  91.      */
  92.     @Override
  93.     public synchronized void write(final byte[] buf, final int off, final int len) {
  94.       super.write(buf, off, len);
  95.     }

  96.     /**
  97.      * Flush forces message to be written to log file.
  98.      */
  99.     @Override
  100.     public synchronized void flush() {
  101.       ByteArrayOutputStream baos = (ByteArrayOutputStream) out;
  102.       try {
  103.         logger.log(new LogRecord(Level.INFO, this.name + " " + baos.toString().trim()));
  104.       } finally {
  105.         // tried to write at least, clear buffer...
  106.         out = new ByteArrayOutputStream();
  107.       }
  108.     }

  109.   }

  110. }