package au.edu.anu.dcclient.progress; import java.beans.PropertyChangeListener; import java.beans.PropertyChangeSupport; import java.io.FilterInputStream; import java.io.IOException; import java.io.InputStream; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class ProgressInputStream extends FilterInputStream { private static final Logger LOGGER = LoggerFactory.getLogger(ProgressInputStream.class); private final PropertyChangeSupport propertyChangeSupport; private final long totalBytes; private volatile long totalBytesRead; public ProgressInputStream(InputStream in, long totalBytes) { super(in); this.propertyChangeSupport = new PropertyChangeSupport(this); this.totalBytes = totalBytes; } public long getTotalBytes() { return totalBytes; } public long getTotalBytesRead() { return totalBytesRead; } public void addPropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.addPropertyChangeListener(l); } public void removePropertyChangeListener(PropertyChangeListener l) { propertyChangeSupport.removePropertyChangeListener(l); } @Override public int read() throws IOException { int b = super.read(); updateProgress(1); return b; } // Not overriding read(byte[]) as it calls read(byte[], int, int) @Override public int read(byte[] b, int off, int len) throws IOException { return (int) updateProgress(super.read(b, off, len)); } @Override public long skip(long n) throws IOException { return updateProgress(super.skip(n)); } @Override public void mark(int readlimit) { throw new UnsupportedOperationException(); } @Override public void reset() throws IOException { throw new UnsupportedOperationException(); } @Override public boolean markSupported() { return false; } private long updateProgress(long numBytesRead) { if (numBytesRead > 0) { long oldTotalNumBytesRead = this.totalBytesRead; this.totalBytesRead += numBytesRead; int oldPercentComplete = (int) (oldTotalNumBytesRead * 100L / totalBytes); int newPercentComplete = (int) (this.totalBytesRead * 100L / totalBytes); propertyChangeSupport.firePropertyChange("percentComplete", oldPercentComplete, newPercentComplete); } return numBytesRead; } }