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