// DecoderThread.java -- run LZMA decoder in a separate thread
// Copyright (c)2007 Christopher League <league@contrapunctus.net>
// This is free software, but it comes with ABSOLUTELY NO WARRANTY.
// GNU Lesser General Public License 2.1 or Common Public License 1.0
package net.contrapunctus.lzma;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.util.concurrent.ArrayBlockingQueue;
import SevenZip.Compression.LZMA.Decoder;
class DecoderThread extends Thread
{
protected ArrayBlockingQueue<byte[]> q;
protected InputStream in;
protected OutputStream out;
protected Decoder dec;
protected IOException exn;
private static final PrintStream dbg = System.err;
private static final boolean DEBUG;
static
{
String ds = null;
try
{
ds = System.getProperty("DEBUG_LzmaCoders");
}
catch (final SecurityException e)
{
}
DEBUG = ds != null;
}
DecoderThread(InputStream _in)
{
q = ConcurrentBufferOutputStream.newQueue();
in = _in;
out = ConcurrentBufferOutputStream.create(q);
dec = new Decoder();
exn = null;
if (DEBUG)
{
dbg.printf("%s >> %s (%s)%n", this, out, q);
}
}
static final int propSize = 5;
static final byte[] props = new byte[propSize];
static
{
// enc.SetEndMarkerMode( true );
// enc.SetDictionarySize( 1 << 20 );
props[0] = 0x5d;
props[1] = 0x00;
props[2] = 0x00;
props[3] = 0x10;
props[4] = 0x00;
}
public void run()
{
try
{
long outSize = 0;
if (LzmaOutputStream.LZMA_HEADER)
{
final int n = in.read(props, 0, propSize);
if (n != propSize)
{
throw new IOException("input .lzma file is too short");
}
dec.SetDecoderProperties(props);
for (int i = 0; i < 8; i++)
{
final int v = in.read();
if (v < 0)
{
throw new IOException("Can't read stream size");
}
outSize |= (long) v << 8 * i;
}
}
else
{
outSize = -1;
dec.SetDecoderProperties(props);
}
if (DEBUG)
{
dbg.printf("%s begins%n", this);
}
dec.Code(in, out, outSize);
if (DEBUG)
{
dbg.printf("%s ends%n", this);
}
in.close(); // ?
}
catch (final IOException _exn)
{
exn = _exn;
if (DEBUG)
{
dbg.printf("%s exception: %s%n", this, exn.getMessage());
}
}
// close either way, so listener can unblock
try
{
out.close();
}
catch (final IOException _exn)
{
}
}
public void maybeThrow() throws IOException
{
if (exn != null)
{
throw exn;
}
}
public String toString()
{
return String.format("Dec@%x", hashCode());
}
}