0N/A/*
2362N/A * Copyright (c) 1994, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
2362N/A * published by the Free Software Foundation. Oracle designates this
0N/A * particular file as subject to the "Classpath" exception as provided
2362N/A * by Oracle in the LICENSE file that accompanied this code.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/Apackage java.io;
0N/A
0N/Aimport java.io.InputStream;
0N/Aimport java.util.Enumeration;
0N/Aimport java.util.Vector;
0N/A
0N/A/**
0N/A * A <code>SequenceInputStream</code> represents
0N/A * the logical concatenation of other input
0N/A * streams. It starts out with an ordered
0N/A * collection of input streams and reads from
0N/A * the first one until end of file is reached,
0N/A * whereupon it reads from the second one,
0N/A * and so on, until end of file is reached
0N/A * on the last of the contained input streams.
0N/A *
0N/A * @author Author van Hoff
0N/A * @since JDK1.0
0N/A */
0N/Apublic
0N/Aclass SequenceInputStream extends InputStream {
0N/A Enumeration e;
0N/A InputStream in;
0N/A
0N/A /**
0N/A * Initializes a newly created <code>SequenceInputStream</code>
0N/A * by remembering the argument, which must
0N/A * be an <code>Enumeration</code> that produces
0N/A * objects whose run-time type is <code>InputStream</code>.
0N/A * The input streams that are produced by
0N/A * the enumeration will be read, in order,
0N/A * to provide the bytes to be read from this
0N/A * <code>SequenceInputStream</code>. After
0N/A * each input stream from the enumeration
0N/A * is exhausted, it is closed by calling its
0N/A * <code>close</code> method.
0N/A *
0N/A * @param e an enumeration of input streams.
0N/A * @see java.util.Enumeration
0N/A */
0N/A public SequenceInputStream(Enumeration<? extends InputStream> e) {
0N/A this.e = e;
0N/A try {
0N/A nextStream();
0N/A } catch (IOException ex) {
0N/A // This should never happen
0N/A throw new Error("panic");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Initializes a newly
0N/A * created <code>SequenceInputStream</code>
0N/A * by remembering the two arguments, which
0N/A * will be read in order, first <code>s1</code>
0N/A * and then <code>s2</code>, to provide the
0N/A * bytes to be read from this <code>SequenceInputStream</code>.
0N/A *
0N/A * @param s1 the first input stream to read.
0N/A * @param s2 the second input stream to read.
0N/A */
0N/A public SequenceInputStream(InputStream s1, InputStream s2) {
0N/A Vector v = new Vector(2);
0N/A
0N/A v.addElement(s1);
0N/A v.addElement(s2);
0N/A e = v.elements();
0N/A try {
0N/A nextStream();
0N/A } catch (IOException ex) {
0N/A // This should never happen
0N/A throw new Error("panic");
0N/A }
0N/A }
0N/A
0N/A /**
0N/A * Continues reading in the next stream if an EOF is reached.
0N/A */
0N/A final void nextStream() throws IOException {
0N/A if (in != null) {
0N/A in.close();
0N/A }
0N/A
0N/A if (e.hasMoreElements()) {
0N/A in = (InputStream) e.nextElement();
0N/A if (in == null)
0N/A throw new NullPointerException();
0N/A }
0N/A else in = null;
0N/A
0N/A }
0N/A
0N/A /**
0N/A * Returns an estimate of the number of bytes that can be read (or
0N/A * skipped over) from the current underlying input stream without
0N/A * blocking by the next invocation of a method for the current
0N/A * underlying input stream. The next invocation might be
0N/A * the same thread or another thread. A single read or skip of this
0N/A * many bytes will not block, but may read or skip fewer bytes.
0N/A * <p>
0N/A * This method simply calls {@code available} of the current underlying
0N/A * input stream and returns the result.
0N/A *
0N/A * @return an estimate of the number of bytes that can be read (or
0N/A * skipped over) from the current underlying input stream
0N/A * without blocking or {@code 0} if this input stream
0N/A * has been closed by invoking its {@link #close()} method
0N/A * @exception IOException if an I/O error occurs.
0N/A *
0N/A * @since JDK1.1
0N/A */
0N/A public int available() throws IOException {
0N/A if(in == null) {
0N/A return 0; // no way to signal EOF from available()
0N/A }
0N/A return in.available();
0N/A }
0N/A
0N/A /**
0N/A * Reads the next byte of data from this input stream. The byte is
0N/A * returned as an <code>int</code> in the range <code>0</code> to
0N/A * <code>255</code>. If no byte is available because the end of the
0N/A * stream has been reached, the value <code>-1</code> is returned.
0N/A * This method blocks until input data is available, the end of the
0N/A * stream is detected, or an exception is thrown.
0N/A * <p>
0N/A * This method
0N/A * tries to read one character from the current substream. If it
0N/A * reaches the end of the stream, it calls the <code>close</code>
0N/A * method of the current substream and begins reading from the next
0N/A * substream.
0N/A *
0N/A * @return the next byte of data, or <code>-1</code> if the end of the
0N/A * stream is reached.
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public int read() throws IOException {
0N/A if (in == null) {
0N/A return -1;
0N/A }
0N/A int c = in.read();
0N/A if (c == -1) {
0N/A nextStream();
0N/A return read();
0N/A }
0N/A return c;
0N/A }
0N/A
0N/A /**
0N/A * Reads up to <code>len</code> bytes of data from this input stream
0N/A * into an array of bytes. If <code>len</code> is not zero, the method
0N/A * blocks until at least 1 byte of input is available; otherwise, no
0N/A * bytes are read and <code>0</code> is returned.
0N/A * <p>
0N/A * The <code>read</code> method of <code>SequenceInputStream</code>
0N/A * tries to read the data from the current substream. If it fails to
0N/A * read any characters because the substream has reached the end of
0N/A * the stream, it calls the <code>close</code> method of the current
0N/A * substream and begins reading from the next substream.
0N/A *
0N/A * @param b the buffer into which the data is read.
0N/A * @param off the start offset in array <code>b</code>
0N/A * at which the data is written.
0N/A * @param len the maximum number of bytes read.
0N/A * @return int the number of bytes read.
0N/A * @exception NullPointerException If <code>b</code> is <code>null</code>.
0N/A * @exception IndexOutOfBoundsException If <code>off</code> is negative,
0N/A * <code>len</code> is negative, or <code>len</code> is greater than
0N/A * <code>b.length - off</code>
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public int read(byte b[], int off, int len) throws IOException {
0N/A if (in == null) {
0N/A return -1;
0N/A } else if (b == null) {
0N/A throw new NullPointerException();
0N/A } else if (off < 0 || len < 0 || len > b.length - off) {
0N/A throw new IndexOutOfBoundsException();
0N/A } else if (len == 0) {
0N/A return 0;
0N/A }
0N/A
0N/A int n = in.read(b, off, len);
0N/A if (n <= 0) {
0N/A nextStream();
0N/A return read(b, off, len);
0N/A }
0N/A return n;
0N/A }
0N/A
0N/A /**
0N/A * Closes this input stream and releases any system resources
0N/A * associated with the stream.
0N/A * A closed <code>SequenceInputStream</code>
0N/A * cannot perform input operations and cannot
0N/A * be reopened.
0N/A * <p>
0N/A * If this stream was created
0N/A * from an enumeration, all remaining elements
0N/A * are requested from the enumeration and closed
0N/A * before the <code>close</code> method returns.
0N/A *
0N/A * @exception IOException if an I/O error occurs.
0N/A */
0N/A public void close() throws IOException {
0N/A do {
0N/A nextStream();
0N/A } while (in != null);
0N/A }
0N/A}