1.1 --- a/jshell.support/PipedInputStream.java Thu Jun 08 01:04:10 2017 -0700
1.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
1.3 @@ -1,447 +0,0 @@
1.4 -/*
1.5 - * Copyright (c) 1995, 2013, Oracle and/or its affiliates. All rights reserved.
1.6 - * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
1.7 - *
1.8 - *
1.9 - *
1.10 - *
1.11 - *
1.12 - *
1.13 - *
1.14 - *
1.15 - *
1.16 - *
1.17 - *
1.18 - *
1.19 - *
1.20 - *
1.21 - *
1.22 - *
1.23 - *
1.24 - *
1.25 - *
1.26 - *
1.27 - */
1.28 -
1.29 -package org.netbeans.modules.jshell.support;
1.30 -
1.31 -import java.io.IOException;
1.32 -import java.io.InputStream;
1.33 -
1.34 -/**
1.35 - * A piped input stream should be connected
1.36 - * to a piped output stream; the piped input
1.37 - * stream then provides whatever data bytes
1.38 - * are written to the piped output stream.
1.39 - * Typically, data is read from a <code>PipedInputStream</code>
1.40 - * object by one thread and data is written
1.41 - * to the corresponding <code>PipedOutputStream</code>
1.42 - * by some other thread. Attempting to use
1.43 - * both objects from a single thread is not
1.44 - * recommended, as it may deadlock the thread.
1.45 - * The piped input stream contains a buffer,
1.46 - * decoupling read operations from write operations,
1.47 - * within limits.
1.48 - * A pipe is said to be <a name="BROKEN"> <i>broken</i> </a> if a
1.49 - * thread that was providing data bytes to the connected
1.50 - * piped output stream is no longer alive.
1.51 - *
1.52 - * @author James Gosling
1.53 - * @see java.io.PipedOutputStream
1.54 - * @since JDK1.0
1.55 - */
1.56 -public class PipedInputStream extends InputStream {
1.57 - boolean closedByWriter = false;
1.58 - volatile boolean closedByReader = false;
1.59 - boolean connected = false;
1.60 -
1.61 - /* REMIND: identification of the read and write sides needs to be
1.62 - more sophisticated. Either using thread groups (but what about
1.63 - pipes within a thread?) or using finalization (but it may be a
1.64 - long time until the next GC). */
1.65 - Thread readSide;
1.66 - Thread writeSide;
1.67 -
1.68 - private static final int DEFAULT_PIPE_SIZE = 1024;
1.69 -
1.70 - /**
1.71 - * The default size of the pipe's circular input buffer.
1.72 - * @since JDK1.1
1.73 - */
1.74 - // This used to be a constant before the pipe size was allowed
1.75 - // to change. This field will continue to be maintained
1.76 - // for backward compatibility.
1.77 - protected static final int PIPE_SIZE = DEFAULT_PIPE_SIZE;
1.78 -
1.79 - /**
1.80 - * The circular buffer into which incoming data is placed.
1.81 - * @since JDK1.1
1.82 - */
1.83 - protected byte buffer[];
1.84 -
1.85 - /**
1.86 - * The index of the position in the circular buffer at which the
1.87 - * next byte of data will be stored when received from the connected
1.88 - * piped output stream. <code>in<0</code> implies the buffer is empty,
1.89 - * <code>in==out</code> implies the buffer is full
1.90 - * @since JDK1.1
1.91 - */
1.92 - protected int in = -1;
1.93 -
1.94 - /**
1.95 - * The index of the position in the circular buffer at which the next
1.96 - * byte of data will be read by this piped input stream.
1.97 - * @since JDK1.1
1.98 - */
1.99 - protected int out = 0;
1.100 -
1.101 - /**
1.102 - * Creates a <code>PipedInputStream</code> so
1.103 - * that it is connected to the piped output
1.104 - * stream <code>src</code>. Data bytes written
1.105 - * to <code>src</code> will then be available
1.106 - * as input from this stream.
1.107 - *
1.108 - * @param src the stream to connect to.
1.109 - * @exception IOException if an I/O error occurs.
1.110 - */
1.111 - public PipedInputStream(PipedOutputStream src) throws IOException {
1.112 - this(src, DEFAULT_PIPE_SIZE);
1.113 - }
1.114 -
1.115 - /**
1.116 - * Creates a <code>PipedInputStream</code> so that it is
1.117 - * connected to the piped output stream
1.118 - * <code>src</code> and uses the specified pipe size for
1.119 - * the pipe's buffer.
1.120 - * Data bytes written to <code>src</code> will then
1.121 - * be available as input from this stream.
1.122 - *
1.123 - * @param src the stream to connect to.
1.124 - * @param pipeSize the size of the pipe's buffer.
1.125 - * @exception IOException if an I/O error occurs.
1.126 - * @exception IllegalArgumentException if {@code pipeSize <= 0}.
1.127 - * @since 1.6
1.128 - */
1.129 - public PipedInputStream(PipedOutputStream src, int pipeSize)
1.130 - throws IOException {
1.131 - initPipe(pipeSize);
1.132 - connect(src);
1.133 - }
1.134 -
1.135 - /**
1.136 - * Creates a <code>PipedInputStream</code> so
1.137 - * that it is not yet {@linkplain #connect(java.io.PipedOutputStream)
1.138 - * connected}.
1.139 - * It must be {@linkplain java.io.PipedOutputStream#connect(
1.140 - * java.io.PipedInputStream) connected} to a
1.141 - * <code>PipedOutputStream</code> before being used.
1.142 - */
1.143 - public PipedInputStream() {
1.144 - initPipe(DEFAULT_PIPE_SIZE);
1.145 - }
1.146 -
1.147 - /**
1.148 - * Creates a <code>PipedInputStream</code> so that it is not yet
1.149 - * {@linkplain #connect(java.io.PipedOutputStream) connected} and
1.150 - * uses the specified pipe size for the pipe's buffer.
1.151 - * It must be {@linkplain java.io.PipedOutputStream#connect(
1.152 - * java.io.PipedInputStream)
1.153 - * connected} to a <code>PipedOutputStream</code> before being used.
1.154 - *
1.155 - * @param pipeSize the size of the pipe's buffer.
1.156 - * @exception IllegalArgumentException if {@code pipeSize <= 0}.
1.157 - * @since 1.6
1.158 - */
1.159 - public PipedInputStream(int pipeSize) {
1.160 - initPipe(pipeSize);
1.161 - }
1.162 -
1.163 - private void initPipe(int pipeSize) {
1.164 - if (pipeSize <= 0) {
1.165 - throw new IllegalArgumentException("Pipe Size <= 0");
1.166 - }
1.167 - buffer = new byte[pipeSize];
1.168 - }
1.169 -
1.170 - /**
1.171 - * Causes this piped input stream to be connected
1.172 - * to the piped output stream <code>src</code>.
1.173 - * If this object is already connected to some
1.174 - * other piped output stream, an <code>IOException</code>
1.175 - * is thrown.
1.176 - * <p>
1.177 - * If <code>src</code> is an
1.178 - * unconnected piped output stream and <code>snk</code>
1.179 - * is an unconnected piped input stream, they
1.180 - * may be connected by either the call:
1.181 - *
1.182 - * <pre><code>snk.connect(src)</code> </pre>
1.183 - * <p>
1.184 - * or the call:
1.185 - *
1.186 - * <pre><code>src.connect(snk)</code> </pre>
1.187 - * <p>
1.188 - * The two calls have the same effect.
1.189 - *
1.190 - * @param src The piped output stream to connect to.
1.191 - * @exception IOException if an I/O error occurs.
1.192 - */
1.193 - public void connect(PipedOutputStream src) throws IOException {
1.194 - src.connect(this);
1.195 - }
1.196 -
1.197 - /**
1.198 - * Receives a byte of data. This method will block if no input is
1.199 - * available.
1.200 - * @param b the byte being received
1.201 - * @exception IOException If the pipe is <a href="#BROKEN"> <code>broken</code></a>,
1.202 - * {@link #connect(java.io.PipedOutputStream) unconnected},
1.203 - * closed, or if an I/O error occurs.
1.204 - * @since JDK1.1
1.205 - */
1.206 - protected synchronized void receive(int b) throws IOException {
1.207 - checkStateForReceive();
1.208 - writeSide = Thread.currentThread();
1.209 - if (in == out)
1.210 - awaitSpace();
1.211 - if (in < 0) {
1.212 - in = 0;
1.213 - out = 0;
1.214 - }
1.215 - buffer[in++] = (byte)(b & 0xFF);
1.216 - if (in >= buffer.length) {
1.217 - in = 0;
1.218 - }
1.219 - }
1.220 -
1.221 - /**
1.222 - * Receives data into an array of bytes. This method will
1.223 - * block until some input is available.
1.224 - * @param b the buffer into which the data is received
1.225 - * @param off the start offset of the data
1.226 - * @param len the maximum number of bytes received
1.227 - * @exception IOException If the pipe is <a href="#BROKEN"> broken</a>,
1.228 - * {@link #connect(java.io.PipedOutputStream) unconnected},
1.229 - * closed,or if an I/O error occurs.
1.230 - */
1.231 - synchronized void receive(byte b[], int off, int len) throws IOException {
1.232 - checkStateForReceive();
1.233 - writeSide = Thread.currentThread();
1.234 - int bytesToTransfer = len;
1.235 - while (bytesToTransfer > 0) {
1.236 - if (in == out)
1.237 - awaitSpace();
1.238 - int nextTransferAmount = 0;
1.239 - if (out < in) {
1.240 - nextTransferAmount = buffer.length - in;
1.241 - } else if (in < out) {
1.242 - if (in == -1) {
1.243 - in = out = 0;
1.244 - nextTransferAmount = buffer.length - in;
1.245 - } else {
1.246 - nextTransferAmount = out - in;
1.247 - }
1.248 - }
1.249 - if (nextTransferAmount > bytesToTransfer)
1.250 - nextTransferAmount = bytesToTransfer;
1.251 - assert(nextTransferAmount > 0);
1.252 - System.arraycopy(b, off, buffer, in, nextTransferAmount);
1.253 - bytesToTransfer -= nextTransferAmount;
1.254 - off += nextTransferAmount;
1.255 - in += nextTransferAmount;
1.256 - if (in >= buffer.length) {
1.257 - in = 0;
1.258 - }
1.259 - }
1.260 - }
1.261 -
1.262 - private void checkStateForReceive() throws IOException {
1.263 - if (!connected) {
1.264 - throw new IOException("Pipe not connected");
1.265 - } else if (closedByWriter || closedByReader) {
1.266 - throw new IOException("Pipe closed");
1.267 - }
1.268 - }
1.269 -
1.270 - private void awaitSpace() throws IOException {
1.271 - while (in == out) {
1.272 - checkStateForReceive();
1.273 -
1.274 - /* full: kick any waiting readers */
1.275 - notifyAll();
1.276 - try {
1.277 - wait(1000);
1.278 - } catch (InterruptedException ex) {
1.279 - throw new java.io.InterruptedIOException();
1.280 - }
1.281 - }
1.282 - }
1.283 -
1.284 - /**
1.285 - * Notifies all waiting threads that the last byte of data has been
1.286 - * received.
1.287 - */
1.288 - synchronized void receivedLast() {
1.289 - closedByWriter = true;
1.290 - notifyAll();
1.291 - }
1.292 -
1.293 - /**
1.294 - * Reads the next byte of data from this piped input stream. The
1.295 - * value byte is returned as an <code>int</code> in the range
1.296 - * <code>0</code> to <code>255</code>.
1.297 - * This method blocks until input data is available, the end of the
1.298 - * stream is detected, or an exception is thrown.
1.299 - *
1.300 - * @return the next byte of data, or <code>-1</code> if the end of the
1.301 - * stream is reached.
1.302 - * @exception IOException if the pipe is
1.303 - * {@link #connect(java.io.PipedOutputStream) unconnected},
1.304 - * <a href="#BROKEN"> <code>broken</code></a>, closed,
1.305 - * or if an I/O error occurs.
1.306 - */
1.307 - public synchronized int read() throws IOException {
1.308 - if (!connected) {
1.309 - throw new IOException("Pipe not connected");
1.310 - } else if (closedByReader) {
1.311 - throw new IOException("Pipe closed");
1.312 - }
1.313 -
1.314 - readSide = Thread.currentThread();
1.315 - int trials = 2;
1.316 - while (in < 0) {
1.317 - if (closedByWriter) {
1.318 - /* closed by writer, return EOF */
1.319 - return -1;
1.320 - }
1.321 -// if ((writeSide != null) && (!writeSide.isAlive()) && (--trials < 0)) {
1.322 -// throw new IOException("Pipe broken");
1.323 -// }
1.324 - /* might be a writer waiting */
1.325 - notifyAll();
1.326 - try {
1.327 - wait(1000);
1.328 - } catch (InterruptedException ex) {
1.329 - throw new java.io.InterruptedIOException();
1.330 - }
1.331 - }
1.332 - int ret = buffer[out++] & 0xFF;
1.333 - if (out >= buffer.length) {
1.334 - out = 0;
1.335 - }
1.336 - if (in == out) {
1.337 - /* now empty */
1.338 - in = -1;
1.339 - }
1.340 -
1.341 - return ret;
1.342 - }
1.343 -
1.344 - /**
1.345 - * Reads up to <code>len</code> bytes of data from this piped input
1.346 - * stream into an array of bytes. Less than <code>len</code> bytes
1.347 - * will be read if the end of the data stream is reached or if
1.348 - * <code>len</code> exceeds the pipe's buffer size.
1.349 - * If <code>len </code> is zero, then no bytes are read and 0 is returned;
1.350 - * otherwise, the method blocks until at least 1 byte of input is
1.351 - * available, end of the stream has been detected, or an exception is
1.352 - * thrown.
1.353 - *
1.354 - * @param b the buffer into which the data is read.
1.355 - * @param off the start offset in the destination array <code>b</code>
1.356 - * @param len the maximum number of bytes read.
1.357 - * @return the total number of bytes read into the buffer, or
1.358 - * <code>-1</code> if there is no more data because the end of
1.359 - * the stream has been reached.
1.360 - * @exception NullPointerException If <code>b</code> is <code>null</code>.
1.361 - * @exception IndexOutOfBoundsException If <code>off</code> is negative,
1.362 - * <code>len</code> is negative, or <code>len</code> is greater than
1.363 - * <code>b.length - off</code>
1.364 - * @exception IOException if the pipe is <a href="#BROKEN"> <code>broken</code></a>,
1.365 - * {@link #connect(java.io.PipedOutputStream) unconnected},
1.366 - * closed, or if an I/O error occurs.
1.367 - */
1.368 - public synchronized int read(byte b[], int off, int len) throws IOException {
1.369 - if (b == null) {
1.370 - throw new NullPointerException();
1.371 - } else if (off < 0 || len < 0 || len > b.length - off) {
1.372 - throw new IndexOutOfBoundsException();
1.373 - } else if (len == 0) {
1.374 - return 0;
1.375 - }
1.376 -
1.377 - /* possibly wait on the first character */
1.378 - int c = read();
1.379 - if (c < 0) {
1.380 - return -1;
1.381 - }
1.382 - b[off] = (byte) c;
1.383 - int rlen = 1;
1.384 - while ((in >= 0) && (len > 1)) {
1.385 -
1.386 - int available;
1.387 -
1.388 - if (in > out) {
1.389 - available = Math.min((buffer.length - out), (in - out));
1.390 - } else {
1.391 - available = buffer.length - out;
1.392 - }
1.393 -
1.394 - // A byte is read beforehand outside the loop
1.395 - if (available > (len - 1)) {
1.396 - available = len - 1;
1.397 - }
1.398 - System.arraycopy(buffer, out, b, off + rlen, available);
1.399 - out += available;
1.400 - rlen += available;
1.401 - len -= available;
1.402 -
1.403 - if (out >= buffer.length) {
1.404 - out = 0;
1.405 - }
1.406 - if (in == out) {
1.407 - /* now empty */
1.408 - in = -1;
1.409 - }
1.410 - }
1.411 - return rlen;
1.412 - }
1.413 -
1.414 - /**
1.415 - * Returns the number of bytes that can be read from this input
1.416 - * stream without blocking.
1.417 - *
1.418 - * @return the number of bytes that can be read from this input stream
1.419 - * without blocking, or {@code 0} if this input stream has been
1.420 - * closed by invoking its {@link #close()} method, or if the pipe
1.421 - * is {@link #connect(java.io.PipedOutputStream) unconnected}, or
1.422 - * <a href="#BROKEN"> <code>broken</code></a>.
1.423 - *
1.424 - * @exception IOException if an I/O error occurs.
1.425 - * @since JDK1.0.2
1.426 - */
1.427 - public synchronized int available() throws IOException {
1.428 - if(in < 0)
1.429 - return 0;
1.430 - else if(in == out)
1.431 - return buffer.length;
1.432 - else if (in > out)
1.433 - return in - out;
1.434 - else
1.435 - return in + buffer.length - out;
1.436 - }
1.437 -
1.438 - /**
1.439 - * Closes this piped input stream and releases any system resources
1.440 - * associated with the stream.
1.441 - *
1.442 - * @exception IOException if an I/O error occurs.
1.443 - */
1.444 - public void close() throws IOException {
1.445 - closedByReader = true;
1.446 - synchronized (this) {
1.447 - in = -1;
1.448 - }
1.449 - }
1.450 -}
2.1 --- a/jshell.support/PipedOutputStream.java Thu Jun 08 01:04:10 2017 -0700
2.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
2.3 @@ -1,180 +0,0 @@
2.4 -/*
2.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2.6 - *
2.7 - * Copyright 2015 Oracle and/or its affiliates. All rights reserved.
2.8 - *
2.9 - * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
2.10 - * Other names may be trademarks of their respective owners.
2.11 - *
2.12 - * The contents of this file are subject to the terms of either the GNU
2.13 - * General Public License Version 2 only ("GPL") or the Common
2.14 - * Development and Distribution License("CDDL") (collectively, the
2.15 - * "License"). You may not use this file except in compliance with the
2.16 - * License. You can obtain a copy of the License at
2.17 - * http://www.netbeans.org/cddl-gplv2.html
2.18 - * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
2.19 - * specific language governing permissions and limitations under the
2.20 - * License. When distributing the software, include this License Header
2.21 - * Notice in each file and include the License file at
2.22 - * nbbuild/licenses/CDDL-GPL-2-CP. Oracle designates this
2.23 - * particular file as subject to the "Classpath" exception as provided
2.24 - * by Oracle in the GPL Version 2 section of the License file that
2.25 - * accompanied this code. If applicable, add the following below the
2.26 - * License Header, with the fields enclosed by brackets [] replaced by
2.27 - * your own identifying information:
2.28 - * "Portions Copyrighted [year] [name of copyright owner]"
2.29 - *
2.30 - * If you wish your version of this file to be governed by only the CDDL
2.31 - * or only the GPL Version 2, indicate your decision by adding
2.32 - * "[Contributor] elects to include this software in this distribution
2.33 - * under the [CDDL or GPL Version 2] license." If you do not indicate a
2.34 - * single choice of license, a recipient has the option to distribute
2.35 - * your version of this file under either the CDDL, the GPL Version 2 or
2.36 - * to extend the choice of license to its licensees as provided above.
2.37 - * However, if you add GPL Version 2 code and therefore, elected the GPL
2.38 - * Version 2 license, then the option applies only if the new code is
2.39 - * made subject to such option by the copyright holder.
2.40 - *
2.41 - * Contributor(s):
2.42 - *
2.43 - * Portions Copyrighted 2015 Sun Microsystems, Inc.
2.44 - */
2.45 -package org.netbeans.modules.jshell.support;
2.46 -
2.47 -import java.io.IOException;
2.48 -import java.io.OutputStream;
2.49 -
2.50 -public
2.51 -class PipedOutputStream extends OutputStream {
2.52 -
2.53 - /* REMIND: identification of the read and write sides needs to be
2.54 - more sophisticated. Either using thread groups (but what about
2.55 - pipes within a thread?) or using finalization (but it may be a
2.56 - long time until the next GC). */
2.57 - private PipedInputStream sink;
2.58 -
2.59 - /**
2.60 - * Creates a piped output stream connected to the specified piped
2.61 - * input stream. Data bytes written to this stream will then be
2.62 - * available as input from <code>snk</code>.
2.63 - *
2.64 - * @param snk The piped input stream to connect to.
2.65 - * @exception IOException if an I/O error occurs.
2.66 - */
2.67 - public PipedOutputStream(PipedInputStream snk) throws IOException {
2.68 - connect(snk);
2.69 - }
2.70 -
2.71 - /**
2.72 - * Creates a piped output stream that is not yet connected to a
2.73 - * piped input stream. It must be connected to a piped input stream,
2.74 - * either by the receiver or the sender, before being used.
2.75 - *
2.76 - * @see PipedInputStream#connect(java.io.PipedOutputStream)
2.77 - * @see java.io.PipedOutputStream#connect(PipedInputStream)
2.78 - */
2.79 - public PipedOutputStream() {
2.80 - }
2.81 -
2.82 - /**
2.83 - * Connects this piped output stream to a receiver. If this object
2.84 - * is already connected to some other piped input stream, an
2.85 - * <code>IOException</code> is thrown.
2.86 - * <p>
2.87 - * If <code>snk</code> is an unconnected piped input stream and
2.88 - * <code>src</code> is an unconnected piped output stream, they may
2.89 - * be connected by either the call:
2.90 - * <blockquote><pre>
2.91 - * src.connect(snk)</pre></blockquote>
2.92 - * or the call:
2.93 - * <blockquote><pre>
2.94 - * snk.connect(src)</pre></blockquote>
2.95 - * The two calls have the same effect.
2.96 - *
2.97 - * @param snk the piped input stream to connect to.
2.98 - * @exception IOException if an I/O error occurs.
2.99 - */
2.100 - public synchronized void connect(PipedInputStream snk) throws IOException {
2.101 - if (snk == null) {
2.102 - throw new NullPointerException();
2.103 - } else if (sink != null || snk.connected) {
2.104 - throw new IOException("Already connected");
2.105 - }
2.106 - sink = snk;
2.107 - snk.in = -1;
2.108 - snk.out = 0;
2.109 - snk.connected = true;
2.110 - }
2.111 -
2.112 - /**
2.113 - * Writes the specified <code>byte</code> to the piped output stream.
2.114 - * <p>
2.115 - * Implements the <code>write</code> method of <code>OutputStream</code>.
2.116 - *
2.117 - * @param b the <code>byte</code> to be written.
2.118 - * @exception IOException if the pipe is <a href=#BROKEN> broken</a>,
2.119 - * {@link #connect(PipedInputStream) unconnected},
2.120 - * closed, or if an I/O error occurs.
2.121 - */
2.122 - public void write(int b) throws IOException {
2.123 - if (sink == null) {
2.124 - throw new IOException("Pipe not connected");
2.125 - }
2.126 - sink.receive(b);
2.127 - }
2.128 -
2.129 - /**
2.130 - * Writes <code>len</code> bytes from the specified byte array
2.131 - * starting at offset <code>off</code> to this piped output stream.
2.132 - * This method blocks until all the bytes are written to the output
2.133 - * stream.
2.134 - *
2.135 - * @param b the data.
2.136 - * @param off the start offset in the data.
2.137 - * @param len the number of bytes to write.
2.138 - * @exception IOException if the pipe is <a href=#BROKEN> broken</a>,
2.139 - * {@link #connect(PipedInputStream) unconnected},
2.140 - * closed, or if an I/O error occurs.
2.141 - */
2.142 - public void write(byte b[], int off, int len) throws IOException {
2.143 - if (sink == null) {
2.144 - throw new IOException("Pipe not connected");
2.145 - } else if (b == null) {
2.146 - throw new NullPointerException();
2.147 - } else if ((off < 0) || (off > b.length) || (len < 0) ||
2.148 - ((off + len) > b.length) || ((off + len) < 0)) {
2.149 - throw new IndexOutOfBoundsException();
2.150 - } else if (len == 0) {
2.151 - return;
2.152 - }
2.153 - sink.receive(b, off, len);
2.154 - }
2.155 -
2.156 - /**
2.157 - * Flushes this output stream and forces any buffered output bytes
2.158 - * to be written out.
2.159 - * This will notify any readers that bytes are waiting in the pipe.
2.160 - *
2.161 - * @exception IOException if an I/O error occurs.
2.162 - */
2.163 - public synchronized void flush() throws IOException {
2.164 - if (sink != null) {
2.165 - synchronized (sink) {
2.166 - sink.notifyAll();
2.167 - }
2.168 - }
2.169 - }
2.170 -
2.171 - /**
2.172 - * Closes this piped output stream and releases any system resources
2.173 - * associated with this stream. This stream may no longer be used for
2.174 - * writing bytes.
2.175 - *
2.176 - * @exception IOException if an I/O error occurs.
2.177 - */
2.178 - public void close() throws IOException {
2.179 - if (sink != null) {
2.180 - sink.receivedLast();
2.181 - }
2.182 - }
2.183 -}