/* * $Id$ * * Copyright (c) 2008-2010 by Joel Uckelman * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License (LGPL) as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, copies are available * at http://www.opensource.org. */ package VASSAL.tools.io; import java.io.IOException; import java.io.InputStream; import java.io.SequenceInputStream; import java.util.Arrays; import java.util.LinkedList; import java.util.List; /** * An {@link InputStream} which concatenates other <code>InputStreams</code>. * As with {@link SequenceInputStream}, the first stream is read until EOF, * followed by the second, and so on, until all input streams are exhausted. * * Note: {@link SequenceInputStream#available()} returns only the number of * bytes available from the current stream in the sequence, which makes it * difficult to efficiently allocate a buffer into which to read the bytes. * * @author Joel Uckelman * @since 3.1.0 * @see SequenceInputStream */ public class CompositeInputStream extends InputStream { protected final LinkedList<InputStream> queue; protected InputStream in; /** * Creates a <code>CompositeInputStream</code> from the given sequence * of <code>InputStream</code>s. * * @param streams the <code>InputStream</code>s to be concatenated */ public CompositeInputStream(List<InputStream> streams) { queue = new LinkedList<InputStream>(streams); in = queue.poll(); } /** * Creates a <code>CompositeInputStream</code> from the given sequence * of <code>InputStream</code>s. * * @param streams the <code>InputStream</code>s to be concatenated */ public CompositeInputStream(InputStream... streams) { this(Arrays.asList(streams)); } protected void nextStream() throws IOException { if (in != null) { in.close(); in = queue.poll(); } } /** {@inheritDoc} */ @Override public int available() throws IOException { int bytes = in != null ? in.available() : 0; for (InputStream ch : queue) { bytes += Math.max(ch.available(), 0); } return bytes; } /** {@inheritDoc} */ @Override public int read() throws IOException { if (in == null) return -1; final int c = in.read(); if (c != -1) return c; nextStream(); return read(); } /** {@inheritDoc} */ @Override public int read(byte b[], int off, int len) throws IOException { if (in == null) return -1; if (len == 0) return 0; final int count = in.read(b, off, len); if (count > 0) return count; nextStream(); return read(b, off, len); } /** {@inheritDoc} */ @Override public void close() throws IOException { while (in != null) nextStream(); } }