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