[jsword-svn] r2039 - in trunk: bibledesktop/src/main/java/org/crosswire/bibledesktop/book/install bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop common-swing/src/main/java/org/crosswire/common/progress/swing common-swing/src/main/java/org/crosswire/common/swing jsword jsword/src/main/java/org/crosswire/common/progress jsword/src/main/java/org/crosswire/common/util jsword/src/main/java/org/crosswire/jsword/book/filter jsword/src/main/java/org/crosswire/jsword/book/install/sword jsword/src/main/java/org/crosswire/jsword/index/lucene jsword/src/test/java/org/crosswire/common/progress jsword-limbo/src/main/java/org/crosswire/bibledesktop/desktop jsword-limbo/src/main/java/org/crosswire/jsword/book/basic jsword-limbo/src/main/java/org/crosswire/jsword/book/search/ser

dmsmith at crosswire.org dmsmith at crosswire.org
Sat Dec 4 06:53:31 MST 2010


Author: dmsmith
Date: 2010-12-04 06:53:31 -0700 (Sat, 04 Dec 2010)
New Revision: 2039

Added:
   trunk/jsword/src/main/java/org/crosswire/common/progress/ProgressMode.java
Modified:
   trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/book/install/SitePane.java
   trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Desktop.java
   trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Splash.java
   trunk/common-swing/src/main/java/org/crosswire/common/progress/swing/JobsProgressBar.java
   trunk/common-swing/src/main/java/org/crosswire/common/swing/CWLabel.java
   trunk/jsword-limbo/src/main/java/org/crosswire/bibledesktop/desktop/DebugPane.java
   trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/basic/Verifier.java
   trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/search/ser/SerIndex.java
   trunk/jsword/JSwordDictionary.txt
   trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java
   trunk/jsword/src/main/java/org/crosswire/common/progress/JobManager.java
   trunk/jsword/src/main/java/org/crosswire/common/progress/Progress.java
   trunk/jsword/src/main/java/org/crosswire/common/util/WebResource.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/filter/FilterFactory.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java
   trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/HttpSwordInstaller.java
   trunk/jsword/src/main/java/org/crosswire/jsword/index/lucene/LuceneIndex.java
   trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java
   trunk/jsword/src/test/java/org/crosswire/common/progress/WorkEventTest.java
Log:
For JS-133:
Changed WebResource to take an optional progress meter.
Changed all the code to always pass a progress meter.
Re-wrote o.c.common.progress in a way that is not backward compatible.
Added ProgressMode so that a caller can know what kind of progress is being reported.

Modified: trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/book/install/SitePane.java
===================================================================
--- trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/book/install/SitePane.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/book/install/SitePane.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -441,7 +441,7 @@
                 // The pattern ###,###,###.# says to separate the number at every third digit and
                 //    to show one digit of fractional part.
                 // The , and . will automatically be converted into the user's proper separators.
-                formattedMsg = Msg.gettext("{0} is {1,number,###,###,###.#}MB. Continue?", new Object[] {name.getName(), new Float(size / 1024.0F)});
+                formattedMsg = Msg.gettext("{0} is {1,number,###,###,###.#}MB. Continue?", new Object[] {name.getName(), new Float(size)});
             } else {
                 // TRANSLATOR: The size of the book is provided so that the user can decide whether to continue a download.
                 // {0} is a placeholder for the name of the book.

Modified: trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Desktop.java
===================================================================
--- trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Desktop.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Desktop.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -157,9 +157,14 @@
         // The first thing that has to be done is to set the locale.
         Translations.instance().setLocale();
 
+        URI predictURI = PROJECT.getWritableURI(SPLASH_PROPS, FileUtil.EXTENSION_PROPERTIES);
+        Progress startJob = JobManager.createJob("Startup");
+        // TRANSLATOR: Progress label shown on BibleDesktop startup.
+        startJob.beginJob(Msg.gettext("Startup"), predictURI);
+        // startJob.setProgress(Msg.STARTUP_CONFIG.toString());
+
         // Load the configuration. And create the lists of installed books.
         // This has to be done before any GUI components are created
-        // (Including the splash).
         // This includes code that is invoked by it.
         // This has to be done after setting the locale.
         generateConfig();
@@ -170,12 +175,6 @@
         // Grab errors
         Reporter.grabAWTExecptions(true);
 
-        // Splash screen
-        URI predictURI = PROJECT.getWritableURI(SPLASH_PROPS, FileUtil.EXTENSION_PROPERTIES);
-        // TRANSLATOR: Progress label shown on BibleDesktop startup.
-        Progress startJob = JobManager.createJob(Msg.gettext("Startup"), predictURI, true);
-        // startJob.setProgress(Msg.STARTUP_CONFIG.toString());
-
         // Create the Desktop Actions
         actions = new DesktopActions(this);
 
@@ -1038,7 +1037,6 @@
                 System.setProperty("com.apple.mrj.application.live-resize", "true");
             }
 
-            // new BusStart();
             ExceptionPane.setHelpDeskListener(true);
             LookAndFeelUtil.initialize();
 

Modified: trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Splash.java
===================================================================
--- trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Splash.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/bibledesktop/src/main/java/org/crosswire/bibledesktop/desktop/Splash.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -42,7 +42,6 @@
 import javax.swing.SwingConstants;
 
 import org.crosswire.common.progress.JobManager;
-import org.crosswire.common.progress.Progress;
 import org.crosswire.common.progress.WorkEvent;
 import org.crosswire.common.progress.WorkListener;
 import org.crosswire.common.progress.swing.JobsProgressBar;
@@ -193,10 +192,10 @@
          * @see org.crosswire.common.progress.WorkListener#workProgressed(org.crosswire.common.progress.WorkEvent)
          */
         public void workProgressed(WorkEvent ev) {
-            Progress job = ev.getJob();
-            if (job.getWork() == 0 || job.isFinished()) {
+//            Progress job = ev.getJob();
+//            if (job.getWork() == 0 || job.isFinished()) {
                 Splash.this.pack();
-            }
+//            }
         }
 
         /* (non-Javadoc)

Modified: trunk/common-swing/src/main/java/org/crosswire/common/progress/swing/JobsProgressBar.java
===================================================================
--- trunk/common-swing/src/main/java/org/crosswire/common/progress/swing/JobsProgressBar.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/common-swing/src/main/java/org/crosswire/common/progress/swing/JobsProgressBar.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -44,6 +44,7 @@
 import org.crosswire.common.progress.Job;
 import org.crosswire.common.progress.JobManager;
 import org.crosswire.common.progress.Progress;
+import org.crosswire.common.progress.ProgressMode;
 import org.crosswire.common.progress.WorkEvent;
 import org.crosswire.common.progress.WorkListener;
 import org.crosswire.common.swing.ActionFactory;
@@ -146,6 +147,9 @@
         log.debug("adding job to panel at " + i + ": " + job.getJobName());
 
         JProgressBar progress = new JProgressBar();
+//        if (job.getProgressMode() == ProgressMode.UNKNOWN) {
+//            progress.setIndeterminate(true);
+//        }
         progress.setStringPainted(true);
         progress.setToolTipText(job.getJobName());
         progress.setBorder(null);
@@ -179,11 +183,15 @@
     protected synchronized void updateJob(Progress job) {
         JobData jobdata = (JobData) jobs.get(job);
 
-        int percent = job.getWork();
+        // At 99% the progress bar animates nicely.
+        int percent = 99;
         StringBuffer buf = new StringBuffer(job.getSectionName());
-        buf.append(": ");
-        buf.append(shaper.shape(Integer.toString(percent)));
-        buf.append('%');
+        if (job.getProgressMode() != ProgressMode.UNKNOWN) {
+            percent = job.getWork();
+            buf.append(": ");
+            buf.append(shaper.shape(Integer.toString(percent)));
+            buf.append('%');
+        }
         jobdata.getProgress().setString(buf.toString());
         jobdata.getProgress().setValue(percent);
     }

Modified: trunk/common-swing/src/main/java/org/crosswire/common/swing/CWLabel.java
===================================================================
--- trunk/common-swing/src/main/java/org/crosswire/common/swing/CWLabel.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/common-swing/src/main/java/org/crosswire/common/swing/CWLabel.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -49,7 +49,7 @@
      *            the text of the label, with an optional mnemonic indicator
      * @return a JLabel
      */
-    static public JLabel createJLabel(String text) {
+     public static JLabel createJLabel(String text) {
         String label = text;
 
         // A Mnemonic can be specified by a preceding _ in the name

Modified: trunk/jsword/JSwordDictionary.txt
===================================================================
--- trunk/jsword/JSwordDictionary.txt	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/JSwordDictionary.txt	2010-12-04 13:53:31 UTC (rev 2039)
@@ -155,3 +155,4 @@
 ditto
 trawl
 breakages
+indeterminant

Modified: trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/common/progress/Job.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -24,7 +24,6 @@
 import java.io.IOException;
 import java.net.URI;
 import java.util.ArrayList;
-import java.util.Date;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
@@ -42,6 +41,7 @@
  * @see gnu.lgpl.License for license details.<br>
  *      The copyright to this program is held by it's authors.
  * @author Joe Walker [joe at eireneh dot com]
+ * @author DM Smith [dmsmith555 at yahoo dot com]
  */
 public final class Job implements Progress {
     /**
@@ -50,175 +50,222 @@
      * 
      * @param description
      *            Short description of this job
-     * @param predictURI
-     *            Optional URI to save/load prediction times from
      * @param worker
      *            Optional thread to use in request to stop worker
-     * @param totalWork
-     *            the size of the work to do
      */
-    protected Job(String description, URI predictURI, Thread worker, int totalWork) {
-        this.predictURI = predictURI;
+    protected Job(String jobName, Thread worker) {
+        this.jobName = jobName;
         this.workerThread = worker;
         this.listeners = new ArrayList();
-        this.start = -1;
-        this.predictedLength = -1;
-        beginJob(description, totalWork);
+        this.cancelable = workerThread != null;
+        this.jobMode = ProgressMode.PREDICTIVE;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#beginJob(java.lang.String,
-     * int)
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#beginJob(java.lang.String)
      */
-    public void beginJob(String name, int workToDo) {
+    public void beginJob(String sectionName) {
+        beginJob(sectionName, 100);
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#beginJob(java.lang.String, long)
+     */
+    public void beginJob(String sectionName, long totalWork) {
         if (this.finished) {
             return;
         }
 
         synchronized (this) {
-            this.totalWork = workToDo;
-            this.sectionName = name;
-            this.jobName = name;
-            this.work = 0;
-            this.finished = false;
-            this.cancelable = workerThread != null;
+            finished = false;
+            currentSectionName = sectionName;
+            totalUnits = totalWork;
+            jobMode = totalUnits == 100 ? ProgressMode.PERCENT : ProgressMode.UNITS;
+        }
 
-            if (totalWork == UNKNOWN) {
-                updater = new Timer();
-                updater.schedule(new PredictTask(), 0, 100);
-            }
+        // Report that the Job has started.
+        JobManager.fireWorkProgressed(this);
+    }
 
-            // Set-up the timings files. It's not a disaster if it doesn't load
-            if (predictURI != null) {
-                loadPredictions();
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#beginJob(java.lang.String, java.net.URI)
+     */
+    public void beginJob(String sectionName, URI predictURI) {
+        if (finished) {
+            return;
+        }
+
+        synchronized (this) {
+            finished = false;
+            currentSectionName = sectionName;
+            predictionMapURI = predictURI;
+            jobMode = ProgressMode.PREDICTIVE;
+            startTime = System.currentTimeMillis();
+
+            fakingTimer = new Timer();
+            fakingTimer.schedule(new PredictTask(), 0, REPORTING_INTERVAL);
+
+            // Load currentPredictionMap. It's not a disaster if it doesn't load
+            totalUnits = loadPredictions();
+
+            // There were no prior predictions so punt.
+            if (totalUnits == Progress.UNKNOWN) {
+                // if we have nothing to go on use our assumption
+                totalUnits = EXTRA_TIME;
+                jobMode = ProgressMode.UNKNOWN;
             }
 
             // And the predictions for next time
-            current = new HashMap();
-            start = System.currentTimeMillis();
+            nextPredictionMap = new HashMap();
         }
+
+        // Report that the Job has started.
         JobManager.fireWorkProgressed(this);
     }
 
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#getJobName()
+     */
+    public synchronized String getJobName() {
+        return jobName;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#getProgressMode()
+     */
+    public synchronized ProgressMode getProgressMode() {
+        return jobMode;
+    }
+
+    /* (non-Javadoc)
      * @see org.crosswire.common.progress.Progress#getTotalWork()
      */
-    public synchronized int getTotalWork() {
-        return totalWork;
+    public synchronized long getTotalWork() {
+        return totalUnits;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see
-     * org.crosswire.common.progress.Progress#setSectionName(java.lang.String)
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#setTotalWork(long)
      */
-    public void setSectionName(String statedesc) {
-        if (this.finished) {
+    public synchronized void setTotalWork(long totalWork) {
+        this.totalUnits = totalWork;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#getWork()
+     */
+    public synchronized int getWork() {
+        return percent;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#setWork(long)
+     */
+    public synchronized void setWork(long work) {
+        setWorkDone(work);
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#getWorkDone()
+     */
+    public synchronized long getWorkDone() {
+        return workUnits;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#setWork(long)
+     */
+    public void setWorkDone(long work) {
+        if (finished) {
             return;
         }
 
-        boolean doUpdate = false;
         synchronized (this) {
-            this.sectionName = statedesc;
-
-            doUpdate = updater != null;
-            if (doUpdate) {
-                if (predictedLength != 0) {
-                    setWork(100 * getAgeFromMap(predicted, statedesc) / predictedLength);
-                } else {
-                    setWork(0);
-                }
+            if (workUnits == work) {
+                return;
             }
-            predictSection(statedesc);
 
-            current.put(statedesc, new Integer((int) (System.currentTimeMillis() - start)));
+            workUnits = work;
+            percent = (int) (100 * workUnits / totalUnits);
         }
 
-        if (doUpdate) {
-            JobManager.fireWorkProgressed(this);
-        }
+        JobManager.fireWorkProgressed(this);
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#setWork(int)
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#incrementWorkDone(long)
      */
-    public void setWork(int work) {
-        if (this.finished) {
+    public void incrementWorkDone(long step) {
+        setWorkDone(getWorkDone() + step);
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#getSectionName()
+     */
+    public synchronized String getSectionName() {
+        return currentSectionName;
+    }
+
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#setSectionName(java.lang.String)
+     */
+    public void setSectionName(String sectionName) {
+        if (finished) {
             return;
         }
 
         synchronized (this) {
-            if (this.work == work) {
-                return;
+            // If we are in some kind of predictive mode, then measure progress toward the expected end.
+            if (jobMode == ProgressMode.PREDICTIVE || jobMode == ProgressMode.UNKNOWN) {
+                updateProgress(System.currentTimeMillis());
+
+                // We are done with the current section and are starting another
+                // So record the length of the last section
+                if (nextPredictionMap != null) {
+                    nextPredictionMap.put(currentSectionName, Long.valueOf(workUnits));
+                }
             }
 
-            this.work = work;
-
-            predictSection(sectionName);
-
-            current.put(sectionName, new Integer((int) (System.currentTimeMillis() - start)));
+            currentSectionName = sectionName;
         }
 
+        // Tell listeners that the label changed.
         JobManager.fireWorkProgressed(this);
     }
 
-    /**
-     * We have moved onto another section so update the percentage complete and
-     * the section title.
-     */
-    public void setProgress(int work, String statedesc) {
-        setSectionName(statedesc);
-        setWork(work);
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
      * @see org.crosswire.common.progress.Progress#done()
      */
     public void done() {
         synchronized (this) {
             finished = true;
             // TRANSLATOR: This shows up in a progress bar when progress is finished.
-            sectionName = UserMsg.gettext("Done");
-            work = 100;
+            currentSectionName = UserMsg.gettext("Done");
 
-            if (updater != null) {
-                updater.cancel();
-                updater = null;
+            // Turn off the timer
+            if (fakingTimer != null) {
+                fakingTimer.cancel();
+                fakingTimer = null;
             }
 
-            current.put(sectionName, new Integer((int) (System.currentTimeMillis() - start)));
+            workUnits = totalUnits;
+            percent = 100;
+
+            if (nextPredictionMap != null) {
+                nextPredictionMap.put(currentSectionName, Long.valueOf(System.currentTimeMillis() - startTime));
+            }
         }
 
         JobManager.fireWorkProgressed(this);
 
         synchronized (this) {
-            if (predictURI != null) {
+            if (predictionMapURI != null) {
                 savePredictions();
             }
         }
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#getSectionName()
-     */
-    public synchronized String getSectionName() {
-        return sectionName;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
      * @see org.crosswire.common.progress.Progress#cancel()
      */
     public void cancel() {
@@ -231,21 +278,24 @@
         }
     }
 
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
+     * @see org.crosswire.common.progress.Progress#isFinished()
+     */
+    public boolean isFinished() {
+        return finished;
+    }
+
+    /* (non-Javadoc)
      * @see org.crosswire.common.progress.Progress#isCancelable()
      */
-    public boolean isCancelable() {
+    public synchronized boolean isCancelable() {
         return cancelable;
     }
 
-    /*
-     * (non-Javadoc)
-     * 
+    /* (non-Javadoc)
      * @see org.crosswire.common.progress.Progress#setCancelable(boolean)
      */
-    public void setCancelable(boolean newInterruptable) {
+    public synchronized void setCancelable(boolean newInterruptable) {
         if (workerThread == null || finished) {
             return;
         }
@@ -253,42 +303,7 @@
         fireStateChanged();
     }
 
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#isFinished()
-     */
-    public boolean isFinished() {
-        return finished;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#getWork()
-     */
-    public synchronized int getWork() {
-        return work;
-    }
-
-    /*
-     * (non-Javadoc)
-     * 
-     * @see org.crosswire.common.progress.Progress#getJobName()
-     */
-    public synchronized String getJobName() {
-        return jobName;
-    }
-
     /**
-     * Typically called from in a catch block, this ensures that we don't save
-     * the timing file because we have a messed up run.
-     */
-    private synchronized void ignoreTimings() {
-        predictURI = null;
-    }
-
-    /**
      * Add a listener to the list
      */
     public synchronized void addWorkListener(WorkListener li) {
@@ -328,7 +343,7 @@
 
         // We ought only to tell listeners about jobs that are in our
         // list of jobs so we need to fire before delete.
-        int count = temp.size();
+        long count = temp.size();
         for (int i = 0; i < count; i++) {
             ((WorkListener) temp.get(i)).workStateChanged(ev);
         }
@@ -337,14 +352,14 @@
     /**
      * Predict a percentage complete
      */
-    private synchronized int getAgeFromMap(Map props, String message) {
+    private synchronized long getAgeFromMap(Map props, String message) {
         if (props == null) {
             return 0;
         }
 
-        Integer time = (Integer) props.get(message);
+        Long time = (Long) props.get(message);
         if (time != null) {
-            return time.intValue();
+            return time.longValue();
         }
 
         return 0;
@@ -353,103 +368,42 @@
     /**
      * Get estimated the percent progress, extrapolating between sections
      */
-    protected synchronized void guessProgress() {
-        long now = System.currentTimeMillis();
+    protected synchronized void updateProgress(long now) {
+        workUnits = now - startTime;
 
-        if (now < sectionStart) {
-            log.warn("now before started: now=" + new Date(now) + " started=" + new Date(sectionStart));
-            return;
+        // Are we taking more time than expected?
+        // Then we are at 100%
+        if (workUnits > totalUnits) {
+            workUnits = totalUnits;
+            percent = 100;
+        } else {
+            percent = (int) (100 * workUnits / totalUnits);
         }
-
-        if (now == sectionStart) {
-            return;
-        }
-
-        if (now > sectionEnd) {
-            // the prediction went wrong and we are ahead of ourselves
-            work = percentEnd;
-            return;
-        }
-
-        // how long is this section
-        int sectlen = (int) (sectionEnd - sectionStart);
-        // what percent of the way through it are we?
-        int sectpc = (int) (100 * (now - sectionStart) / sectlen);
-        // so what do we need to add to the current percentage
-        int boost = sectpc * (percentEnd - work) / 100;
-        // so we guess at progress at:
-        int total = work + boost;
-        // but check this is not more than 100
-        total = total <= 100 ? total : 100;
-
-        work = total;
     }
 
     /**
-     * Predict a percentage complete
-     */
-    private synchronized void predictSection(String message) {
-        sectionStart = System.currentTimeMillis();
-
-        // if we have nothing to go on assume 10 sections of 10 sec each.
-        if (predicted == null || predictedLength == 0) {
-            sectionEnd = 10000;
-            percentEnd = 10;
-            return;
-        }
-
-        // from the predictions get this section starts and ends and the final
-        // finish
-        int predsectstart = getAgeFromMap(predicted, sectionName);
-        int predsectend = Integer.MAX_VALUE;
-
-        // find better values for predsectend and predallend
-        Iterator iter = predicted.keySet().iterator();
-        while (iter.hasNext()) {
-            String title = (String) iter.next();
-            int age = ((Integer) predicted.get(title)).intValue();
-
-            // if this is a later section (than the current) but early than the
-            // current earliest
-            if (age > predsectstart && age < predsectend) {
-                predsectend = age;
-            }
-        }
-        int predsecttime = predsectend - predsectstart;
-
-        sectionEnd = sectionStart + predsecttime;
-
-        // And what is the end percentage?
-        int pcstart = 100 * predsectstart / predictedLength;
-        int pcend = 100 * predsectend / predictedLength;
-        int pcdiff = pcend - pcstart;
-
-        percentEnd = work + pcdiff;
-
-        log.debug("Predicting " + predsecttime + "ms (" + work + '-' + percentEnd + "%) for section " + message);
-    }
-
-    /**
      * Load the predictive timings if any
      */
-    private synchronized void loadPredictions() {
+    private synchronized long loadPredictions() {
+        long maxAge = UNKNOWN;
         try {
-            predicted = new HashMap();
-            Properties temp = NetUtil.loadProperties(predictURI);
+            currentPredictionMap = new HashMap();
+            Properties temp = NetUtil.loadProperties(predictionMapURI);
 
+            // Determine the predicted time from the current prediction map
             Iterator iter = temp.keySet().iterator();
             while (iter.hasNext()) {
                 String title = (String) iter.next();
                 String timestr = temp.getProperty(title);
 
                 try {
-                    Integer time = new Integer(timestr);
-                    predicted.put(title, time);
+                    Long time = Long.valueOf(timestr);
+                    currentPredictionMap.put(title, time);
 
                     // if this time is later than the latest
-                    int age = time.intValue();
-                    if (age > predictedLength) {
-                        predictedLength = age;
+                    long age = time.longValue();
+                    if (maxAge < age) {
+                        maxAge = age;
                     }
                 } catch (NumberFormatException ex) {
                     log.error("Time format error", ex);
@@ -458,78 +412,78 @@
         } catch (IOException ex) {
             log.debug("Failed to load prediction times - guessing");
         }
+
+        return maxAge;
     }
 
     /**
      * Save the known timings to a properties file.
      */
     private synchronized void savePredictions() {
-        // We need to create a new prediction file. Work out the end point
-        long end = start;
-        Iterator iter = current.keySet().iterator();
-        while (iter.hasNext()) {
-            String message = (String) iter.next();
-            int age = getAgeFromMap(current, message);
-            if (age > end) {
-                end = age;
-            }
-        }
-        // long length = end - start;
-
         // Now we know the start and the end we can convert all times to
         // percents
         Properties predictions = new Properties();
-        iter = current.keySet().iterator();
+        Iterator iter = nextPredictionMap.keySet().iterator();
         while (iter.hasNext()) {
-            String message = (String) iter.next();
-            int age = getAgeFromMap(current, message);
-            predictions.setProperty(message, Integer.toString(age));
+            String sectionName = (String) iter.next();
+            long age = getAgeFromMap(nextPredictionMap, sectionName);
+            predictions.setProperty(sectionName, Long.toString(age));
         }
 
         // And save. It's not a disaster if this goes wrong
         try {
-            NetUtil.storeProperties(predictions, predictURI, "Predicted Startup Times");
+            NetUtil.storeProperties(predictions, predictionMapURI, "Predicted Startup Times");
         } catch (IOException ex) {
             log.error("Failed to save prediction times", ex);
         }
     }
 
     /**
-     * Total amount of work to do.
+     * Typically called from in a catch block, this ensures that we don't save
+     * the timing file because we have a messed up run.
      */
-    private int totalWork;
+    private synchronized void ignoreTimings() {
+        predictionMapURI = null;
+    }
 
+    private static final int REPORTING_INTERVAL = 100;
+
     /**
-     * Does this job allow interruptions?
+     * The amount of extra time if the predicted time was off and more time is needed.
      */
-    private boolean cancelable;
+    private static final int EXTRA_TIME = 2 * REPORTING_INTERVAL;
 
     /**
-     * Have we just finished?
+     * The type of job being performed. This is used to simplify code.
      */
-    private boolean finished;
+    private ProgressMode jobMode;
 
     /**
-     * The officially reported progress
+     * Total amount of work to do.
      */
-    private int work;
+    private long totalUnits;
 
     /**
-     * When do we expect this section to end
+     * Does this job allow interruptions?
      */
-    private long sectionEnd;
+    private boolean cancelable;
 
     /**
-     * When did this section start?
+     * Have we just finished?
      */
-    private long sectionStart;
+    private boolean finished;
 
     /**
-     * The percentage at the end of this section
+     * The amount of work done against the total.
      */
-    private int percentEnd;
+    private long workUnits;
 
     /**
+     * The officially reported progress
+     */
+    private int percent;
+
+    /**
      * A short descriptive phrase
      */
     private String jobName;
@@ -542,37 +496,32 @@
     /**
      * Description of what we are doing
      */
-    private String sectionName;
+    private String currentSectionName;
 
     /**
-     * When did this job start?
+     * The URI to which we load and save timings
      */
-    private long start;
+    private URI predictionMapURI;
 
     /**
-     * The timings as measured this time
-     */
-    private Map current;
-
-    /**
      * The timings loaded from where they were saved after the last run
      */
-    private Map predicted;
+    private Map currentPredictionMap;
 
     /**
-     * How long to we predict this job is going to last?
+     * The timings as measured this time
      */
-    private int predictedLength;
+    private Map nextPredictionMap;
 
     /**
-     * The URI to which we load and save timings
+     * When did this job start? Measured in milliseconds since beginning of epoch.
      */
-    private URI predictURI;
+    private long startTime;
 
     /**
-     * The timer that lets us post fake progress events
+     * The timer that lets us post fake progress events.
      */
-    private Timer updater;
+    private Timer fakingTimer;
 
     /**
      * People that want to know about "cancelable" changes
@@ -583,16 +532,12 @@
      * So we can fake progress for Jobs that don't tell us how they are doing
      */
     final class PredictTask extends TimerTask {
-        /*
-         * (non-Javadoc)
-         * 
-         * @see
-         * java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent
-         * )
+        /* (non-Javadoc)
+         * @see java.util.TimerTask#run()
          */
-        /* @Override */
+        @Override
         public void run() {
-            guessProgress();
+            updateProgress(System.currentTimeMillis());
             JobManager.fireWorkProgressed(Job.this);
         }
 

Modified: trunk/jsword/src/main/java/org/crosswire/common/progress/JobManager.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/progress/JobManager.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/common/progress/JobManager.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -21,7 +21,6 @@
  */
 package org.crosswire.common.progress;
 
-import java.net.URI;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -78,36 +77,27 @@
     }
 
     /**
-     * Create a new Job
+     * Create a new Job that cannot be canceled.
+     * 
+     * @param jobName the name of the Job
      */
-    public static Progress createJob(String description, URI predictURI, Thread work, boolean fakeupdates) {
-        Progress job = new Job(description, predictURI, work, fakeupdates ? Progress.UNKNOWN : 100);
-        jobs.add(job);
-
-        log.debug("job starting: " + job.getJobName());
-
-        return job;
+    public static Progress createJob(String jobName) {
+        return createJob(jobName, null);
     }
 
     /**
-     * Create a new Job
+     * Create a new Job that can be canceled.
+     * 
+     * @param jobName the name of the Job
+     * @param workerThread the thread on which this job runs
      */
-    public static Progress createJob(String description, Thread work, boolean fakeupdates) {
-        return createJob(description, null, work, fakeupdates);
-    }
+    public static Progress createJob(String jobName, Thread workerThread) {
+        Progress job = new Job(jobName, workerThread);
+        jobs.add(job);
 
-    /**
-     * Create a new Job
-     */
-    public static Progress createJob(String description, URI predictURI, boolean fakeupdates) {
-        return createJob(description, predictURI, null, fakeupdates);
-    }
+        log.debug("job starting: " + job.getJobName());
 
-    /**
-     * Create a new Job
-     */
-    public static Progress createJob(String description, boolean fakeupdates) {
-        return createJob(description, null, null, fakeupdates);
+        return job;
     }
 
     /**

Modified: trunk/jsword/src/main/java/org/crosswire/common/progress/Progress.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/progress/Progress.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/common/progress/Progress.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -21,6 +21,8 @@
  */
 package org.crosswire.common.progress;
 
+import java.net.URI;
+
 /**
  * A Generic way of keeping track of Threads and monitoring their progress.
  * 
@@ -32,61 +34,127 @@
     /**
      * Indicate that the total amount of work is unknown.
      */
-    int UNKNOWN = -1;
+    long UNKNOWN = -1;
 
     /**
-     * Start the task.
+     * Start the task measured from 0 to 100. It is the caller's responsibility to compute percentages.
      * 
-     * @param name
+     * @param sectionName
      *            the initial name of the job.
+     */
+    void beginJob(String sectionName);
+
+    /**
+     * Start the task reporting progress toward total work. Percentages will be
+     * computed on behalf of the caller.
+     * 
+     * @param sectionName
+     *            the initial name of the job.
      * @param totalWork
-     *            the total amount that is to be worked. If UNKNOWN then the
-     *            progress is to be guessed.
+     *            the total amount that is to be worked.
      */
-    void beginJob(String name, int totalWork);
+    void beginJob(String sectionName, long totalWork);
 
     /**
+     * Start the task using timings from a prior run as a guess for the current
+     * run. If there are no predictions then progress is faked.
+     * 
+     * @param sectionName
+     *            the initial name of the job.
+     * @param predictURI
+     *            the URI of a properties file from which past behavior is read
+     *            and the results of the current run are stored.
+     */
+    void beginJob(String sectionName, URI predictURI);
+
+    /**
      * @return the job name
      */
     String getJobName();
 
     /**
-     * @return the total amount of work to be done
+     * Gets the current ProgressMode. Builders of progress bars should use
+     * an indeterminant progress bar for ProgressMode.UNKNOWN and ProgressMode.PREDICTIVE.
+     * @return the current progress mode.
      */
-    int getTotalWork();
+    ProgressMode getProgressMode();
 
     /**
-     * Called to indicate that we are finished doing work.
+     * @return the total amount of work to be done, or UNKNOWN if it not known
      */
-    void done();
+    long getTotalWork();
 
     /**
-     * We have moved onto another section so update the section title.
+     * Set the total amount of work to be done. This can be called any time. It
+     * is the responsibility of the caller for it to be meaningful. It is
+     * ignored when the task is started with a prediction properties file.
      * 
-     * @param name
-     *            the name of the section
+     * @param totalWork
+     *            the total amount of work to be done in units that make sense
+     *            to the caller.
      */
-    void setSectionName(String name);
+    void setTotalWork(long totalWork);
 
     /**
-     * We have moved onto another section so update the section title.
+     * Return the computed percentage as an integer, typically from 0 to 100.
+     * 
+     * @return the amount of work done as a percentage
      */
-    String getSectionName();
+    int getWork();
 
     /**
-     * Indicate progress toward the whole.
+     * Indicate progress toward 100%. Note this is just a call to setWorkDone.
      * 
      * @param progress
      *            a part of the whole.
      */
-    void setWork(int progress);
+    void setWork(long progress);
 
     /**
-     * @return the amount of work done so far, possibly estimated
+     * @return the amount of work done so far as reported by the caller
      */
-    int getWork();
+    long getWorkDone();
 
     /**
+     * Indicate progress toward the whole. It is up to the caller to give a
+     * value that makes sense. When using 100 as a basis, it is typically a
+     * number from 0 to 100. In every case, it is a number from 0 to totalWork.
+     * 
+     * @param progress
+     *            a part of the whole.
+     */
+    void setWorkDone(long progress);
+
+    /**
+     * Indicate progress toward the whole. It is up to the caller to give a
+     * value that makes sense.
+     * 
+     * @param step
+     *            the amount of work done since the last call.
+     */
+    void incrementWorkDone(long step);
+
+    /**
+     * The section name is used in reporting progress.
+     * 
+     * @return the current section name
+     */
+    String getSectionName();
+
+    /**
+     * We have moved onto another section so update the section title. The section name is used in reporting progress.
+     * 
+     * @param name
+     *            the name of the section
+     */
+    void setSectionName(String name);
+
+    /**
+     * Called to indicate that we are finished doing work.
+     */
+    void done();
+
+    /**
      * Cancel the job (if possible). If isCancelable() is false, then the job
      * will be canceled if cancelable becomes true. There is no guarantee that
      * 

Added: trunk/jsword/src/main/java/org/crosswire/common/progress/ProgressMode.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/progress/ProgressMode.java	                        (rev 0)
+++ trunk/jsword/src/main/java/org/crosswire/common/progress/ProgressMode.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -0,0 +1,48 @@
+/**
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program is distributed in the hope
+ * that it will be useful, but WITHOUT ANY WARRANTY; without even the
+ * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+ * See the GNU Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2007
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: org.eclipse.jdt.ui.prefs 1178 2006-11-06 12:48:02Z dmsmith $
+ */
+package org.crosswire.common.progress;
+
+/**
+ * Progress can be  one of several modes, which correspond to the <code>Progress.beginJob()</code> calls.
+ *
+ * @see gnu.lgpl.License for license details.<br>
+ *      The copyright to this program is held by it's authors.
+ * @author DM Smith [dmsmith555 at yahoo dot com]
+ */
+public enum ProgressMode {
+    /**
+     * Progress is working toward 100% and is supplying work from 0 to 100.
+     */
+    PERCENT,
+    /**
+     * Progress is working toward a number of units. It might be 100.
+     */
+    UNITS,
+    /**
+     * Progress is predicted on the basis of prior runs. The caller has supplied a useful map of the sections for last run.
+     */
+    PREDICTIVE,
+    /**
+     * Progress is entirely indeterminate. The user has not supplied a useful map of the sections for last run.
+     */
+    UNKNOWN
+}

Modified: trunk/jsword/src/main/java/org/crosswire/common/util/WebResource.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/common/util/WebResource.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/common/util/WebResource.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -44,6 +44,7 @@
 import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
 import org.apache.http.params.HttpConnectionParams;
 import org.apache.http.params.HttpParams;
+import org.crosswire.common.progress.Progress;
 
 /**
  * A WebResource is backed by an URL and potentially the proxy through which it
@@ -202,13 +203,7 @@
             response = client.execute(method);
             StatusLine statusLine = response.getStatusLine();
             if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
-                Header header = response.getFirstHeader("Content-Length");
-                String value = header.getValue();
-                try {
-                    return Long.parseLong(value);
-                } catch (NumberFormatException ex) {
-                    return 0;
-                }
+                return getHeaderAsLong(response, "Content-Length");
             }
             String reason = response.getStatusLine().getReasonPhrase();
             // TRANSLATOR: Common error condition: {0} is a placeholder for the
@@ -230,7 +225,6 @@
      * 
      * @return the last mod date of the file
      */
-    @SuppressWarnings("deprecation")
     public long getLastModified() {
         HttpRequestBase method = new HttpHead(uri);
         HttpResponse response = null;
@@ -239,14 +233,7 @@
             response = client.execute(method);
             StatusLine statusLine = response.getStatusLine();
             if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
-                Header header = response.getFirstHeader("Last-Modified");
-                String value = header.getValue();
-                try {
-                    // This date cannot be readily parsed with DateFormatter
-                    return Date.parse(value);
-                } catch (Exception ex) {
-                    return 0;
-                }
+                return getHeaderAsDate(response, "Last-Modified");
             }
             String reason = response.getStatusLine().getReasonPhrase();
             // TRANSLATOR: Common error condition: {0} is a placeholder for the
@@ -261,12 +248,15 @@
     }
 
     /**
-     * Copy this WebResource to the destination.
+     * Copy this WebResource to the destination and report progress.
      * 
      * @param dest
+     *            the URI of the destination, typically a file:///.
+     * @param meter
+     *            the job on which to report progress
      * @throws LucidException
      */
-    public void copy(URI dest) throws LucidException {
+    public void copy(URI dest, Progress meter) throws LucidException  {
         InputStream in = null;
         OutputStream out = null;
 
@@ -276,6 +266,18 @@
         try {
             // Execute the method.
             response = client.execute(method);
+
+            // Initialize the meter, if present
+            if (meter != null) {
+                // Find out how big it is
+                long size = getHeaderAsLong(response, "Content-Length");
+                // Sometimes the Content-Length is not given and we have to grab it via HEAD method
+                if (size == 0) {
+                    size = getSize();
+                }
+                meter.setTotalWork(size);
+            }
+
             entity = response.getEntity();
             if (entity != null) {
                 in = entity.getContent();
@@ -286,6 +288,9 @@
                 byte[] buf = new byte[4096];
                 int count = in.read(buf);
                 while (-1 != count) {
+                    if (meter != null) {
+                        meter.incrementWorkDone(count);
+                    }
                     out.write(buf, 0, count);
                     count = in.read(buf);
                 }
@@ -311,6 +316,51 @@
     }
 
     /**
+     * Copy this WebResource to the destination.
+     * 
+     * @param dest
+     * @throws LucidException
+     */
+    public void copy(URI dest) throws LucidException {
+        copy(dest, null);
+    }
+
+    /**
+     * Get the field as a long.
+     * 
+     * @param response The response from the request
+     * @param field the header field to check
+     * @return the long value for the field
+     */
+    private long getHeaderAsLong(HttpResponse response, String field) {
+        Header header = response.getFirstHeader(field);
+        String value = header.getValue();
+        try {
+            return Long.parseLong(value);
+        } catch (NumberFormatException ex) {
+            return 0;
+        }
+    }
+
+    /**
+     * Get the number of seconds since start of epoch for the field in the response headers as a Date.
+     * 
+     * @param response The response from the request
+     * @param field the header field to check
+     * @return number of seconds since start of epoch
+     */
+    @SuppressWarnings("deprecation")
+    private long getHeaderAsDate(HttpResponse response, String field) {
+        Header header = response.getFirstHeader(field);
+        String value = header.getValue();
+        try {
+            // This date cannot be readily parsed with DateFormatter
+            return Date.parse(value);
+        } catch (IllegalArgumentException ex) {
+            return 0;
+        }
+    }
+    /**
      * Define a 750 ms timeout to get a connection
      */
     private static int timeout = 750;

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/filter/FilterFactory.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/filter/FilterFactory.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/filter/FilterFactory.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -102,7 +102,7 @@
      * not found then the default filter will be used.
      */
     public static Filter getFilter(String lookup) {
-        Filter reply = (Filter) filters.get(lookup.toLowerCase());
+        Filter reply = (Filter) filters.get(lookup.toLowerCase(Locale.ENGLISH));
 
         if (reply == null) {
             reply = deft;

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/AbstractSwordInstaller.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -36,7 +36,6 @@
 import org.crosswire.common.progress.Progress;
 import org.crosswire.common.util.CWProject;
 import org.crosswire.common.util.CollectionUtil;
-import org.crosswire.common.util.FileUtil;
 import org.crosswire.common.util.IOUtil;
 import org.crosswire.common.util.Logger;
 import org.crosswire.common.util.NetUtil;
@@ -240,9 +239,12 @@
              */
             /* @Override */
             public void run() {
-                URI predictURI = CWProject.instance().getWritableURI("sword-install", FileUtil.EXTENSION_PROPERTIES);
+                Progress job = JobManager.createJob("Install", this);
+
                 // TRANSLATOR: Progress label indicating the installation of a book. {0} is a placeholder for the name of the book.
-                Progress job = JobManager.createJob(UserMsg.gettext("Installing book: {0}", sbmd.getName()), predictURI, this, true);
+                String jobName = UserMsg.gettext("Installing book: {0}", sbmd.getName());
+                // Don't bother setting a size, we'll do it later.
+                job.beginJob(jobName);
 
                 yield();
 
@@ -302,8 +304,9 @@
      * @see org.crosswire.jsword.book.install.Installer#reloadIndex()
      */
     public void reloadBookList() throws InstallException {
+        Progress job = JobManager.createJob("BookList", Thread.currentThread());
         // TRANSLATOR: Progress label for downloading one or more files.
-        Progress job = JobManager.createJob(UserMsg.gettext("Downloading files"), Thread.currentThread(), false);
+        job.beginJob(UserMsg.gettext("Downloading files"));
 
         try {
             URI scratchfile = getCachedIndexFile();
@@ -325,8 +328,9 @@
      * .jsword.book.BookMetaData, java.net.URI)
      */
     public void downloadSearchIndex(Book book, URI localDest) throws InstallException {
+        Progress job = JobManager.createJob("SearchIndex", Thread.currentThread());
         // TRANSLATOR: Progress label for downloading one or more files.
-        Progress job = JobManager.createJob(UserMsg.gettext("Downloading files"), Thread.currentThread(), false);
+        job.beginJob(UserMsg.gettext("Downloading files"));
 
         try {
             download(job, packageDirectory + '/' + SEARCH_DIR, book.getInitials() + ZIP_SUFFIX, localDest);

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/HttpSwordInstaller.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/HttpSwordInstaller.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/book/install/sword/HttpSwordInstaller.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -111,7 +111,7 @@
         }
 
         WebResource wr = new WebResource(uri, proxyHost, proxyPort);
-        wr.copy(dest);
+        wr.copy(dest, job);
         wr.shutdown();
     }
 

Modified: trunk/jsword/src/main/java/org/crosswire/jsword/index/lucene/LuceneIndex.java
===================================================================
--- trunk/jsword/src/main/java/org/crosswire/jsword/index/lucene/LuceneIndex.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/main/java/org/crosswire/jsword/index/lucene/LuceneIndex.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -151,7 +151,8 @@
         DataPolice.setBook(book.getBookMetaData());
 
         // TRANSLATOR: Progress label indicating the start of indexing. {0} is a placeholder for the book's short name.
-        Progress job = JobManager.createJob(UserMsg.gettext("Creating index. Processing {0}", book.getInitials()), Thread.currentThread(), false);
+        Progress job = JobManager.createJob("CreateIndex", Thread.currentThread());
+        job.beginJob(UserMsg.gettext("Creating index. Processing {0}", book.getInitials()));
 
         IndexStatus finalStatus = IndexStatus.UNDONE;
 
@@ -463,9 +464,12 @@
                 }
 
                 subCount++;
+                int oldPercent = percent;
                 percent = 95 * subCount / size;
 
-                job.setWork(percent);
+                if (oldPercent != percent) {
+                    job.setWork(percent);
+                }
 
                 // This could take a long time ...
                 Thread.yield();

Modified: trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/test/java/org/crosswire/common/progress/JobTest.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -55,7 +55,9 @@
         File tempfile = File.createTempFile("jobtest", "tmp");
         URI uri = new URI(NetUtil.PROTOCOL_FILE, null, tempfile.getAbsolutePath(), null);
 
-        job = JobManager.createJob(WIBBLE, false);
+        job = JobManager.createJob(WIBBLE);
+        job.beginJob(WIBBLE);
+
         assertEquals(job.getJobName(), WIBBLE);
         assertEquals(job.isFinished(), false);
         assertEquals(job.isCancelable(), false);
@@ -66,7 +68,8 @@
         assertEquals(job.getWork(), 100);
         assertEquals(job.isCancelable(), false);
 
-        job = JobManager.createJob(WIBBLE, Thread.currentThread(), false);
+        job = JobManager.createJob(WIBBLE, Thread.currentThread());
+        job.beginJob(WIBBLE);
         assertEquals(job.getJobName(), WIBBLE);
         assertEquals(job.isFinished(), false);
         assertEquals(job.isCancelable(), true);
@@ -77,7 +80,8 @@
         assertEquals(job.getWork(), 100);
         // assertEquals(job.isCancelable(), false);
 
-        job = JobManager.createJob(WIBBLE, uri, false);
+        job = JobManager.createJob(WIBBLE);
+        job.beginJob(WIBBLE, uri);
         assertEquals(job.getJobName(), WIBBLE);
         assertEquals(job.isFinished(), false);
         assertEquals(job.isCancelable(), false);
@@ -88,7 +92,8 @@
         assertEquals(job.getWork(), 100);
         // assertEquals(job.isCancelable(), false);
 
-        job = JobManager.createJob(WIBBLE, uri, Thread.currentThread(), false);
+        job = JobManager.createJob(WIBBLE, Thread.currentThread());
+        job.beginJob(WIBBLE, uri);
         assertEquals(job.getJobName(), WIBBLE);
         assertEquals(job.isFinished(), false);
         assertEquals(job.isCancelable(), true);

Modified: trunk/jsword/src/test/java/org/crosswire/common/progress/WorkEventTest.java
===================================================================
--- trunk/jsword/src/test/java/org/crosswire/common/progress/WorkEventTest.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword/src/test/java/org/crosswire/common/progress/WorkEventTest.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -41,7 +41,8 @@
     }
 
     public void testGetJob() {
-        Progress job = JobManager.createJob("wibble", false);
+        Progress job = JobManager.createJob("wibble");
+        job.beginJob("wibble");
         WorkEvent ev = new WorkEvent(job);
 
         assertEquals(ev.getJob(), job);

Modified: trunk/jsword-limbo/src/main/java/org/crosswire/bibledesktop/desktop/DebugPane.java
===================================================================
--- trunk/jsword-limbo/src/main/java/org/crosswire/bibledesktop/desktop/DebugPane.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword-limbo/src/main/java/org/crosswire/bibledesktop/desktop/DebugPane.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -153,15 +153,15 @@
      * Create some test jobs
      */
     public void createTestJobs() {
-        createTestJob(30000, "test1", 20, false);
-        createTestJob(30000, "test2", 3, false);
-        createTestJob(30000, "test3", 3, true);
+        createTestJob(30000, "test1", 20);
+        createTestJob(30000, "test2", 3);
+        createTestJob(30000, "test3", 3);
     }
 
     /**
      * Create a test job
      */
-    public static void createTestJob(final long millis, final String predictbase, final int steps, final boolean fake) {
+    public static void createTestJob(final long millis, final String predictbase, final int steps) {
         final URI predicturl = CWProject.instance().getWritableURI(predictbase, FileUtil.EXTENSION_PROPERTIES);
         final Thread test = new Thread() {
             /*
@@ -171,7 +171,8 @@
              */
             /* @Override */
             public synchronized void run() {
-                Progress job = JobManager.createJob(predictbase, predicturl, Thread.currentThread(), fake);
+                Progress job = JobManager.createJob(predictbase, Thread.currentThread());
+                job.beginJob(predictbase, predicturl);
 
                 job.setSectionName(LimboMsg.DEBUG_STEPS.toString(new Object[] {
                         new Integer(0), new Integer(steps)

Modified: trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/basic/Verifier.java
===================================================================
--- trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/basic/Verifier.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/basic/Verifier.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -99,7 +99,8 @@
      * Read from the given source version to generate ourselves
      */
     public void checkText(Key key, PrintWriter out) {
-        Progress job = JobManager.createJob(VerifierMsg.VERIFY_START.toString(), Thread.currentThread(), false);
+        Progress job = JobManager.createJob(VerifierMsg.VERIFY_START.toString(), Thread.currentThread());
+        job.beginJob(VerifierMsg.VERIFY_START.toString());
 
         if (key == null) {
             key = book1.getGlobalKeyList();
@@ -153,7 +154,8 @@
      * Read from the given source version to generate ourselves
      */
     public void checkPassage(PrintWriter out) throws BookException {
-        Progress job = JobManager.createJob(VerifierMsg.VERIFY_PASSAGES.toString(), Thread.currentThread(), false);
+        Progress job = JobManager.createJob(VerifierMsg.VERIFY_PASSAGES.toString(), Thread.currentThread());
+        job.beginJob(VerifierMsg.VERIFY_PASSAGES.toString());
         int count = 0;
         int percent = -1;
 

Modified: trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/search/ser/SerIndex.java
===================================================================
--- trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/search/ser/SerIndex.java	2010-12-02 11:47:38 UTC (rev 2038)
+++ trunk/jsword-limbo/src/main/java/org/crosswire/jsword/book/search/ser/SerIndex.java	2010-12-04 13:53:31 UTC (rev 2039)
@@ -90,7 +90,8 @@
         this.book = book;
         this.uri = storage;
 
-        Progress job = JobManager.createJob(Msg.INDEX_START.toString(), Thread.currentThread(), false);
+        Progress job = JobManager.createJob(Msg.INDEX_START.toString(), Thread.currentThread());
+        job.beginJob(Msg.INDEX_START.toString());
 
         try {
             synchronized (creating) {




More information about the jsword-svn mailing list