Frames | No Frames |
1: /* SequenceInputStream.java -- Reads multiple input streams in sequence 2: Copyright (C) 1998, 1999, 2001, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.io; 40: 41: import java.util.Enumeration; 42: 43: /* Written using "Java Class Libraries", 2nd edition, ISBN 0-201-31002-3 44: * "The Java Language Specification", ISBN 0-201-63451-1 45: * plus online API docs for JDK 1.2 beta from http://www.javasoft.com. 46: * Status: Believed complete and correct. 47: */ 48: 49: /** 50: * This class merges a sequence of multiple <code>InputStream</code>'s in 51: * order to form a single logical stream that can be read by applications 52: * that expect only one stream. 53: * <p> 54: * The streams passed to the constructor method are read in order until 55: * they return -1 to indicate they are at end of stream. When a stream 56: * reports end of stream, it is closed, then the next stream is read. 57: * When the last stream is closed, the next attempt to read from this 58: * stream will return a -1 to indicate it is at end of stream. 59: * <p> 60: * If this stream is closed prior to all subordinate streams being read 61: * to completion, all subordinate streams are closed. 62: * 63: * @author Aaron M. Renn (arenn@urbanophile.com) 64: * @author Warren Levy (warrenl@cygnus.com) 65: */ 66: public class SequenceInputStream extends InputStream 67: { 68: /** The handle for the current input stream. */ 69: private InputStream in; 70: 71: /** Secondary input stream; not used if constructed w/ enumeration. */ 72: private InputStream in2; 73: 74: /** The enumeration handle; not used if constructed w/ 2 explicit input streams. */ 75: private Enumeration e; 76: 77: /** 78: * This method creates a new <code>SequenceInputStream</code> that obtains 79: * its list of subordinate <code>InputStream</code>s from the specified 80: * <code>Enumeration</code> 81: * 82: * @param e An <code>Enumeration</code> that will return a list of 83: * <code>InputStream</code>s to read in sequence 84: */ 85: public SequenceInputStream(Enumeration e) 86: { 87: this.e = e; 88: in = (InputStream) e.nextElement(); 89: in2 = null; 90: } 91: 92: /** 93: * This method creates a new <code>SequenceInputStream</code> that will read 94: * the two specified subordinate <code>InputStream</code>s in sequence. 95: * 96: * @param s1 The first <code>InputStream</code> to read 97: * @param s2 The second <code>InputStream</code> to read 98: */ 99: public SequenceInputStream(InputStream s1, InputStream s2) 100: { 101: in = s1; 102: in2 = s2; 103: } 104: 105: /** 106: * This method returns the number of bytes than can be read from the 107: * currently being read subordinate stream before that stream could 108: * block. Note that it is possible more bytes than this can actually 109: * be read without the stream blocking. If a 0 is returned, then the 110: * stream could block on the very next read. 111: * 112: * @return The number of bytes that can be read before blocking could occur 113: * 114: * @exception IOException If an error occurs 115: */ 116: public int available() throws IOException 117: { 118: if (in == null) 119: return 0; 120: 121: return in.available(); 122: } 123: 124: /** 125: * Closes this stream. This will cause any remaining unclosed subordinate 126: * <code>InputStream</code>'s to be closed as well. Subsequent attempts to 127: * read from this stream may cause an exception. 128: * 129: * @exception IOException If an error occurs 130: */ 131: public void close() throws IOException 132: { 133: while (in != null) 134: { 135: in.close(); 136: in = getNextStream (); 137: } 138: } 139: 140: /** 141: * This method reads an unsigned byte from the input stream and returns it 142: * as an int in the range of 0-255. This method also will return -1 if 143: * the end of the stream has been reached. This will only happen when 144: * all of the subordinate streams have been read. 145: * <p> 146: * This method will block until the byte can be read. 147: * 148: * @return The byte read, or -1 if end of stream 149: * 150: * @exception IOException If an error occurs 151: */ 152: public int read() throws IOException 153: { 154: int ch = -1; 155: 156: while (in != null && (ch = in.read()) < 0) 157: { 158: in.close(); 159: in = getNextStream(); 160: } 161: 162: return ch; 163: } 164: 165: /** 166: * This method reads bytes from a stream and stores them into a caller 167: * supplied buffer. It starts storing the data at index <code>offset</code> 168: * into the buffer and attempts to read <code>len</code> bytes. This method 169: * can return before reading the number of bytes requested. The actual number 170: * of bytes read is returned as an int. A -1 is returend to indicate the 171: * end of the stream. This will only happen when all of the subordinate 172: * streams have been read. 173: * <p> 174: * This method will block until at least one byte can be read. 175: * 176: * @param b The array into which bytes read should be stored 177: * @param off The offset into the array to start storing bytes 178: * @param len The requested number of bytes to read 179: * 180: * @return The actual number of bytes read, or -1 if end of stream 181: * 182: * @exception IOException If an error occurs 183: */ 184: public int read(byte[] b, int off, int len) throws IOException 185: { 186: int ch = -1; 187: 188: // The validity of the parameters will be checked by in.read so 189: // don't bother doing it here. 190: while (in != null && (ch = in.read(b, off, len)) < 0) 191: { 192: in.close(); 193: in = getNextStream(); 194: } 195: 196: return ch; 197: } 198: 199: /** 200: * This private method is used to get the next <code>InputStream</code> to 201: * read from. Returns null when no more streams are available. 202: */ 203: private InputStream getNextStream() 204: { 205: InputStream nextIn = null; 206: 207: if (e != null) 208: { 209: if (e.hasMoreElements()) 210: nextIn = (InputStream) e.nextElement(); 211: } 212: else 213: if (in2 != null) 214: { 215: nextIn = in2; 216: in2 = null; 217: } 218: 219: return nextIn; 220: } 221: }