From 09d0bfa4b6d50ca54a6106dabc4f28134fa7ded3 Mon Sep 17 00:00:00 2001 From: Matthew Blair Date: Sat, 8 Mar 2014 11:26:10 -0500 Subject: [PATCH] Implement search download progress reporting --- project.clj | 1 + .../ConsoleReportingInputStream.java | 90 +++++++++++++++++++ src/leiningen/search.clj | 14 +-- 3 files changed, 100 insertions(+), 5 deletions(-) create mode 100644 src/java/leiningen/ConsoleReportingInputStream.java diff --git a/project.clj b/project.clj index 40a8c4c7..9fe8b7fd 100644 --- a/project.clj +++ b/project.clj @@ -34,6 +34,7 @@ :offline (comp (partial not-any? identity) (juxt :online :disabled))} :source-paths ["leiningen-core/src" "src"] + :java-source-paths ["src/java"] ;; work around Clojure bug http://dev.clojure.org/jira/browse/CLJ-1034 :uberjar-exclusions [#"^data_readers.clj$"] :eval-in :leiningen) diff --git a/src/java/leiningen/ConsoleReportingInputStream.java b/src/java/leiningen/ConsoleReportingInputStream.java new file mode 100644 index 00000000..046735ff --- /dev/null +++ b/src/java/leiningen/ConsoleReportingInputStream.java @@ -0,0 +1,90 @@ +package leiningen; + +import java.io.InputStream; +import java.io.IOException; + +/** + * Extends java.io.InputStream by reporting to console output + * the percentage of the stream that has been consumed after each + * read. Employs a Decorator pattern so that the capabilities of + * the original InputStream subclass are preserved. + */ + +public class ConsoleReportingInputStream extends InputStream +{ + + private final long contentLength; + private final InputStream stream; + private long totalBytesRead=0; + + /** + * @param stream - the InputStream to be wrapped by this object + * @param contentLength - the size, in bytes, of the content + * referred to by the stream parameter + */ + public ConsoleReportingInputStream(InputStream stream, long contentLength) + throws IOException + { + if(stream == null) { + throw new IOException("InputStream cannot be null"); + } + + if(contentLength <= 0) { + throw new IOException("InputStream content-length must be greater than zero"); + } + + this.stream = stream; + this.contentLength = contentLength; + } + + + private void updateAndReportProgress(int bytesRead) { + + totalBytesRead += bytesRead; + double progress = (totalBytesRead * 100.0)/contentLength; + // if progress < 100.0, then end output with carriage return + // otherwise, end output with newline. This ensures that + // progress will update on the same line until 100% reached + char lineTerm = '\r'; + if(progress == 100.0) { lineTerm = '\n'; } + + // Show one digit to the right of the decimal + System.out.printf("%.1f", progress); + System.out.print("% complete" + lineTerm); + } + + + @Override + public int read() throws IOException + { + byte[] buf = new byte[1]; + int cnt = stream.read(buf); + + if(cnt == -1) { return cnt; } + else { + updateAndReportProgress(cnt); + return buf[0]; + } + + } + + @Override + public int read(byte[] b) throws IOException + { + int cnt = stream.read(b); + if(cnt >= 0) { + updateAndReportProgress(cnt); + } + return cnt; + } + + @Override + public int read(byte[] b, int off, int len) throws IOException + { + int cnt = stream.read(b, off, len); + if(cnt >= 0) { + updateAndReportProgress(cnt); + } + return cnt; + } +} diff --git a/src/leiningen/search.clj b/src/leiningen/search.clj index dbacd87d..09f755b2 100644 --- a/src/leiningen/search.clj +++ b/src/leiningen/search.clj @@ -14,7 +14,8 @@ (org.apache.maven.index.expr UserInputSearchExpression) (org.apache.maven.index.updater IndexUpdater IndexUpdateRequest ResourceFetcher) - (org.codehaus.plexus DefaultPlexusContainer PlexusContainer))) + (org.codehaus.plexus DefaultPlexusContainer PlexusContainer) + (leiningen ConsoleReportingInputStream))) (defonce container (DefaultPlexusContainer.)) @@ -34,7 +35,7 @@ (defn- remove-context [context] (.removeIndexingContext indexer context false)) -;; TODO: add progress reporting back in + (defn- http-resource-fetcher [] (let [base-url (promise) stream (promise)] @@ -45,9 +46,12 @@ (disconnect [] (.close @stream)) (^java.io.InputStream retrieve [name] - (main/debug "Downloading" (str @base-url "/" name)) - (let [s (:body (http/get (str @base-url "/" name) - {:throw-exceptions false :as :stream}))] + (println "Downloading" (str @base-url "/" name)) + (let [r (http/get (str @base-url "/" name) + {:throw-exceptions false :as :stream}) + s (ConsoleReportingInputStream. + (:body r) + (Long/parseLong (get (:headers r) "content-length")))] (deliver stream s) s)))))