/*
Copyright (c) 1996-2010 Ariba, Inc.
All rights reserved. Patents pending.
$Id: //ariba/platform/util/core/ariba/util/io/CombinedInputStream.java#1 $
Responsible: dfinlay
*/
package ariba.util.io;
import java.io.InputStream;
import java.io.IOException;
import java.util.List;
/**
Is the input stream contained by stream a collection of streams one after
another moving to the next one when one is exhausted. <p/>
@aribaapi ariba
*/
public class CombinedInputStream extends InputStream
{
//--------------------------------------------------------------------------
// data members
private InputStream[] _streams;
private InputStream _current;
private int _idx;
//--------------------------------------------------------------------------
// constructors
/**
Constructs a new instance.
@aribaapi ariba
*/
public CombinedInputStream (InputStream[] streams)
{
_streams = streams;
_idx = -1;
_current = null;
advance();
}
/**
Constructs a new instance.
@aribaapi ariba
*/
public CombinedInputStream (List<InputStream> streams)
{
this(streams.toArray(new InputStream[streams.size()]));
}
private InputStream advance ()
{
if (_idx < _streams.length) {
++_idx;
_current = (_idx < _streams.length) ? _streams[_idx] : null;
}
return _current;
}
/**
As specified in superclass.
@aribaapi ariba
*/
public int read () throws IOException
{
if (_current == null) {
return -1;
}
int result;
do {
result = _current.read();
if (result != -1) {
return result;
}
} while (advance() != null);
return result;
}
/**
As specified in superclass.
@aribaapi ariba
*/
public int read (byte[] bytes, int offset, int length) throws IOException
{
if (_current == null) {
return -1;
}
int off = offset;
int len = length;
int result = 0;
while (len > 0) {
int read = _current.read(bytes, off, len);
if (read >= 0) {
result += read;
off += read;
len -= read;
}
else {
if (advance() == null) {
break;
}
}
}
return result;
}
/**
As specified in superclass.
@aribaapi ariba
*/
public int available () throws IOException
{
return _current != null ? _current.available() : 0;
}
/**
Closes all the streams in this (even if an exception occurs.) <p/>
@aribaapi ariba
*/
public void close () throws IOException
{
IOException exception = null;
for (InputStream stream : _streams) {
try {
stream.close();
}
catch (IOException ex) {
if (exception == null) {
exception = ex;
}
}
}
_current = null;
_idx = _streams.length;
if (exception != null) {
throw exception;
}
}
}