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
  12.  * printstreams that log all writes when flushed.
  13.  */
  14. public class RedirectConsole {

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

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

  21.     /** The previous system.err stream. */
  22.     private static PrintStream PREVIOUS_SYSTEM_ERR;

  23.     /** The previous system.out.stream. */
  24.     private static PrintStream PREVIOUS_SYSTEM_OUT;

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

  37.         PREVIOUS_SYSTEM_OUT = System.out;
  38.         System.setOut(new LoggerPrintStream("STDOUT", SYSTEM_OUT_LOGGER));

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

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

  64.     /**
  65.      * A PrintStream that writes messages to a Logger object.
  66.      */
  67.     private static class LoggerPrintStream extends PrintStream {

  68.         /** Name for output, prepended to LogRecord. */
  69.         private String name;

  70.         /** Logger used when flush is called. */
  71.         private Logger logger;

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

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

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

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

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

  114.     }

  115. }