151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
22c87ad3a45cecf9e344487cad1abfdebe79f2c7cNarayan Kamath * Copyright (C) 2014 The Android Open Source Project
361cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak * Copyright (c) 1996, 2013, Oracle and/or its affiliates. All rights reserved.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage java.io;
2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
2911f21c9f4078463e7d4b9ff2bf49f4fa45d284eaPrzemyslaw Szczepaniakimport libcore.io.IoUtils;
3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Piped character-input streams.
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author      Mark Reinhold
3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since       JDK1.1
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic class PipedReader extends Reader {
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean closedByWriter = false;
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean closedByReader = false;
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    boolean connected = false;
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /* REMIND: identification of the read and write sides needs to be
4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       more sophisticated.  Either using thread groups (but what about
4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       pipes within a thread?) or using finalization (but it may be a
4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski       long time until the next GC). */
4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    Thread readSide;
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    Thread writeSide;
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski   /**
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    * The size of the pipe's circular input buffer.
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    */
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private static final int DEFAULT_PIPE_SIZE = 1024;
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The circular buffer into which incoming data is placed.
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    char buffer[];
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The index of the position in the circular buffer at which the
6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * next character of data will be stored when received from the connected
6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * piped writer. <code>in&lt;0</code> implies the buffer is empty,
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>in==out</code> implies the buffer is full
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int in = -1;
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * The index of the position in the circular buffer at which the next
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * character of data will be read by this piped reader.
7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    int out = 0;
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>PipedReader</code> so
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * that it is connected to the piped writer
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>src</code>. Data written to <code>src</code>
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will then be available as input from this stream.
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      src   the stream to connect to.
8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PipedReader(PipedWriter src) throws IOException {
8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        this(src, DEFAULT_PIPE_SIZE);
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>PipedReader</code> so that it is connected
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to the piped writer <code>src</code> and uses the specified
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * pipe size for the pipe's buffer. Data written to <code>src</code>
9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will then be  available as input from this stream.
9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      src       the stream to connect to.
9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      pipeSize  the size of the pipe's buffer.
9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
9661cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since      1.6
9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PipedReader(PipedWriter src, int pipeSize) throws IOException {
10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initPipe(pipeSize);
10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        connect(src);
10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>PipedReader</code> so
10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * that it is not yet {@linkplain #connect(java.io.PipedWriter)
10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * connected}. It must be {@linkplain java.io.PipedWriter#connect(
10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * java.io.PipedReader) connected} to a <code>PipedWriter</code>
11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * before being used.
11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PipedReader() {
11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initPipe(DEFAULT_PIPE_SIZE);
11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Creates a <code>PipedReader</code> so that it is not yet
11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * {@link #connect(java.io.PipedWriter) connected} and uses
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the specified pipe size for the pipe's buffer.
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * It must be  {@linkplain java.io.PipedWriter#connect(
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * java.io.PipedReader) connected} to a <code>PipedWriter</code>
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * before being used.
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param   pipeSize the size of the pipe's buffer.
12561cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak     * @exception  IllegalArgumentException if {@code pipeSize <= 0}.
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @since      1.6
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public PipedReader(int pipeSize) {
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        initPipe(pipeSize);
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    private void initPipe(int pipeSize) {
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (pipeSize <= 0) {
13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IllegalArgumentException("Pipe size <= 0");
13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        buffer = new char[pipeSize];
13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Causes this piped reader to be connected
14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * to the piped  writer <code>src</code>.
14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If this object is already connected to some
14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * other piped writer, an <code>IOException</code>
14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is thrown.
14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If <code>src</code> is an
14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * unconnected piped writer and <code>snk</code>
14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * is an unconnected piped reader, they
14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * may be connected by either the call:
15061cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak     *
15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <pre><code>snk.connect(src)</code> </pre>
15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * or the call:
15461cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak     *
15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <pre><code>src.connect(snk)</code> </pre>
15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <p>
15761cf642f86a0af82e88fb27f31e6842435326b5aPrzemyslaw Szczepaniak     * The two calls have the same effect.
15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      src   The piped writer to connect to.
16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void connect(PipedWriter src) throws IOException {
16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        src.connect(this);
16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Receives a char of data. This method will block if no input is
16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * available.
16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    synchronized void receive(int c) throws IOException {
17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!connected) {
17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe not connected");
17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (closedByWriter || closedByReader) {
17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe closed");
17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (readSide != null && !readSide.isAlive()) {
17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Read end dead");
17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        writeSide = Thread.currentThread();
18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (in == out) {
18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((readSide != null) && !readSide.isAlive()) {
18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IOException("Pipe broken");
18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* full: kick any waiting readers */
18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            notifyAll();
18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                wait(1000);
18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (InterruptedException ex) {
1896975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer                // BEGIN Android-changed: re-set the thread's interrupt status
19011f21c9f4078463e7d4b9ff2bf49f4fa45d284eaPrzemyslaw Szczepaniak                // throw new java.io.InterruptedIOException();
19111f21c9f4078463e7d4b9ff2bf49f4fa45d284eaPrzemyslaw Szczepaniak                IoUtils.throwInterruptedIoException();
19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in < 0) {
19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in = 0;
19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            out = 0;
19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        buffer[in++] = (char) c;
19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in >= buffer.length) {
20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in = 0;
20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Receives data into an array of characters.  This method will
20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * block until some input is available.
20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    synchronized void receive(char c[], int off, int len)  throws IOException {
20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (--len >= 0) {
21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            receive(c[off++]);
21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Notifies all waiting threads that the last character of data has been
21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * received.
21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    synchronized void receivedLast() {
21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        closedByWriter = true;
22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        notifyAll();
22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads the next character of data from this piped stream.
22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * If no character is available because the end of the stream
22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * has been reached, the value <code>-1</code> is returned.
22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * This method blocks until input data is available, the end of
22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * the stream is detected, or an exception is thrown.
22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     the next character of data, or <code>-1</code> if the end of the
23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             stream is reached.
23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if the pipe is
23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          {@link #connect(java.io.PipedWriter) unconnected}, closed,
23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *          or an I/O error occurs.
23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized int read()  throws IOException {
23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!connected) {
23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe not connected");
24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (closedByReader) {
24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe closed");
24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (writeSide != null && !writeSide.isAlive()
24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   && !closedByWriter && (in < 0)) {
24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Write end dead");
24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        readSide = Thread.currentThread();
24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int trials = 2;
24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while (in < 0) {
25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (closedByWriter) {
25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* closed by writer, return EOF */
25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                return -1;
25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                throw new IOException("Pipe broken");
25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* might be a writer waiting */
25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            notifyAll();
25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            try {
26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                wait(1000);
26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            } catch (InterruptedException ex) {
2626975f84c2ed72e1e26d20190b6f318718c849008Tobias Thierer              // Android-changed: re-set the thread's interrupt status
26311f21c9f4078463e7d4b9ff2bf49f4fa45d284eaPrzemyslaw Szczepaniak              // throw new java.io.InterruptedIOException();
26411f21c9f4078463e7d4b9ff2bf49f4fa45d284eaPrzemyslaw Szczepaniak              IoUtils.throwInterruptedIoException();
26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int ret = buffer[out++];
26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (out >= buffer.length) {
26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            out = 0;
27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in == out) {
27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            /* now empty */
27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            in = -1;
27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return ret;
27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Reads up to <code>len</code> characters of data from this piped
28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stream into an array of characters. Less than <code>len</code> characters
28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * will be read if the end of the data stream is reached or if
28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * <code>len</code> exceeds the pipe's buffer size. This method
28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * blocks until at least one character of input is available.
28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      cbuf     the buffer into which the data is read.
28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      off   the start offset of the data.
28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @param      len   the maximum number of characters read.
28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @return     the total number of characters read into the buffer, or
28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             <code>-1</code> if there is no more data because the end of
29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *             the stream has been reached.
29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if the pipe is
29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  {@link #connect(java.io.PipedWriter) unconnected}, closed,
29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  or an I/O error occurs.
29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized int read(char cbuf[], int off, int len)  throws IOException {
29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!connected) {
29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe not connected");
29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (closedByReader) {
30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe closed");
30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (writeSide != null && !writeSide.isAlive()
30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   && !closedByWriter && (in < 0)) {
30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Write end dead");
30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if ((off < 0) || (off > cbuf.length) || (len < 0) ||
30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ((off + len) > cbuf.length) || ((off + len) < 0)) {
30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IndexOutOfBoundsException();
30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (len == 0) {
31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return 0;
31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        /* possibly wait on the first character */
31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int c = read();
31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (c < 0) {
31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return -1;
31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        cbuf[off] =  (char)c;
31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        int rlen = 1;
32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        while ((in >= 0) && (--len > 0)) {
32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            cbuf[off + rlen] = buffer[out++];
32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            rlen++;
32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (out >= buffer.length) {
32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                out = 0;
32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            if (in == out) {
32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                /* now empty */
32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                in = -1;
32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            }
33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return rlen;
33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Tell whether this stream is ready to be read.  A piped character
33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * stream is ready if the circular buffer is not empty.
33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if the pipe is
33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  <a href=PipedInputStream.html#BROKEN> <code>broken</code></a>,
34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *                  {@link #connect(java.io.PipedWriter) unconnected}, or closed.
34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public synchronized boolean ready() throws IOException {
34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (!connected) {
34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe not connected");
34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (closedByReader) {
34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Pipe closed");
34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else if (writeSide != null && !writeSide.isAlive()
34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski                   && !closedByWriter && (in < 0)) {
34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            throw new IOException("Write end dead");
35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (in < 0) {
35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return false;
35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        } else {
35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            return true;
35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    /**
35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * Closes this piped stream and releases any system resources
36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * associated with the stream.
36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     *
36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     * @exception  IOException  if an I/O error occurs.
36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski     */
36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    public void close()  throws IOException {
36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        in = -1;
36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        closedByReader = true;
36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
369