• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 package java.io;
19 
20 import 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  */
29 public 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      */
PipedWriter()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      */
PipedWriter(PipedReader destination)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
close()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      */
connect(PipedReader reader)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
flush()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
write(char[] buffer, int offset, int count)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
write(int c)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