| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package java.io; |
| |
| import java.util.Arrays; |
| |
| /** |
| * Places information on a communications pipe. When two threads want to pass |
| * data back and forth, one creates a piped writer and the other creates a piped |
| * reader. |
| * |
| * @see PipedReader |
| */ |
| public class PipedWriter extends Writer { |
| |
| private PipedReader destination; |
| private boolean isClosed; |
| |
| /** |
| * Constructs a new unconnected {@code PipedWriter}. The resulting writer |
| * must be connected to a {@code PipedReader} before data may be written to |
| * it. |
| * |
| * @see PipedReader |
| */ |
| public PipedWriter() { |
| } |
| |
| /** |
| * Constructs a new {@code PipedWriter} connected to {@code destination}. |
| * Any data written to this writer can be read from {@code destination}. |
| * |
| * @param destination |
| * the {@code PipedReader} to connect to. |
| * @throws IOException |
| * if {@code destination} is already connected. |
| */ |
| public PipedWriter(PipedReader destination) throws IOException { |
| super(destination); |
| connect(destination); |
| } |
| |
| /** |
| * Closes this writer. If a {@link PipedReader} is connected to this writer, |
| * it is closed as well and the pipe is disconnected. Any data buffered in |
| * the reader can still be read. |
| * |
| * @throws IOException |
| * if an error occurs while closing this writer. |
| */ |
| @Override |
| public void close() throws IOException { |
| PipedReader reader = destination; |
| if (reader != null) { |
| reader.done(); |
| isClosed = true; |
| destination = null; |
| } |
| } |
| |
| /** |
| * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data |
| * written to this writer becomes readable in the reader. |
| * |
| * @param reader |
| * the reader to connect to. |
| * @throws IOException |
| * if this writer is closed or already connected, or if {@code |
| * reader} is already connected. |
| */ |
| public void connect(PipedReader reader) throws IOException { |
| if (reader == null) { |
| throw new NullPointerException("reader == null"); |
| } |
| synchronized (reader) { |
| if (this.destination != null) { |
| throw new IOException("Pipe already connected"); |
| } |
| reader.establishConnection(); |
| this.lock = reader; |
| this.destination = reader; |
| } |
| } |
| |
| /** |
| * Notifies the readers of this {@code PipedReader} that characters can be read. This |
| * method does nothing if this Writer is not connected. |
| * |
| * @throws IOException |
| * if an I/O error occurs while flushing this writer. |
| */ |
| @Override |
| public void flush() throws IOException { |
| PipedReader reader = destination; |
| if (isClosed) { |
| throw new IOException("Pipe is closed"); |
| } |
| if (reader == null) { |
| return; |
| } |
| |
| synchronized (reader) { |
| reader.notifyAll(); |
| } |
| } |
| |
| /** |
| * Writes {@code count} characters from the character array {@code buffer} |
| * starting at offset {@code index} to this writer. The written data can |
| * then be read from the connected {@link PipedReader} instance. |
| * <p> |
| * Separate threads should be used to write to a {@code PipedWriter} and to |
| * read from the connected {@code PipedReader}. If the same thread is used, |
| * a deadlock may occur. |
| * |
| * @param buffer |
| * the buffer to write. |
| * @param offset |
| * the index of the first character in {@code buffer} to write. |
| * @param count |
| * the number of characters from {@code buffer} to write to this |
| * writer. |
| * @throws IndexOutOfBoundsException |
| * if {@code offset < 0} or {@code count < 0}, or if {@code |
| * offset + count} is bigger than the length of {@code buffer}. |
| * @throws InterruptedIOException |
| * if the pipe is full and the current thread is interrupted |
| * waiting for space to write data. This case is not currently |
| * handled correctly. |
| * @throws IOException |
| * if this writer is closed or not connected, if the target |
| * reader is closed or if the thread reading from the target |
| * reader is no longer alive. This case is currently not handled |
| * correctly. |
| * @throws NullPointerException |
| * if {@code buffer} is {@code null}. |
| */ |
| @Override |
| public void write(char[] buffer, int offset, int count) throws IOException { |
| PipedReader reader = destination; |
| if (reader == null) { |
| throw new IOException("Pipe not connected"); |
| } |
| reader.receive(buffer, offset, count); |
| } |
| |
| /** |
| * Writes a single character {@code c} to this writer. This character can |
| * then be read from the connected {@link PipedReader} instance. |
| * <p> |
| * Separate threads should be used to write to a {@code PipedWriter} and to |
| * read from the connected {@code PipedReader}. If the same thread is used, |
| * a deadlock may occur. |
| * |
| * @param c |
| * the character to write. |
| * @throws InterruptedIOException |
| * if the pipe is full and the current thread is interrupted |
| * waiting for space to write data. This case is not currently |
| * handled correctly. |
| * @throws IOException |
| * if this writer is closed or not connected, if the target |
| * reader is closed or if the thread reading from the target |
| * reader is no longer alive. This case is currently not handled |
| * correctly. |
| */ |
| @Override |
| public void write(int c) throws IOException { |
| PipedReader reader = destination; |
| if (reader == null) { |
| throw new IOException("Pipe not connected"); |
| } |
| reader.receive((char) c); |
| } |
| } |