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<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