/*
 * @(#)SuspendableInputStream.java  1.0  1999-10-19
 *
 * Copyright (c) 1999 Werner Randelshofer, Immensee, Switzerland.
 * All rights reserved.
 *
 * You may not use, copy or modify this file, except in compliance with the
 * license agreement you entered into with Werner Randelshofer.
 * For details see accompanying license terms.
 */
package ch.randelshofer.io;

import java.io.FilterInputStream;
import java.io.InputStream;
import java.io.IOException;


/**
* This input stream can be used to suspend, resume and abort a worker thread
* who is reading an input stream.
* The methods #suspend, #resume and #abort must by called from a different
* thread (the supervising thread).
*
* @author Werner Randelshofer, Hausmatt 10, CH-6405 Immensee, Switzerland
* @version  1.0 1999-10-19
*/
public class SuspendableInputStream
extends FilterInputStream
  {
  private final static int ACTIVE = 0;
  private final static int SUSPENDED = 1;
  private final static int ABORTED = 2;

  private volatile int state_ = ACTIVE;

  public SuspendableInputStream(InputStream in)
    { super(in); }

  public synchronized void suspend()
    {
    if (state_ == ACTIVE)
      {
      state_ = SUSPENDED;
      notifyAll();
      }
    }

  public synchronized void resume()
    {
    if (state_ == SUSPENDED)
      {
      state_ = ACTIVE;
      notifyAll();
      }
    }

   public synchronized void abort()
    {
    if (state_ != ABORTED)
      {
      state_ = ABORTED;
      notifyAll();
      }
    }

  public boolean isSuspended()
    { return state_ == SUSPENDED; }

  public boolean isAborted()
    { return state_ == ABORTED; }

  public int read()
  throws IOException
    {
    synchronized(this)
      {
      while (state_ == SUSPENDED)
        {
        try { wait(); }
        catch (InterruptedException e) {}
        }
      }
    if (state_ == ABORTED)
      { throw new IOException("Aborted"); }
    return super.read();
    }
  public int read(byte[] b)
  throws IOException
    {
    synchronized(this)
      {
      while (state_ == SUSPENDED)
        {
        try { wait(); }
        catch (InterruptedException e) {}
        }
      }
    if (state_ == ABORTED)
      { throw new IOException("Aborted"); }
    return super.read(b);
    }
  public int read(byte[] b, int off, int len)
  throws IOException
    {
    synchronized(this)
      {
      while (state_ == SUSPENDED)
        {
        try { wait(); }
        catch (InterruptedException e) {}
        }
      }
    if (state_ == ABORTED)
      { throw new IOException("Aborted"); }
    return super.read(b,off,len);
    }
  }
