1. /*
  2. * @(#)PipedWriter.java 1.13 00/02/02
  3. *
  4. * Copyright 1996-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.io;
  11. /**
  12. * Piped character-output streams.
  13. *
  14. * @version 1.13, 00/02/02
  15. * @author Mark Reinhold
  16. * @since JDK1.1
  17. */
  18. public class PipedWriter extends Writer {
  19. /* REMIND: identification of the read and write sides needs to be
  20. more sophisticated. Either using thread groups (but what about
  21. pipes within a thread?) or using finalization (but it may be a
  22. long time until the next GC). */
  23. private PipedReader sink;
  24. /* This flag records the open status of this particular writer. It
  25. * is independent of the status flags defined in PipedReader. It is
  26. * used to do a sanity check on connect.
  27. */
  28. private boolean closed = false;
  29. /**
  30. * Creates a piped writer connected to the specified piped
  31. * reader. Data characters written to this stream will then be
  32. * available as input from <code>snk</code>.
  33. *
  34. * @param snk The piped reader to connect to.
  35. * @exception IOException if an I/O error occurs.
  36. */
  37. public PipedWriter(PipedReader snk) throws IOException {
  38. connect(snk);
  39. }
  40. /**
  41. * Creates a piped writer that is not yet connected to a
  42. * piped reader. It must be connected to a piped reader,
  43. * either by the receiver or the sender, before being used.
  44. *
  45. * @see java.io.PipedReader#connect(java.io.PipedWriter)
  46. * @see java.io.PipedWriter#connect(java.io.PipedReader)
  47. */
  48. public PipedWriter() {
  49. }
  50. /**
  51. * Connects this piped writer to a receiver. If this object
  52. * is already connected to some other piped reader, an
  53. * <code>IOException</code> is thrown.
  54. * <p>
  55. * If <code>snk</code> is an unconnected piped reader and
  56. * <code>src</code> is an unconnected piped writer, they may
  57. * be connected by either the call:
  58. * <blockquote><pre>
  59. * src.connect(snk)</pre></blockquote>
  60. * or the call:
  61. * <blockquote><pre>
  62. * snk.connect(src)</pre></blockquote>
  63. * The two calls have the same effect.
  64. *
  65. * @param snk the piped reader to connect to.
  66. * @exception IOException if an I/O error occurs.
  67. */
  68. public synchronized void connect(PipedReader snk) throws IOException {
  69. if (snk == null) {
  70. throw new NullPointerException();
  71. } else if (sink != null || snk.connected) {
  72. throw new IOException("Already connected");
  73. } else if (snk.closedByReader || closed) {
  74. throw new IOException("Pipe closed");
  75. }
  76. sink = snk;
  77. snk.in = -1;
  78. snk.out = 0;
  79. snk.connected = true;
  80. }
  81. /**
  82. * Writes the specified <code>char</code> to the piped output stream.
  83. * If a thread was reading data characters from the connected piped input
  84. * stream, but the thread is no longer alive, then an
  85. * <code>IOException</code> is thrown.
  86. * <p>
  87. * Implements the <code>write</code> method of <code>Writer</code>.
  88. *
  89. * @param c the <code>char</code> to be written.
  90. * @exception IOException if an I/O error occurs.
  91. */
  92. public void write(int c) throws IOException {
  93. if (sink == null) {
  94. throw new IOException("Pipe not connected");
  95. }
  96. sink.receive(c);
  97. }
  98. /**
  99. * Writes <code>len</code> characters from the specified character array
  100. * starting at offset <code>off</code> to this piped output stream.
  101. * If a thread was reading data characters from the connected piped input
  102. * stream, but the thread is no longer alive, then an
  103. * <code>IOException</code> is thrown.
  104. *
  105. * @param cbuf the data.
  106. * @param off the start offset in the data.
  107. * @param len the number of characters to write.
  108. * @exception IOException if an I/O error occurs.
  109. */
  110. public void write(char cbuf[], int off, int len) throws IOException {
  111. if (sink == null) {
  112. throw new IOException("Pipe not connected");
  113. } else if ((off | len | (off + len) | (cbuf.length - (off + len))) < 0) {
  114. throw new IndexOutOfBoundsException();
  115. }
  116. sink.receive(cbuf, off, len);
  117. }
  118. /**
  119. * Flushes this output stream and forces any buffered output characters
  120. * to be written out.
  121. * This will notify any readers that characters are waiting in the pipe.
  122. *
  123. * @exception IOException if an I/O error occurs.
  124. */
  125. public synchronized void flush() throws IOException {
  126. if (sink != null) {
  127. if (sink.closedByReader || closed) {
  128. throw new IOException("Pipe closed");
  129. }
  130. synchronized (sink) {
  131. sink.notifyAll();
  132. }
  133. }
  134. }
  135. /**
  136. * Closes this piped output stream and releases any system resources
  137. * associated with this stream. This stream may no longer be used for
  138. * writing characters.
  139. *
  140. * @exception IOException if an I/O error occurs.
  141. */
  142. public void close() throws IOException {
  143. closed = true;
  144. if (sink != null) {
  145. sink.receivedLast();
  146. }
  147. }
  148. }