PipedWriter.java revision f5597e626ecf7949d249dea08c1a2964d890ec11
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 org.apache.harmony.luni.util.Msg; 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 * The destination PipedReader 32 */ 33 private PipedReader dest; 34 35 private boolean closed; 36 37 /** 38 * Constructs a new unconnected {@code PipedWriter}. The resulting writer 39 * must be connected to a {@code PipedReader} before data may be written to 40 * it. 41 * 42 * @see PipedReader 43 */ 44 public PipedWriter() { 45 super(); 46 } 47 48 /** 49 * Constructs a new {@code PipedWriter} connected to the {@link PipedReader} 50 * {@code dest}. Any data written to this writer can be read from {@code 51 * dest}. 52 * 53 * @param dest 54 * the {@code PipedReader} to connect to. 55 * @throws IOException 56 * if {@code dest} is already connected. 57 */ 58 public PipedWriter(PipedReader dest) throws IOException { 59 super(dest); 60 connect(dest); 61 } 62 63 /** 64 * Closes this writer. If a {@link PipedReader} is connected to this writer, 65 * it is closed as well and the pipe is disconnected. Any data buffered in 66 * the reader can still be read. 67 * 68 * @throws IOException 69 * if an error occurs while closing this writer. 70 */ 71 @Override 72 public void close() throws IOException { 73 synchronized (lock) { 74 /* Is the pipe connected? */ 75 if (dest != null) { 76 dest.done(); 77 dest = null; 78 } 79 closed = true; 80 } 81 } 82 83 /** 84 * Connects this {@code PipedWriter} to a {@link PipedReader}. Any data 85 * written to this writer becomes readable in the reader. 86 * 87 * @param stream 88 * the reader to connect to. 89 * @throws IOException 90 * if this writer is closed or already connected, or if {@code 91 * stream} is already connected. 92 */ 93 public void connect(PipedReader stream) throws IOException { 94 synchronized (lock) { 95 if (this.dest != null) { 96 throw new IOException(Msg.getString("K0079")); //$NON-NLS-1$ 97 } 98 if (closed) { 99 throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$ 100 } 101 stream.establishConnection(); 102 this.dest = stream; 103 } 104 } 105 106 /** 107 * Notifies the readers of this {@code PipedReader} that characters can be read. This 108 * method does nothing if this Writer is not connected. 109 * 110 * @throws IOException 111 * if an I/O error occurs while flushing this writer. 112 */ 113 @Override 114 public void flush() throws IOException { 115 if (dest != null) { 116 dest.flush(); 117 } 118 } 119 120 /** 121 * Writes {@code count} characters from the character array {@code buffer} 122 * starting at offset {@code index} to this writer. The written data can 123 * then be read from the connected {@link PipedReader} instance. 124 * <p> 125 * Separate threads should be used to write to a {@code PipedWriter} and to 126 * read from the connected {@code PipedReader}. If the same thread is used, 127 * a deadlock may occur. 128 * 129 * @param buffer 130 * the buffer to write. 131 * @param offset 132 * the index of the first character in {@code buffer} to write. 133 * @param count 134 * the number of characters from {@code buffer} to write to this 135 * writer. 136 * @throws IndexOutOfBoundsException 137 * if {@code offset < 0} or {@code count < 0}, or if {@code 138 * offset + count} is bigger than the length of {@code buffer}. 139 * @throws InterruptedIOException 140 * if the pipe is full and the current thread is interrupted 141 * waiting for space to write data. This case is not currently 142 * handled correctly. 143 * @throws IOException 144 * if this writer is closed or not connected, if the target 145 * reader is closed or if the thread reading from the target 146 * reader is no longer alive. This case is currently not handled 147 * correctly. 148 * @throws NullPointerException 149 * if {@code buffer} is {@code null}. 150 */ 151 @Override 152 public void write(char[] buffer, int offset, int count) throws IOException { 153 // BEGIN android-note 154 // changed array notation to be consistent with the rest of harmony 155 // END android-note 156 synchronized (lock) { 157 if (closed) { 158 throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$ 159 } 160 if (dest == null) { 161 throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$ 162 } 163 if (buffer == null) { 164 throw new NullPointerException(Msg.getString("K0047")); //$NON-NLS-1$ 165 } 166 167 // avoid int overflow 168 // BEGIN android-changed 169 // Exception priorities (in case of multiple errors) differ from 170 // RI, but are spec-compliant. 171 // removed redundant check, used (offset | count) < 0 172 // instead of (offset < 0) || (count < 0) to safe one operation 173 if ((offset | count) < 0 || count > buffer.length - offset) { 174 throw new IndexOutOfBoundsException(Msg.getString("K002f")); //$NON-NLS-1$ 175 } 176 // END android-changed 177 dest.receive(buffer, offset, count); 178 } 179 } 180 181 /** 182 * Writes a single character {@code c} to this writer. This character can 183 * then be read from the connected {@link PipedReader} instance. 184 * <p> 185 * Separate threads should be used to write to a {@code PipedWriter} and to 186 * read from the connected {@code PipedReader}. If the same thread is used, 187 * a deadlock may occur. 188 * 189 * @param c 190 * the character to write. 191 * @throws InterruptedIOException 192 * if the pipe is full and the current thread is interrupted 193 * waiting for space to write data. This case is not currently 194 * handled correctly. 195 * @throws IOException 196 * if this writer is closed or not connected, if the target 197 * reader is closed or if the thread reading from the target 198 * reader is no longer alive. This case is currently not handled 199 * correctly. 200 */ 201 @Override 202 public void write(int c) throws IOException { 203 synchronized (lock) { 204 if (closed) { 205 throw new IOException(Msg.getString("K0078")); //$NON-NLS-1$ 206 } 207 if (dest == null) { 208 throw new IOException(Msg.getString("K007b")); //$NON-NLS-1$ 209 } 210 dest.receive((char) c); 211 } 212 } 213} 214