TimeoutOutputStream.java

  1. package gov.usgs.earthquake.util;

  2. import java.io.FilterOutputStream;
  3. import java.io.IOException;
  4. import java.io.OutputStream;

  5. /**
  6.  * An output stream that self-closes if the specified timeout elapses between
  7.  * writes.
  8.  */
  9. public class TimeoutOutputStream extends FilterOutputStream implements Runnable {

  10.     /** write timeout in milliseconds. */
  11.     private final long timeout;
  12.     /** thread that enforces timeout. */
  13.     private final Thread timeoutThread;
  14.     /** flag for timeoutThread to terminate. */
  15.     private boolean closed = false;

  16.     /**
  17.      * Create a TimeoutOutputStream.
  18.      *
  19.      * @param out
  20.      *            the wrapped output stream.
  21.      * @param timeout
  22.      *            the timeout in milliseconds between writes. If this timeout
  23.      *            completes, the underlying stream will be closed.
  24.      */
  25.     public TimeoutOutputStream(final OutputStream out, final long timeout) {
  26.         super(out);
  27.         this.timeout = timeout;
  28.         this.timeoutThread = new Thread(this);
  29.         this.timeoutThread.start();
  30.     }

  31.     @Override
  32.     public void write(int b) throws IOException {
  33.         // pass directly to underlying stream
  34.         this.out.write(b);
  35.         timeoutThread.interrupt();
  36.     }

  37.     @Override
  38.     public void write(byte[] buf) throws IOException {
  39.         // pass directly to underlying stream
  40.         this.out.write(buf);
  41.         timeoutThread.interrupt();
  42.     }

  43.     @Override
  44.     public void write(byte[] buf, int offset, int length) throws IOException {
  45.         // pass directly to underlying stream
  46.         this.out.write(buf, offset, length);
  47.         timeoutThread.interrupt();
  48.     }

  49.     @Override
  50.     public void close() throws IOException {
  51.         closed = true;
  52.         try {
  53.             super.close();
  54.         } finally {
  55.             // interrupt in case close called from outside timeoutThread
  56.             timeoutThread.interrupt();
  57.         }
  58.     }

  59.     @Override
  60.     public void run() {
  61.         while (!closed) {
  62.             try {
  63.                 // wait for timeout milliseconds
  64.                 Thread.sleep(timeout);
  65.                 // timeout elapsed, close stream
  66.                 try {
  67.                     close();
  68.                 } catch (IOException e) {
  69.                 }
  70.             } catch (InterruptedException ie) {
  71.                 // a write occured
  72.             }
  73.         }
  74.     }

  75. }