package net.contrapunctus.rngzip.io;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.List;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPInputStream;
import net.contrapunctus.rngzip.util.BaliAutomaton;
import net.contrapunctus.rngzip.util.BitInputStream;
import net.contrapunctus.rngzip.util.ContextualInputStream;
import net.contrapunctus.rngzip.util.MultiplexInputStream;
import net.contrapunctus.rngzip.util.SchemaFormatException;
/**
* This implements a compressed XML input interface by reading the
* tree structure and data stream(s) from a single underlying input
* stream. The embedded streams may optionally be compressed using
* gzip; this is specified in a configuration stream of the input.
*
* <p class='license'>This is free software; you may modify and/or
* redistribute it under the terms of the GNU General Public License,
* but it comes with <b>absolutely no warranty.</b>
*
* @author Christopher League
*/
public final class RNGZInputStream implements RNGZInputInterface
{
private MultiplexInputStream mux;
private RNGZSettings settings;
private BitInputStream bits;
private ContextualInputStream data;
private URL schemaURL;
private long expectedSum;
private InputStream filter(int streamID, int kind) throws IOException
{
InputStream is = mux.open(streamID);
switch(kind) {
case 0x01:
is = new GZIPInputStream(is);
break;
}
return is;
}
/**
* Construct an input stream for compressed XML data, which reads
* from ‘in’. Additional configuration data is read from the
* stream itself.
* @throws IllegalArgumentException if ‘in’ is null.
* @throws RNGZFormatException if the data on ‘in’ does not
* appear to represent a valid input stream in the format expected
* by this class.
* @throws IOException if there is some other problem reading from
* ‘in’.
*/
public RNGZInputStream(InputStream in, RNGZSettings se)
throws IOException
{
mux = new MultiplexInputStream(in);
settings = se.fromStream(mux, 1);
bits = settings.newBitInput(mux, 0);
data = settings.newDataInput(mux, 2);
String s = data.readUTF(null);
if( s.length() > 0 ) {
schemaURL = new URL( s );
expectedSum = data.readLong(null);
}
}
public URL getSchemaURL()
{
return schemaURL;
}
public long getSchemaSum()
{
return expectedSum;
}
private final void check()
{
if(mux == null) {
throw new IllegalStateException("stream already closed");
}
}
public ChoiceDecoder makeChoiceDecoder(int limit, Object id)
{
return settings.makeChoiceCoder(limit, id);
}
/**
* @throws IllegalStateException if the stream is already closed.
*/
public int readChoice(ChoiceDecoder dec) throws IOException
{
check();
return dec.decode(bits);
}
/**
* @throws IllegalStateException if the stream is already closed.
*/
public String readContent(List<String> path) throws IOException
{
check();
//String elt = path.get(path.size()-1);
return data.readUTF(path);
}
/**
* Closes the multiplexed input stream, and all the embedded
* streams; the object becomes useless after this.
* @throws IllegalStateException if the stream is already closed.
*/
public void close() throws IOException
{
check();
mux.close();
mux = null;
bits = null;
data = null;
}
}