home *** CD-ROM | disk | FTP | other *** search
/ Chip 1998 November / Chip_1998-11_cd.bin / tema / Cafe / main.bin / PipedInputStream.java < prev    next >
Text File  |  1997-05-20  |  9KB  |  295 lines

  1. /*
  2.  * @(#)PipedInputStream.java    1.18 97/02/20
  3.  * 
  4.  * Copyright (c) 1995, 1996 Sun Microsystems, Inc. All Rights Reserved.
  5.  * 
  6.  * This software is the confidential and proprietary information of Sun
  7.  * Microsystems, Inc. ("Confidential Information").  You shall not
  8.  * disclose such Confidential Information and shall use it only in
  9.  * accordance with the terms of the license agreement you entered into
  10.  * with Sun.
  11.  * 
  12.  * SUN MAKES NO REPRESENTATIONS OR WARRANTIES ABOUT THE SUITABILITY OF THE
  13.  * SOFTWARE, EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  14.  * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
  15.  * PURPOSE, OR NON-INFRINGEMENT. SUN SHALL NOT BE LIABLE FOR ANY DAMAGES
  16.  * SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR DISTRIBUTING
  17.  * THIS SOFTWARE OR ITS DERIVATIVES.
  18.  * 
  19.  * CopyrightVersion 1.1_beta
  20.  * 
  21.  */
  22.  
  23. package java.io;
  24.  
  25. /**
  26.  * A piped input stream is the receiving end of a communications 
  27.  * pipe. Two threads can communicate by having one thread send data 
  28.  * through a piped output stream and having the other thread read the 
  29.  * data through a piped input stream.
  30.  *
  31.  * @author  James Gosling
  32.  * @version 1.18, 02/20/97
  33.  * @see     java.io.PipedOutputStream
  34.  * @since   JDK1.0
  35.  */
  36. public
  37. class PipedInputStream extends InputStream {
  38.     boolean closed = true;
  39.     boolean closedByReader = false;
  40.     boolean connected = false;
  41.  
  42.     /* REMIND: identification of the read and write sides needs to be
  43.        more sophisticated.  Either using thread groups (but what about
  44.        pipes within a thread?) or using finalization (but it may be a
  45.        long time until the next GC). */
  46.     Thread readSide;
  47.     Thread writeSide;
  48.  
  49.     /**
  50.      * @since   JDK1.1
  51.      */
  52.     protected static final int PIPE_SIZE = 1024;
  53.  
  54.     /**
  55.      * The circular buffer into which incoming data is placed.
  56.      * @since   JDK1.1
  57.      */
  58.     protected byte buffer[] = new byte[PIPE_SIZE];
  59.  
  60.     /*
  61.      * fill and empty pointers.  in<0 implies the buffer is empty, in==out
  62.      * implies the buffer is full
  63.      */
  64.  
  65.     /**
  66.      * @since   JDK1.1
  67.      */
  68.     protected int in = -1;
  69.  
  70.     /**
  71.      * @since   JDK1.1
  72.      */
  73.     protected int out = 0;
  74.  
  75.     /**
  76.      * Creates a piped input stream connected to the specified piped 
  77.      * output stream. 
  78.      *
  79.      * @param      src   the stream to connect to.
  80.      * @exception  IOException  if an I/O error occurs.
  81.      * @since      JDK1.0
  82.      */
  83.     public PipedInputStream(PipedOutputStream src) throws IOException {
  84.     connect(src);
  85.     }
  86.  
  87.     /**
  88.      * Creates a piped input stream that is not yet connected to a piped 
  89.      * output stream. It must be connected to a piped output stream, 
  90.      * either by the receiver or the sender, before being used. 
  91.      *
  92.      * @see     java.io.PipedInputStream#connect(java.io.PipedOutputStream)
  93.      * @see     java.io.PipedOutputStream#connect(java.io.PipedInputStream)
  94.      * @since   JDK1.0
  95.      */
  96.     public PipedInputStream() {
  97.     }
  98.  
  99.     /**
  100.      * Connects this piped input stream to a sender. 
  101.      *
  102.      * @param      src   The piped output stream to connect to.
  103.      * @exception  IOException  if an I/O error occurs.
  104.      * @since      JDK1.0
  105.      */
  106.     public void connect(PipedOutputStream src) throws IOException {
  107.     if (connected) {
  108.         throw new IOException("Pipe already connected");
  109.     }
  110.     src.connect(this);
  111.     connected = true;
  112.     }
  113.     
  114.     /**
  115.      * Receives a byte of data.  This method will block if no input is
  116.      * available.
  117.      * @param b the byte being received
  118.      * @exception IOException If the pipe is broken.
  119.      * @since     JDK1.1
  120.      */
  121.     protected synchronized void receive(int b) throws IOException {
  122.     writeSide = Thread.currentThread();
  123.     while (in == out) {
  124.         if ((readSide != null) && !readSide.isAlive()) {
  125.         throw new IOException("Pipe broken");
  126.         }
  127.         /* full: kick any waiting readers */
  128.         notifyAll();    
  129.         try {
  130.             wait(1000);
  131.         } catch (InterruptedException ex) {
  132.         throw new java.io.InterruptedIOException();
  133.         }
  134.     }
  135.     if (in < 0) {
  136.         in = 0;
  137.         out = 0;
  138.     }
  139.     buffer[in++] = (byte)(b & 0xFF);
  140.     if (in >= buffer.length) {
  141.         in = 0;
  142.     }
  143.     }
  144.  
  145.     /**
  146.      * Receives data into an array of bytes.  This method will
  147.      * block until some input is available. 
  148.      * @param b the buffer into which the data is received
  149.      * @param off the start offset of the data
  150.      * @param len the maximum number of bytes received
  151.      * @return the actual number of bytes received, -1 is
  152.      *          returned when the end of the stream is reached. 
  153.      * @exception IOException If an I/O error has occurred. 
  154.      */
  155.     synchronized void receive(byte b[], int off, int len)  throws IOException {
  156.     while (--len >= 0) {
  157.         receive(b[off++]);
  158.     }
  159.     }
  160.  
  161.     /**
  162.      * Notifies all waiting threads that the last byte of data has been
  163.      * received.
  164.      */
  165.     synchronized void receivedLast() {
  166.     closed = true;
  167.     notifyAll();
  168.     }
  169.  
  170.     /**
  171.      * Reads the next byte of data from this piped input stream. The 
  172.      * value byte is returned as an <code>int</code> in the range 
  173.      * <code>0</code> to <code>255</code>. If no byte is available 
  174.      * because this end of the stream has been reached, the value 
  175.      * <code>-1</code> is returned. This method blocks until input data 
  176.      * is available, the end of the stream is detected, or an exception 
  177.      * is thrown. 
  178.      *
  179.      * @return     the next byte of data, or <code>-1</code> if the end of the
  180.      *             stream is reached.
  181.      * @exception  IOException  if the pipe is broken.
  182.      * @since      JDK1.0
  183.      */
  184.     public synchronized int read()  throws IOException {
  185.     if (closedByReader) {
  186.         throw new IOException("InputStream closed");
  187.     }
  188.     int trials = 2;
  189.     while (in < 0) {
  190.         readSide = Thread.currentThread();
  191.         if (closed) { 
  192.         /* closed by writer, return EOF */
  193.         return -1;
  194.         }
  195.         if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
  196.         throw new IOException("Pipe broken");
  197.         }
  198.             /* might be a writer waiting */
  199.         notifyAll();
  200.         try {
  201.             wait(1000);
  202.         } catch (InterruptedException ex) {
  203.         throw new java.io.InterruptedIOException();
  204.         }
  205.      }
  206.     int ret = buffer[out++] & 0xFF;
  207.     if (out >= buffer.length) {
  208.         out = 0;
  209.     }
  210.     if (in == out) {
  211.             /* now empty */
  212.         in = -1;        
  213.     }
  214.     return ret;
  215.     }
  216.  
  217.     /**
  218.      * Reads up to <code>len</code> bytes of data from this piped input 
  219.      * stream into an array of bytes. This method blocks until at least one
  220.      * byte of input is available. 
  221.      *
  222.      * @param      b     the buffer into which the data is read.
  223.      * @param      off   the start offset of the data.
  224.      * @param      len   the maximum number of bytes read.
  225.      * @return     the total number of bytes read into the buffer, or
  226.      *             <code>-1</code> if there is no more data because the end of
  227.      *             the stream has been reached.
  228.      * @exception  IOException  if an I/O error occurs.
  229.      * @since      JDK1.0
  230.      */
  231.     public synchronized int read(byte b[], int off, int len)  throws IOException {
  232.  
  233.     if (b == null) {
  234.         throw new NullPointerException();
  235.     } else if (off < 0 || len < 0 || off + len > b.length) {
  236.         throw new ArrayIndexOutOfBoundsException();
  237.     } else if (len == 0) {
  238.         return 0;
  239.     }
  240.  
  241.         /* possibly wait on the first character */
  242.     int c = read();        
  243.     if (c < 0) {
  244.         return -1;
  245.     }
  246.     b[off] = (byte) c;
  247.     int rlen = 1;
  248.     while ((in >= 0) && (--len > 0)) {
  249.         b[off + rlen] = buffer[out++];
  250.         rlen++;
  251.         if (out >= buffer.length) {
  252.         out = 0;
  253.         }
  254.         if (in == out) {
  255.                 /* now empty */
  256.         in = -1;    
  257.         }
  258.     }
  259.     return rlen;
  260.     }
  261.  
  262.     /**
  263.      * Returns the number of bytes that can be read from this input 
  264.      * stream without blocking. This method overrides the <code>available</code>
  265.      * method of the parent class.
  266.      *
  267.      * @return     the number of bytes that can be read from this input stream
  268.      *             without blocking.
  269.      * @exception  IOException  if an I/O error occurs.
  270.      * @since   JDK1.0.2
  271.      */
  272.   public synchronized int available() throws IOException {
  273.     if(in < 0)
  274.       return 0;
  275.     else if(in == out)
  276.       return buffer.length;
  277.     else if (in > out)
  278.       return in - out;
  279.     else
  280.       return in + buffer.length - out;
  281.   }
  282.     
  283.     /**
  284.      * Closes this piped input stream and releases any system resources 
  285.      * associated with the stream. 
  286.      *
  287.      * @exception  IOException  if an I/O error occurs.
  288.      * @since      JDK1.0
  289.      */
  290.     public void close()  throws IOException {
  291.     in = -1;
  292.     closedByReader = true;
  293.     }
  294. }
  295.