1adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/* 2adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one or more 3adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * contributor license agreements. See the NOTICE file distributed with 4adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * this work for additional information regarding copyright ownership. 5adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * The ASF licenses this file to You under the Apache License, Version 2.0 6adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * (the "License"); you may not use this file except in compliance with 7adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the License. You may obtain a copy of the License at 8adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 9adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * http://www.apache.org/licenses/LICENSE-2.0 10adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * 11adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Unless required by applicable law or agreed to in writing, software 12adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS, 13adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * See the License for the specific language governing permissions and 15adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * limitations under the License. 16adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 17adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 18adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpackage java.io; 19adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 20a1603838fe9e865575c87982e32c6343740e464cElliott Hughesimport java.util.Arrays; 21a1603838fe9e865575c87982e32c6343740e464cElliott Hughes 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Places information on a communications pipe. When two threads want to pass 24adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * data back and forth, one creates a piped writer and the other creates a piped 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader. 26f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see PipedReader 28adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 29adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class PipedWriter extends Writer { 30dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson 31dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson private PipedReader destination; 32dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson private boolean isClosed; 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new unconnected {@code PipedWriter}. The resulting writer 36adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be connected to a {@code PipedReader} before data may be written to 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it. 38f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see PipedReader 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public PipedWriter() { 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 43adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 44adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 45dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * Constructs a new {@code PipedWriter} connected to {@code destination}. 46dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * Any data written to this writer can be read from {@code destination}. 47f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 48dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * @param destination 49adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code PipedReader} to connect to. 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 51dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * if {@code destination} is already connected. 52adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 53dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson public PipedWriter(PipedReader destination) throws IOException { 54dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson super(destination); 55dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson connect(destination); 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes this writer. If a {@link PipedReader} is connected to this writer, 60adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it is closed as well and the pipe is disconnected. Any data buffered in 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reader can still be read. 62f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while closing this writer. 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 66adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 67adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 68dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 69da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader != null) { 70da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.done(); 71dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson isClosed = true; 72dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson destination = null; 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 77adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data 78adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * written to this writer becomes readable in the reader. 79f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 80da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson * @param reader 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reader to connect to. 82adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or already connected, or if {@code 84da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson * reader} is already connected. 85adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 86da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson public void connect(PipedReader reader) throws IOException { 87da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 8886acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("reader == null"); 89da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson } 90da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson synchronized (reader) { 91dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson if (this.destination != null) { 92dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson throw new IOException("Pipe already connected"); 93adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 94da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.establishConnection(); 95da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson this.lock = reader; 96dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson this.destination = reader; 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 101adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies the readers of this {@code PipedReader} that characters can be read. This 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method does nothing if this Writer is not connected. 103f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs while flushing this writer. 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 107adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 108adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void flush() throws IOException { 109dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 110dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson if (isClosed) { 111dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson throw new IOException("Pipe is closed"); 112dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson } 113da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 114da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson return; 115da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson } 116da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson 117da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson synchronized (reader) { 118da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.notifyAll(); 119adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes {@code count} characters from the character array {@code buffer} 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * starting at offset {@code index} to this writer. The written data can 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * then be read from the connected {@link PipedReader} instance. 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Separate threads should be used to write to a {@code PipedWriter} and to 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read from the connected {@code PipedReader}. If the same thread is used, 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a deadlock may occur. 130f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 131adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buffer 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer to write. 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the index of the first character in {@code buffer} to write. 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param count 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of characters from {@code buffer} to write to this 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * writer. 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IndexOutOfBoundsException 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset < 0} or {@code count < 0}, or if {@code 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * offset + count} is bigger than the length of {@code buffer}. 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws InterruptedIOException 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the pipe is full and the current thread is interrupted 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * waiting for space to write data. This case is not currently 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handled correctly. 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or not connected, if the target 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is closed or if the thread reading from the target 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is no longer alive. This case is currently not handled 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * correctly. 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code buffer} is {@code null}. 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(char[] buffer, int offset, int count) throws IOException { 155dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 156da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 157b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Pipe not connected"); 158adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 159da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.receive(buffer, offset, count); 160adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes a single character {@code c} to this writer. This character can 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * then be read from the connected {@link PipedReader} instance. 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Separate threads should be used to write to a {@code PipedWriter} and to 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read from the connected {@code PipedReader}. If the same thread is used, 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a deadlock may occur. 169f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 170adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param c 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the character to write. 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws InterruptedIOException 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the pipe is full and the current thread is interrupted 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * waiting for space to write data. This case is not currently 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handled correctly. 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or not connected, if the target 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is closed or if the thread reading from the target 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is no longer alive. This case is currently not handled 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * correctly. 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(int c) throws IOException { 184dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 185da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 186b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Pipe not connected"); 187adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 188da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.receive((char) c); 189adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 191