package name.abuchen.portfolio.util;
import java.io.FilterInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InterruptedIOException;
import org.eclipse.core.runtime.IProgressMonitor;
/**
* Based on org.eclipse.team.internal.core.streams.ProgressMonitorInputStream
*/
public class ProgressMonitorInputStream extends FilterInputStream
{
private IProgressMonitor monitor;
private int updateIncrement;
private long bytesRead = 0;
private long lastUpdate = -1;
private long nextUpdate = 0;
public ProgressMonitorInputStream(InputStream in, int updateIncrement, IProgressMonitor monitor)
{
super(in);
this.updateIncrement = updateIncrement;
this.monitor = monitor;
}
/**
* Constructs a ProgressMonitorInputStream by using
* {@link java.io.InputStream#available()} to determine the total length of
* the stream.
*/
public ProgressMonitorInputStream(InputStream in, IProgressMonitor monitor) throws IOException
{
this(in, (int) Math.min(in.available() / 20L, Integer.MAX_VALUE), monitor);
}
public void close() throws IOException
{
try
{
in.close();
}
finally
{
monitor.done();
}
}
public int read() throws IOException
{
int b = in.read();
if (b != -1)
{
bytesRead += 1;
update();
}
return b;
}
public int read(byte[] buffer, int offset, int length) throws IOException
{
try
{
int count = in.read(buffer, offset, length);
if (count != -1)
{
bytesRead += count;
update();
}
return count;
}
catch (InterruptedIOException e)
{
bytesRead += e.bytesTransferred;
update();
throw e;
}
}
public long skip(long amount) throws IOException
{
try
{
long count = in.skip(amount);
bytesRead += count;
update();
return count;
}
catch (InterruptedIOException e)
{
bytesRead += e.bytesTransferred;
update();
throw e;
}
}
public boolean markSupported()
{
return false;
}
private void update()
{
if (bytesRead >= nextUpdate)
{
nextUpdate = bytesRead - (bytesRead % updateIncrement);
if (nextUpdate != lastUpdate)
monitor.worked(1);
lastUpdate = nextUpdate;
nextUpdate += updateIncrement;
}
}
}