1. /*
  2. * @(#)SequenceInputStream.java 1.23 00/02/02
  3. *
  4. * Copyright 1994-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. import java.io.InputStream;
  12. import java.util.Enumeration;
  13. import java.util.Vector;
  14. /**
  15. * A <code>SequenceInputStream</code> represents
  16. * the logical concatenation of other input
  17. * streams. It starts out with an ordered
  18. * collection of input streams and reads from
  19. * the first one until end of file is reached,
  20. * whereupon it reads from the second one,
  21. * and so on, until end of file is reached
  22. * on the last of the contained input streams.
  23. *
  24. * @author Author van Hoff
  25. * @version 1.23, 02/02/00
  26. * @since JDK1.0
  27. */
  28. public
  29. class SequenceInputStream extends InputStream {
  30. Enumeration e;
  31. InputStream in;
  32. /**
  33. * Initializes a newly created <code>SequenceInputStream</code>
  34. * by remembering the argument, which must
  35. * be an <code>Enumeration</code> that produces
  36. * objects whose run-time type is <code>InputStream</code>.
  37. * The input streams that are produced by
  38. * the enumeration will be read, in order,
  39. * to provide the bytes to be read from this
  40. * <code>SequenceInputStream</code>. After
  41. * each input stream from the enumeration
  42. * is exhausted, it is closed by calling its
  43. * <code>close</code> method.
  44. *
  45. * @param e an enumeration of input streams.
  46. * @see java.util.Enumeration
  47. */
  48. public SequenceInputStream(Enumeration e) {
  49. this.e = e;
  50. try {
  51. nextStream();
  52. } catch (IOException ex) {
  53. // This should never happen
  54. throw new Error("panic");
  55. }
  56. }
  57. /**
  58. * Initializes a newly
  59. * created <code>SequenceInputStream</code>
  60. * by remembering the two arguments, which
  61. * will be read in order, first <code>s1</code>
  62. * and then <code>s2</code>, to provide the
  63. * bytes to be read from this <code>SequenceInputStream</code>.
  64. *
  65. * @param s1 the first input stream to read.
  66. * @param s2 the second input stream to read.
  67. */
  68. public SequenceInputStream(InputStream s1, InputStream s2) {
  69. Vector v = new Vector(2);
  70. v.addElement(s1);
  71. v.addElement(s2);
  72. e = v.elements();
  73. try {
  74. nextStream();
  75. } catch (IOException ex) {
  76. // This should never happen
  77. throw new Error("panic");
  78. }
  79. }
  80. /**
  81. * Continues reading in the next stream if an EOF is reached.
  82. */
  83. final void nextStream() throws IOException {
  84. if (in != null) {
  85. in.close();
  86. }
  87. if (e.hasMoreElements()) {
  88. in = (InputStream) e.nextElement();
  89. if (in == null)
  90. throw new NullPointerException();
  91. }
  92. else in = null;
  93. }
  94. /**
  95. * Returns the number of bytes available on the current stream.
  96. *
  97. * @since JDK1.1
  98. */
  99. public int available() throws IOException {
  100. if(in == null) {
  101. return 0; // no way to signal EOF from available()
  102. }
  103. return in.available();
  104. }
  105. /**
  106. * Reads the next byte of data from this input stream. The byte is
  107. * returned as an <code>int</code> in the range <code>0</code> to
  108. * <code>255</code>. If no byte is available because the end of the
  109. * stream has been reached, the value <code>-1</code> is returned.
  110. * This method blocks until input data is available, the end of the
  111. * stream is detected, or an exception is thrown.
  112. * <p>
  113. * This method
  114. * tries to read one character from the current substream. If it
  115. * reaches the end of the stream, it calls the <code>close</code>
  116. * method of the current substream and begins reading from the next
  117. * substream.
  118. *
  119. * @return the next byte of data, or <code>-1</code> if the end of the
  120. * stream is reached.
  121. * @exception IOException if an I/O error occurs.
  122. */
  123. public int read() throws IOException {
  124. if (in == null) {
  125. return -1;
  126. }
  127. int c = in.read();
  128. if (c == -1) {
  129. nextStream();
  130. return read();
  131. }
  132. return c;
  133. }
  134. /**
  135. * Reads up to <code>len</code> bytes of data from this input stream
  136. * into an array of bytes. This method blocks until at least 1 byte
  137. * of input is available. If the first argument is <code>null</code>,
  138. * up to <code>len</code> bytes are read and discarded.
  139. * <p>
  140. * The <code>read</code> method of <code>SequenceInputStream</code>
  141. * tries to read the data from the current substream. If it fails to
  142. * read any characters because the substream has reached the end of
  143. * the stream, it calls the <code>close</code> method of the current
  144. * substream and begins reading from the next substream.
  145. *
  146. * @param b the buffer into which the data is read.
  147. * @param off the start offset of the data.
  148. * @param len the maximum number of bytes read.
  149. * @return int the number of bytes read.
  150. * @exception IOException if an I/O error occurs.
  151. */
  152. public int read(byte b[], int off, int len) throws IOException {
  153. if (in == null) {
  154. return -1;
  155. } else if (b == null) {
  156. throw new NullPointerException();
  157. } else if ((off < 0) || (off > b.length) || (len < 0) ||
  158. ((off + len) > b.length) || ((off + len) < 0)) {
  159. throw new IndexOutOfBoundsException();
  160. } else if (len == 0) {
  161. return 0;
  162. }
  163. int n = in.read(b, off, len);
  164. if (n <= 0) {
  165. nextStream();
  166. return read(b, off, len);
  167. }
  168. return n;
  169. }
  170. /**
  171. * Closes this input stream and releases any system resources
  172. * associated with the stream.
  173. * A closed <code>SequenceInputStream</code>
  174. * cannot perform input operations and cannot
  175. * be reopened.
  176. * <p>
  177. * If this stream was created
  178. * from an enumeration, all remaining elements
  179. * are requested from the enumeration and closed
  180. * before the <code>close</code> method returns.
  181. * of <code>InputStream</code> .
  182. *
  183. * @exception IOException if an I/O error occurs.
  184. */
  185. public void close() throws IOException {
  186. do {
  187. nextStream();
  188. } while (in != null);
  189. }
  190. }