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