001 /*
002 * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.io;
027
028 /**
029 * Piped character-output streams.
030 *
031 * @version 1.25, 07/05/05
032 * @author Mark Reinhold
033 * @since JDK1.1
034 */
035
036 public class PipedWriter extends Writer {
037
038 /* REMIND: identification of the read and write sides needs to be
039 more sophisticated. Either using thread groups (but what about
040 pipes within a thread?) or using finalization (but it may be a
041 long time until the next GC). */
042 private PipedReader sink;
043
044 /* This flag records the open status of this particular writer. It
045 * is independent of the status flags defined in PipedReader. It is
046 * used to do a sanity check on connect.
047 */
048 private boolean closed = false;
049
050 /**
051 * Creates a piped writer connected to the specified piped
052 * reader. Data characters written to this stream will then be
053 * available as input from <code>snk</code>.
054 *
055 * @param snk The piped reader to connect to.
056 * @exception IOException if an I/O error occurs.
057 */
058 public PipedWriter(PipedReader snk) throws IOException {
059 connect(snk);
060 }
061
062 /**
063 * Creates a piped writer that is not yet connected to a
064 * piped reader. It must be connected to a piped reader,
065 * either by the receiver or the sender, before being used.
066 *
067 * @see java.io.PipedReader#connect(java.io.PipedWriter)
068 * @see java.io.PipedWriter#connect(java.io.PipedReader)
069 */
070 public PipedWriter() {
071 }
072
073 /**
074 * Connects this piped writer to a receiver. If this object
075 * is already connected to some other piped reader, an
076 * <code>IOException</code> is thrown.
077 * <p>
078 * If <code>snk</code> is an unconnected piped reader and
079 * <code>src</code> is an unconnected piped writer, they may
080 * be connected by either the call:
081 * <blockquote><pre>
082 * src.connect(snk)</pre></blockquote>
083 * or the call:
084 * <blockquote><pre>
085 * snk.connect(src)</pre></blockquote>
086 * The two calls have the same effect.
087 *
088 * @param snk the piped reader to connect to.
089 * @exception IOException if an I/O error occurs.
090 */
091 public synchronized void connect(PipedReader snk)
092 throws IOException {
093 if (snk == null) {
094 throw new NullPointerException();
095 } else if (sink != null || snk.connected) {
096 throw new IOException("Already connected");
097 } else if (snk.closedByReader || closed) {
098 throw new IOException("Pipe closed");
099 }
100
101 sink = snk;
102 snk.in = -1;
103 snk.out = 0;
104 snk.connected = true;
105 }
106
107 /**
108 * Writes the specified <code>char</code> to the piped output stream.
109 * If a thread was reading data characters from the connected piped input
110 * stream, but the thread is no longer alive, then an
111 * <code>IOException</code> is thrown.
112 * <p>
113 * Implements the <code>write</code> method of <code>Writer</code>.
114 *
115 * @param c the <code>char</code> to be written.
116 * @exception IOException if the pipe is
117 * <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
118 * {@link #connect(java.io.PipedReader) unconnected}, closed
119 * or an I/O error occurs.
120 */
121 public void write(int c) throws IOException {
122 if (sink == null) {
123 throw new IOException("Pipe not connected");
124 }
125 sink.receive(c);
126 }
127
128 /**
129 * Writes <code>len</code> characters from the specified character array
130 * starting at offset <code>off</code> to this piped output stream.
131 * This method blocks until all the characters are written to the output
132 * stream.
133 * If a thread was reading data characters from the connected piped input
134 * stream, but the thread is no longer alive, then an
135 * <code>IOException</code> is thrown.
136 *
137 * @param cbuf the data.
138 * @param off the start offset in the data.
139 * @param len the number of characters to write.
140 * @exception IOException if the pipe is
141 * <a href=PipedOutputStream.html#BROKEN> <code>broken</code></a>,
142 * {@link #connect(java.io.PipedReader) unconnected}, closed
143 * or an I/O error occurs.
144 */
145 public void write(char cbuf[], int off, int len) throws IOException {
146 if (sink == null) {
147 throw new IOException("Pipe not connected");
148 } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {
149 throw new IndexOutOfBoundsException();
150 }
151 sink.receive(cbuf, off, len);
152 }
153
154 /**
155 * Flushes this output stream and forces any buffered output characters
156 * to be written out.
157 * This will notify any readers that characters are waiting in the pipe.
158 *
159 * @exception IOException if the pipe is closed, or an I/O error occurs.
160 */
161 public synchronized void flush() throws IOException {
162 if (sink != null) {
163 if (sink.closedByReader || closed) {
164 throw new IOException("Pipe closed");
165 }
166 synchronized (sink) {
167 sink.notifyAll();
168 }
169 }
170 }
171
172 /**
173 * Closes this piped output stream and releases any system resources
174 * associated with this stream. This stream may no longer be used for
175 * writing characters.
176 *
177 * @exception IOException if an I/O error occurs.
178 */
179 public void close() throws IOException {
180 closed = true;
181 if (sink != null) {
182 sink.receivedLast();
183 }
184 }
185 }
|