package org.docear.plugin.core.io; import java.io.IOException; import java.io.InputStream; import java.io.InterruptedIOException; import java.net.URL; import java.net.URLConnection; import java.util.Collection; import org.docear.plugin.core.DocearController; import org.docear.plugin.core.features.DocearProgressObserver; public class ProgressInputStream extends InputStream { private final InputStream stream; private final URL url; private int length = 0; private int progress = 0; private boolean closed = false; public ProgressInputStream(URLConnection connection) throws IOException { this.length = connection.getContentLength(); this.stream = connection.getInputStream(); this.url = connection.getURL(); } public ProgressInputStream(InputStream stream, URL url) throws IOException { this.stream = stream; this.length = stream.available(); this.url = url; } public ProgressInputStream(InputStream stream, URL url, int length) { this.stream = stream; this.length = length; this.url = url; } @Override public int read() throws IOException { if(closed) { fireProgessFinished(); throw new InterruptedIOException(); } int read = this.stream.read(); this.progress++; if(read >= 0) { adjustProgress(); fireProgessUpdated(); } else { fireProgessFinished(); } return read; } private void fireProgessUpdated() { Collection<DocearProgressObserver> observers = DocearController.getController().getProgressObservers(this.getClass()); for(DocearProgressObserver observer : observers) { observer.update(this, this.progress, this.length, url.toString()); } } private void fireProgessFinished() { Collection<DocearProgressObserver> observers = DocearController.getController().getProgressObservers(this.getClass()); for(DocearProgressObserver observer : observers) { observer.finished(this, url.toString()); } } public int available() throws IOException { return this.stream.available(); } private void adjustProgress() throws IOException { int streamLength = this.progress+available(); if(this.length < streamLength) { this.length = streamLength+1; } } public void close() throws IOException { this.stream.close(); closed = true; } }