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 20adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project/** 21adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Places information on a communications pipe. When two threads want to pass 22adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * data back and forth, one creates a piped writer and the other creates a piped 23adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader. 24f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 25adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see PipedReader 26adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 27adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Projectpublic class PipedWriter extends Writer { 28dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson 29dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson private PipedReader destination; 30dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson private boolean isClosed; 31adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 32adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 33adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Constructs a new unconnected {@code PipedWriter}. The resulting writer 34adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * must be connected to a {@code PipedReader} before data may be written to 35adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it. 36f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 37adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @see PipedReader 38adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 39adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public PipedWriter() { 40adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 41adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 42adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 43dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * Constructs a new {@code PipedWriter} connected to {@code destination}. 44dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * Any data written to this writer can be read from {@code destination}. 45f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 46dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * @param destination 47adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the {@code PipedReader} to connect to. 48adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 49dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson * if {@code destination} is already connected. 50adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 51dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson public PipedWriter(PipedReader destination) throws IOException { 52dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson super(destination); 53dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson connect(destination); 54adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 55adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 56adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 57adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Closes this writer. If a {@link PipedReader} is connected to this writer, 58adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * it is closed as well and the pipe is disconnected. Any data buffered in 59adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reader can still be read. 60f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 61adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 62adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an error occurs while closing this writer. 63adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 64adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 65adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void close() throws IOException { 66dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 67da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader != null) { 68da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.done(); 69dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson isClosed = true; 70dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson destination = null; 71adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 72adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 73adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 74adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 75adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data 76adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * written to this writer becomes readable in the reader. 77f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 78da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson * @param reader 79adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the reader to connect to. 80adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 81adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or already connected, or if {@code 82da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson * reader} is already connected. 83adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 84da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson public void connect(PipedReader reader) throws IOException { 85da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 8686acc043d3334651ee26c65467d78d6cefedd397Kenny Root throw new NullPointerException("reader == null"); 87da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson } 88da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson synchronized (reader) { 89dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson if (this.destination != null) { 90dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson throw new IOException("Pipe already connected"); 91adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 92da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.establishConnection(); 93da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson this.lock = reader; 94dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson this.destination = reader; 95adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 96adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 97adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 98adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 99adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Notifies the readers of this {@code PipedReader} that characters can be read. This 100adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * method does nothing if this Writer is not connected. 101f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 102adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 103adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if an I/O error occurs while flushing this writer. 104adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 105adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 106adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void flush() throws IOException { 107dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 108dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson if (isClosed) { 109dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson throw new IOException("Pipe is closed"); 110dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson } 111da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 112da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson return; 113da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson } 114da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson 115da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson synchronized (reader) { 1160048bf7983e68d6d99b7b1332db8a2239de50949Narayan Kamath if (reader.isClosed) { 1170048bf7983e68d6d99b7b1332db8a2239de50949Narayan Kamath throw new IOException("Pipe is broken"); 1180048bf7983e68d6d99b7b1332db8a2239de50949Narayan Kamath } 119da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.notifyAll(); 120adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 121adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 122adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 123adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 124adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes {@code count} characters from the character array {@code buffer} 125adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * starting at offset {@code index} to this writer. The written data can 126adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * then be read from the connected {@link PipedReader} instance. 127adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 128adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Separate threads should be used to write to a {@code PipedWriter} and to 129adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read from the connected {@code PipedReader}. If the same thread is used, 130adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a deadlock may occur. 131f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 132adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param buffer 133adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the buffer to write. 134adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param offset 135adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the index of the first character in {@code buffer} to write. 136adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param count 137adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the number of characters from {@code buffer} to write to this 138adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * writer. 139adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IndexOutOfBoundsException 140adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code offset < 0} or {@code count < 0}, or if {@code 141adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * offset + count} is bigger than the length of {@code buffer}. 142adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws InterruptedIOException 143adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the pipe is full and the current thread is interrupted 144adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * waiting for space to write data. This case is not currently 145adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handled correctly. 146adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 147adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or not connected, if the target 148adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is closed or if the thread reading from the target 149adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is no longer alive. This case is currently not handled 150adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * correctly. 151adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws NullPointerException 152adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if {@code buffer} is {@code null}. 153adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 154adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 155adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(char[] buffer, int offset, int count) throws IOException { 156dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 157da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 158b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Pipe not connected"); 159adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 160da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.receive(buffer, offset, count); 161adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 162adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project 163adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project /** 164adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Writes a single character {@code c} to this writer. This character can 165adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * then be read from the connected {@link PipedReader} instance. 166adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * <p> 167adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * Separate threads should be used to write to a {@code PipedWriter} and to 168adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * read from the connected {@code PipedReader}. If the same thread is used, 169adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * a deadlock may occur. 170f5597e626ecf7949d249dea08c1a2964d890ec11Jesse Wilson * 171adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @param c 172adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * the character to write. 173adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws InterruptedIOException 174adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if the pipe is full and the current thread is interrupted 175adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * waiting for space to write data. This case is not currently 176adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * handled correctly. 177adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * @throws IOException 178adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * if this writer is closed or not connected, if the target 179adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is closed or if the thread reading from the target 180adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * reader is no longer alive. This case is currently not handled 181adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project * correctly. 182adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project */ 183adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project @Override 184adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project public void write(int c) throws IOException { 185dfc6136d9473dfd0aa5b310035ce48d5f8eebe0dJesse Wilson PipedReader reader = destination; 186da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson if (reader == null) { 187b1396870f92135aa140bd2b86221768dea5bc11dElliott Hughes throw new IOException("Pipe not connected"); 188adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 189da1bdbd09a1f6c394fa9d4210de9db0b570ac1fdJesse Wilson reader.receive((char) c); 190adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project } 191adc854b798c1cfe3bfd4c27d68d5cee38ca617daThe Android Open Source Project} 192