Home » openjdk-7 » java » io » [javadoc | source]

    1   /*
    2    * Copyright (c) 1996, 2006, Oracle and/or its affiliates. All rights reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Oracle designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Oracle in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
   22    * or visit www.oracle.com if you need additional information or have any
   23    * questions.
   24    */
   25   
   26   package java.io;
   27   
   28   
   29   /**
   30    * Piped character-input streams.
   31    *
   32    * @author      Mark Reinhold
   33    * @since       JDK1.1
   34    */
   35   
   36   public class PipedReader extends Reader {
   37       boolean closedByWriter = false;
   38       boolean closedByReader = false;
   39       boolean connected = false;
   40   
   41       /* REMIND: identification of the read and write sides needs to be
   42          more sophisticated.  Either using thread groups (but what about
   43          pipes within a thread?) or using finalization (but it may be a
   44          long time until the next GC). */
   45       Thread readSide;
   46       Thread writeSide;
   47   
   48      /**
   49       * The size of the pipe's circular input buffer.
   50       */
   51       private static final int DEFAULT_PIPE_SIZE = 1024;
   52   
   53       /**
   54        * The circular buffer into which incoming data is placed.
   55        */
   56       char buffer[];
   57   
   58       /**
   59        * The index of the position in the circular buffer at which the
   60        * next character of data will be stored when received from the connected
   61        * piped writer. <code>in&lt;0</code> implies the buffer is empty,
   62        * <code>in==out</code> implies the buffer is full
   63        */
   64       int in = -1;
   65   
   66       /**
   67        * The index of the position in the circular buffer at which the next
   68        * character of data will be read by this piped reader.
   69        */
   70       int out = 0;
   71   
   72       /**
   73        * Creates a <code>PipedReader</code> so
   74        * that it is connected to the piped writer
   75        * <code>src</code>. Data written to <code>src</code>
   76        * will then be available as input from this stream.
   77        *
   78        * @param      src   the stream to connect to.
   79        * @exception  IOException  if an I/O error occurs.
   80        */
   81       public PipedReader(PipedWriter src) throws IOException {
   82           this(src, DEFAULT_PIPE_SIZE);
   83       }
   84   
   85       /**
   86        * Creates a <code>PipedReader</code> so that it is connected
   87        * to the piped writer <code>src</code> and uses the specified
   88        * pipe size for the pipe's buffer. Data written to <code>src</code>
   89        * will then be  available as input from this stream.
   90   
   91        * @param      src       the stream to connect to.
   92        * @param      pipeSize  the size of the pipe's buffer.
   93        * @exception  IOException  if an I/O error occurs.
   94        * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
   95        * @since      1.6
   96        */
   97       public PipedReader(PipedWriter src, int pipeSize) throws IOException {
   98           initPipe(pipeSize);
   99           connect(src);
  100       }
  101   
  102   
  103       /**
  104        * Creates a <code>PipedReader</code> so
  105        * that it is not yet {@linkplain #connect(java.io.PipedWriter)
  106        * connected}. It must be {@linkplain java.io.PipedWriter#connect(
  107        * java.io.PipedReader) connected} to a <code>PipedWriter</code>
  108        * before being used.
  109        */
  110       public PipedReader() {
  111           initPipe(DEFAULT_PIPE_SIZE);
  112       }
  113   
  114       /**
  115        * Creates a <code>PipedReader</code> so that it is not yet
  116        * {@link #connect(java.io.PipedWriter) connected} and uses
  117        * the specified pipe size for the pipe's buffer.
  118        * It must be  {@linkplain java.io.PipedWriter#connect(
  119        * java.io.PipedReader) connected} to a <code>PipedWriter</code>
  120        * before being used.
  121        *
  122        * @param   pipeSize the size of the pipe's buffer.
  123        * @exception  IllegalArgumentException if <code>pipeSize <= 0</code>.
  124        * @since      1.6
  125        */
  126       public PipedReader(int pipeSize) {
  127           initPipe(pipeSize);
  128       }
  129   
  130       private void initPipe(int pipeSize) {
  131           if (pipeSize <= 0) {
  132               throw new IllegalArgumentException("Pipe size <= 0");
  133           }
  134           buffer = new char[pipeSize];
  135       }
  136   
  137       /**
  138        * Causes this piped reader to be connected
  139        * to the piped  writer <code>src</code>.
  140        * If this object is already connected to some
  141        * other piped writer, an <code>IOException</code>
  142        * is thrown.
  143        * <p>
  144        * If <code>src</code> is an
  145        * unconnected piped writer and <code>snk</code>
  146        * is an unconnected piped reader, they
  147        * may be connected by either the call:
  148        * <p>
  149        * <pre><code>snk.connect(src)</code> </pre>
  150        * <p>
  151        * or the call:
  152        * <p>
  153        * <pre><code>src.connect(snk)</code> </pre>
  154        * <p>
  155        * The two
  156        * calls have the same effect.
  157        *
  158        * @param      src   The piped writer to connect to.
  159        * @exception  IOException  if an I/O error occurs.
  160        */
  161       public void connect(PipedWriter src) throws IOException {
  162           src.connect(this);
  163       }
  164   
  165       /**
  166        * Receives a char of data. This method will block if no input is
  167        * available.
  168        */
  169       synchronized void receive(int c) throws IOException {
  170           if (!connected) {
  171               throw new IOException("Pipe not connected");
  172           } else if (closedByWriter || closedByReader) {
  173               throw new IOException("Pipe closed");
  174           } else if (readSide != null && !readSide.isAlive()) {
  175               throw new IOException("Read end dead");
  176           }
  177   
  178           writeSide = Thread.currentThread();
  179           while (in == out) {
  180               if ((readSide != null) && !readSide.isAlive()) {
  181                   throw new IOException("Pipe broken");
  182               }
  183               /* full: kick any waiting readers */
  184               notifyAll();
  185               try {
  186                   wait(1000);
  187               } catch (InterruptedException ex) {
  188                   throw new java.io.InterruptedIOException();
  189               }
  190           }
  191           if (in < 0) {
  192               in = 0;
  193               out = 0;
  194           }
  195           buffer[in++] = (char) c;
  196           if (in >= buffer.length) {
  197               in = 0;
  198           }
  199       }
  200   
  201       /**
  202        * Receives data into an array of characters.  This method will
  203        * block until some input is available.
  204        */
  205       synchronized void receive(char c[], int off, int len)  throws IOException {
  206           while (--len >= 0) {
  207               receive(c[off++]);
  208           }
  209       }
  210   
  211       /**
  212        * Notifies all waiting threads that the last character of data has been
  213        * received.
  214        */
  215       synchronized void receivedLast() {
  216           closedByWriter = true;
  217           notifyAll();
  218       }
  219   
  220       /**
  221        * Reads the next character of data from this piped stream.
  222        * If no character is available because the end of the stream
  223        * has been reached, the value <code>-1</code> is returned.
  224        * This method blocks until input data is available, the end of
  225        * the stream is detected, or an exception is thrown.
  226        *
  227        * @return     the next character of data, or <code>-1</code> if the end of the
  228        *             stream is reached.
  229        * @exception  IOException  if the pipe is
  230        *          <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
  231        *          {@link #connect(java.io.PipedWriter) unconnected}, closed,
  232        *          or an I/O error occurs.
  233        */
  234       public synchronized int read()  throws IOException {
  235           if (!connected) {
  236               throw new IOException("Pipe not connected");
  237           } else if (closedByReader) {
  238               throw new IOException("Pipe closed");
  239           } else if (writeSide != null && !writeSide.isAlive()
  240                      && !closedByWriter && (in < 0)) {
  241               throw new IOException("Write end dead");
  242           }
  243   
  244           readSide = Thread.currentThread();
  245           int trials = 2;
  246           while (in < 0) {
  247               if (closedByWriter) {
  248                   /* closed by writer, return EOF */
  249                   return -1;
  250               }
  251               if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
  252                   throw new IOException("Pipe broken");
  253               }
  254               /* might be a writer waiting */
  255               notifyAll();
  256               try {
  257                   wait(1000);
  258               } catch (InterruptedException ex) {
  259                   throw new java.io.InterruptedIOException();
  260               }
  261           }
  262           int ret = buffer[out++];
  263           if (out >= buffer.length) {
  264               out = 0;
  265           }
  266           if (in == out) {
  267               /* now empty */
  268               in = -1;
  269           }
  270           return ret;
  271       }
  272   
  273       /**
  274        * Reads up to <code>len</code> characters of data from this piped
  275        * stream into an array of characters. Less than <code>len</code> characters
  276        * will be read if the end of the data stream is reached or if
  277        * <code>len</code> exceeds the pipe's buffer size. This method
  278        * blocks until at least one character of input is available.
  279        *
  280        * @param      cbuf     the buffer into which the data is read.
  281        * @param      off   the start offset of the data.
  282        * @param      len   the maximum number of characters read.
  283        * @return     the total number of characters read into the buffer, or
  284        *             <code>-1</code> if there is no more data because the end of
  285        *             the stream has been reached.
  286        * @exception  IOException  if the pipe is
  287        *                  <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
  288        *                  {@link #connect(java.io.PipedWriter) unconnected}, closed,
  289        *                  or an I/O error occurs.
  290        */
  291       public synchronized int read(char cbuf[], int off, int len)  throws IOException {
  292           if (!connected) {
  293               throw new IOException("Pipe not connected");
  294           } else if (closedByReader) {
  295               throw new IOException("Pipe closed");
  296           } else if (writeSide != null && !writeSide.isAlive()
  297                      && !closedByWriter && (in < 0)) {
  298               throw new IOException("Write end dead");
  299           }
  300   
  301           if ((off < 0) || (off > cbuf.length) || (len < 0) ||
  302               ((off + len) > cbuf.length) || ((off + len) < 0)) {
  303               throw new IndexOutOfBoundsException();
  304           } else if (len == 0) {
  305               return 0;
  306           }
  307   
  308           /* possibly wait on the first character */
  309           int c = read();
  310           if (c < 0) {
  311               return -1;
  312           }
  313           cbuf[off] =  (char)c;
  314           int rlen = 1;
  315           while ((in >= 0) && (--len > 0)) {
  316               cbuf[off + rlen] = buffer[out++];
  317               rlen++;
  318               if (out >= buffer.length) {
  319                   out = 0;
  320               }
  321               if (in == out) {
  322                   /* now empty */
  323                   in = -1;
  324               }
  325           }
  326           return rlen;
  327       }
  328   
  329       /**
  330        * Tell whether this stream is ready to be read.  A piped character
  331        * stream is ready if the circular buffer is not empty.
  332        *
  333        * @exception  IOException  if the pipe is
  334        *                  <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
  335        *                  {@link #connect(java.io.PipedWriter) unconnected}, or closed.
  336        */
  337       public synchronized boolean ready() throws IOException {
  338           if (!connected) {
  339               throw new IOException("Pipe not connected");
  340           } else if (closedByReader) {
  341               throw new IOException("Pipe closed");
  342           } else if (writeSide != null && !writeSide.isAlive()
  343                      && !closedByWriter && (in < 0)) {
  344               throw new IOException("Write end dead");
  345           }
  346           if (in < 0) {
  347               return false;
  348           } else {
  349               return true;
  350           }
  351       }
  352   
  353       /**
  354        * Closes this piped stream and releases any system resources
  355        * associated with the stream.
  356        *
  357        * @exception  IOException  if an I/O error occurs.
  358        */
  359       public void close()  throws IOException {
  360           in = -1;
  361           closedByReader = true;
  362       }
  363   }

Home » openjdk-7 » java » io » [javadoc | source]