diff --git a/src/java/com/threerings/getdown/data/Application.java b/src/java/com/threerings/getdown/data/Application.java
index 323f7ac..7bd3c44 100644
--- a/src/java/com/threerings/getdown/data/Application.java
+++ b/src/java/com/threerings/getdown/data/Application.java
@@ -1027,23 +1027,35 @@ public class Application
protected void downloadConfigFile ()
throws IOException
{
- checkForAnotherGetdown();
+ requireNoOtherGetdownRunning();
downloadControlFile(CONFIG_FILE, false);
updateConfigModtime();
}
/**
- * Checks the modtime on CONFIG_FILE and if it's changed since the last time this was called,
- * raise a MultipleGetdownRunning exception
+ * Checks the modtime on CONFIG_FILE and returns whether it has changed since the last time
+ * this method was called.
*/
- public void checkForAnotherGetdown ()
- throws MultipleGetdownRunning
+ public boolean checkForAnotherGetdown ()
{
File config = getLocalPath(CONFIG_FILE);
if (_lastConfigModtime != -1 && _lastConfigModtime < config.lastModified()) {
- throw new MultipleGetdownRunning();
+ return true;
}
_lastConfigModtime = config.lastModified();
+ return false;
+ }
+
+ /**
+ * Calls {@link #checkForAnotherGetdown} and throws a {@link MultipleGetdownRunning} if it
+ * detects that another Getdown instance is running.
+ */
+ public void requireNoOtherGetdownRunning ()
+ throws MultipleGetdownRunning
+ {
+ if (checkForAnotherGetdown()) {
+ throw new MultipleGetdownRunning();
+ }
}
/**
@@ -1054,8 +1066,9 @@ public class Application
{
File config = getLocalPath(CONFIG_FILE);
_lastConfigModtime = System.currentTimeMillis();
- if(!config.setLastModified(_lastConfigModtime) && !_warnedAboutSetLastModified){
- Log.warning("Unable to set modtime on config file, will be unable to check for other instances of getdown running");
+ if (!config.setLastModified(_lastConfigModtime) && !_warnedAboutSetLastModified) {
+ Log.warning("Unable to set modtime on config file, will be unable to check for " +
+ "other instances of getdown running.");
_warnedAboutSetLastModified = true;
}
}
@@ -1152,7 +1165,7 @@ public class Application
// Check that another getdown hasn't started running since we started downloading this
// file. The rename will obliterate the modtime we're tracking to keep multiple instances
// from running.
- checkForAnotherGetdown();
+ requireNoOtherGetdownRunning();
// now move the temporary file over the original
File original = getLocalPath(path);
diff --git a/src/java/com/threerings/getdown/launcher/Getdown.java b/src/java/com/threerings/getdown/launcher/Getdown.java
index 60058ea..2b5e58c 100644
--- a/src/java/com/threerings/getdown/launcher/Getdown.java
+++ b/src/java/com/threerings/getdown/launcher/Getdown.java
@@ -62,6 +62,9 @@ import com.samskivert.util.StringUtil;
import com.threerings.getdown.Log;
import com.threerings.getdown.data.Application;
import com.threerings.getdown.data.Resource;
+import com.threerings.getdown.net.Downloader;
+import com.threerings.getdown.net.HTTPDownloader;
+import com.threerings.getdown.net.TorrentDownloader;
import com.threerings.getdown.tools.Patcher;
import com.threerings.getdown.util.ConfigUtil;
import com.threerings.getdown.util.LaunchUtil;
@@ -359,9 +362,9 @@ public abstract class Getdown extends Thread
// now force our UI to be recreated with the updated info
createInterface(true);
}
- _app.checkForAnotherGetdown();
+ _app.requireNoOtherGetdownRunning();
// Update the modtime here to stake a claim that we're going to getdown eventually
- _app.updateConfigModtime();
+ _app.updateConfigModtime();
if (_delay > 0) {
try {
Log.info("Waiting " + _delay + " minutes before beginning actual work");
@@ -413,7 +416,7 @@ public abstract class Getdown extends Thread
// Only launch if we aren't in silent mode. Some mystery program starting out
// of the blue would be disconcerting.
if (!_silent || _launchInSilent) {
- _app.checkForAnotherGetdown();
+ _app.requireNoOtherGetdownRunning();
launch();
}
return;
@@ -628,34 +631,29 @@ public abstract class Getdown extends Thread
updateStatus("m.resolving");
}
- public void downloadProgress (int percent, long remaining)
- throws IOException {
- // Check for another getdown running at 0 and every 10% after that
+ public boolean downloadProgress (int percent, long remaining) {
+ // check for another getdown running at 0 and every 10% after that
if (_lastCheck == -1 || percent >= _lastCheck + 10) {
- _app.checkForAnotherGetdown();
+ if (_app.checkForAnotherGetdown()) {
+ return false;
+ }
_lastCheck = percent;
}
setStatus("m.downloading", percent, remaining, true);
if (percent > 0) {
reportTrackingEvent("progress", percent);
}
+ return true;
}
- public void downloadFailed (Resource rsrc, Exception e)
- throws IOException {
- if (e instanceof MultipleGetdownRunning) {
- throw (IOException)e;
- } else {
- updateStatus(MessageUtil.tcompose("m.failure", e.getMessage()));
- Log.warning("Download failed [rsrc=" + rsrc + "].");
- Log.logStackTrace(e);
- }
+ public void downloadFailed (Resource rsrc, Exception e) {
+ updateStatus(MessageUtil.tcompose("m.failure", e.getMessage()));
+ Log.warning("Download failed [rsrc=" + rsrc + "].");
+ Log.logStackTrace(e);
}
-
- /**
- * The last percentage at which we checked for another getdown running, or -1 for not
- * having checked at all.
- */
+
+ /** The last percentage at which we checked for another getdown running, or -1 for not
+ * having checked at all. */
protected int _lastCheck = -1;
};
@@ -680,7 +678,9 @@ public abstract class Getdown extends Thread
}
// start the download and wait for it to complete
- dl.download();
+ if (!dl.download()) {
+ throw new MultipleGetdownRunning();
+ }
}
/**
diff --git a/src/java/com/threerings/getdown/net/DownloadAbortedException.java b/src/java/com/threerings/getdown/net/DownloadAbortedException.java
new file mode 100644
index 0000000..0764f2d
--- /dev/null
+++ b/src/java/com/threerings/getdown/net/DownloadAbortedException.java
@@ -0,0 +1,30 @@
+//
+// $Id$
+//
+// Getdown - application installer, patcher and launcher
+// Copyright (C) 2004-2006 Three Rings Design, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// 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 General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the: Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+package com.threerings.getdown.net;
+
+import java.io.IOException;
+
+/**
+ * Used to terminate the download process in its midst.
+ */
+public class DownloadAbortedException extends IOException
+{
+}
diff --git a/src/java/com/threerings/getdown/launcher/Downloader.java b/src/java/com/threerings/getdown/net/Downloader.java
similarity index 68%
rename from src/java/com/threerings/getdown/launcher/Downloader.java
rename to src/java/com/threerings/getdown/net/Downloader.java
index 2c084a7..300e021 100644
--- a/src/java/com/threerings/getdown/launcher/Downloader.java
+++ b/src/java/com/threerings/getdown/net/Downloader.java
@@ -18,69 +18,63 @@
// this program; if not, write to the: Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
-package com.threerings.getdown.launcher;
+package com.threerings.getdown.net;
import java.io.File;
import java.io.IOException;
+
import java.util.List;
import com.threerings.getdown.Log;
import com.threerings.getdown.data.Resource;
/**
- * Handles the download of a collection of files, first issuing HTTP head
- * requests to obtain size information and then downloading the files
- * individually, reporting progress back via a callback interface.
+ * Handles the download of a collection of files, first issuing HTTP head requests to obtain size
+ * information and then downloading the files individually, reporting progress back via a callback
+ * interface.
*/
public abstract class Downloader extends Thread
{
/**
- * An interface used to communicate status back to an external entity.
- * Note: these methods are all called on the download thread,
- * so implementors must take care to only execute thread-safe code or
- * simply pass a message to the AWT thread, for example.
+ * An interface used to communicate status back to an external entity. Note: these
+ * methods are all called on the download thread, so implementors must take care to only
+ * execute thread-safe code or simply pass a message to the AWT thread, for example.
*/
public interface Observer
{
/**
- * Called before the downloader begins the series of HTTP head
- * requests to determine the size of the files it needs to
- * download.
+ * Called before the downloader begins the series of HTTP head requests to determine the
+ * size of the files it needs to download.
*/
public void resolvingDownloads ();
/**
- * Called to inform the observer of ongoing progress toward
- * completion of the overall downloading task. The caller is
- * guaranteed to get at least one call reporting 100% completion.
+ * Called to inform the observer of ongoing progress toward completion of the overall
+ * downloading task. The caller is guaranteed to get at least one call reporting 100%
+ * completion.
*
- * @param percent the percent completion, in terms of total file
- * size, of the downloads.
- * @param remaining the estimated download time remaining in
- * seconds, or -1 if the time can not yet be
- * determined.
- * @throws IOException if getdown shouldn't continue in its current state.
+ * @param percent the percent completion, in terms of total file size, of the downloads.
+ * @param remaining the estimated download time remaining in seconds, or -1 if
+ * the time can not yet be determined.
+ *
+ * @return true if the download should continue, false if it should be aborted.
*/
- public void downloadProgress (int percent, long remaining) throws IOException;
+ public boolean downloadProgress (int percent, long remaining);
/**
- * Called if a failure occurs while checking for an update or
- * downloading a file.
+ * Called if a failure occurs while checking for an update or downloading a file.
*
- * @param rsrc the resource that was being downloaded when the
- * error occurred, or null if the failure occurred
- * while resolving downloads.
+ * @param rsrc the resource that was being downloaded when the error occurred, or
+ * null if the failure occurred while resolving downloads.
* @param e the exception detailing the failure.
- * @throws IOException if getdown shouldn't continue after this failure.
*/
- public void downloadFailed (Resource rsrc, Exception e) throws IOException;
+ public void downloadFailed (Resource rsrc, Exception e);
}
/**
- * Creates a downloader that will download the supplied list of
- * resources and communicate with the specified observer. The {@link
- * #download} method must be called on the downloader to initiate the
- * download process.
+ * Creates a downloader that will download the supplied list of resources and communicate with
+ * the specified observer. The {@link #download} method must be called on the downloader to
+ * initiate the download process.
*/
public Downloader (List resources, Observer obs)
{
@@ -95,20 +89,16 @@ public abstract class Downloader extends Thread
@Override
public void run ()
{
- try {
- download();
- } catch (IOException e) {
- // This was either logged or reported to our observer in download, so we're good.
- }
+ download();
}
/**
- * Start downloading the resources in this Downloader.
- *
- * @throws IOException if an unrecoverable error was discovered in dowloading.
+ * Start downloading the resources in this downloader.
+ *
+ * @return true if the download completed or failed for unexpected reasons (in which case the
+ * observer will have been notified), false if it was aborted by the observer.
*/
- public void download ()
- throws IOException
+ public boolean download ()
{
Resource current = null;
try {
@@ -132,12 +122,17 @@ public abstract class Downloader extends Thread
download(resource);
}
- // finally report our download completion if we did not
- // already do so when downloading our final resource
+ // finally report our download completion if we did not already do so when downloading
+ // our final resource
if (_obs != null && !_complete) {
- _obs.downloadProgress(100, 0);
+ if (!_obs.downloadProgress(100, 0)) {
+ return false;
+ }
}
+ } catch (DownloadAbortedException e) {
+ return false;
+
} catch (Exception e) {
if (_obs != null) {
_obs.downloadFailed(current, e);
@@ -145,6 +140,7 @@ public abstract class Downloader extends Thread
Log.logStackTrace(e);
}
}
+ return true;
}
/**
@@ -163,8 +159,7 @@ public abstract class Downloader extends Thread
protected abstract long checkSize (Resource rsrc) throws IOException;
/**
- * Downloads the specified resource from its remote location to its
- * local location.
+ * Downloads the specified resource from its remote location to its local location.
*/
protected void download (Resource rsrc)
throws IOException
@@ -173,23 +168,20 @@ public abstract class Downloader extends Thread
File parent = new File(rsrc.getLocal().getParent());
if (!parent.exists()) {
if (!parent.mkdirs()) {
- Log.warning("Failed to create target directory for " +
- "resource '" + rsrc + "'. Download will " +
- "certainly fail.");
+ Log.warning("Failed to create target directory for resource '" + rsrc + "'. " +
+ "Download will certainly fail.");
}
}
doDownload(rsrc);
}
/**
- * Periodically called by the protocol-specific downloaders
- * to update their progress.
- * @throws IOException
+ * Periodically called by the protocol-specific downloaders to update their progress.
*/
- protected void updateObserver () throws IOException
+ protected void updateObserver ()
+ throws IOException
{
- // notify the observer if it's been sufficiently long
- // since our last notification
+ // notify the observer if it's been sufficiently long since our last notification
long now = System.currentTimeMillis();
if ((now - _lastUpdate) >= UPDATE_DELAY) {
_lastUpdate = now;
@@ -199,24 +191,24 @@ public abstract class Downloader extends Thread
long bps = (secs == 0) ? 0 : (_currentSize / secs);
// compute our percentage completion
- int pctdone = (_totalSize == 0) ? 0 :
- (int)((_currentSize * 100f) / _totalSize);
+ int pctdone = (_totalSize == 0) ? 0 : (int)((_currentSize * 100f) / _totalSize);
// estimate our time remaining
- long remaining = (bps <= 0 || _totalSize == 0) ? -1 :
- (_totalSize - _currentSize) / bps;
+ long remaining = (bps <= 0 || _totalSize == 0) ? -1 : (_totalSize - _currentSize) / bps;
// make sure we only report 100% exactly once
if (pctdone < 100 || !_complete) {
_complete = (pctdone == 100);
- _obs.downloadProgress(pctdone, remaining);
+ if (!_obs.downloadProgress(pctdone, remaining)) {
+ throw new DownloadAbortedException();
+ }
}
}
}
/**
- * Accomplishes the copying of the resource from remote location to
- * local location using protocol-specific code
+ * Accomplishes the copying of the resource from remote location to local location using
+ * protocol-specific code
*/
protected abstract void doDownload (Resource rsrc) throws IOException;
@@ -241,15 +233,13 @@ public abstract class Downloader extends Thread
/** The current transfer rate in bytes per second. */
protected long _bytesPerSecond;
- /** The time at which the last progress update was posted to the
- * progress observer. */
+ /** The time at which the last progress update was posted to the progress observer. */
protected long _lastUpdate;
- /** Whether the download has completed and the progress observer
- * notified. */
+ /** Whether the download has completed and the progress observer notified. */
protected boolean _complete;
- /** The delay in milliseconds between notifying progress observers of
- * file download progress. */
+ /** The delay in milliseconds between notifying progress observers of file download
+ * progress. */
protected static final long UPDATE_DELAY = 500L;
}
diff --git a/src/java/com/threerings/getdown/launcher/HTTPDownloader.java b/src/java/com/threerings/getdown/net/HTTPDownloader.java
similarity index 76%
rename from src/java/com/threerings/getdown/launcher/HTTPDownloader.java
rename to src/java/com/threerings/getdown/net/HTTPDownloader.java
index e2d124c..0a645e8 100644
--- a/src/java/com/threerings/getdown/launcher/HTTPDownloader.java
+++ b/src/java/com/threerings/getdown/net/HTTPDownloader.java
@@ -1,4 +1,24 @@
-package com.threerings.getdown.launcher;
+//
+// $Id$
+//
+// Getdown - application installer, patcher and launcher
+// Copyright (C) 2004-2006 Three Rings Design, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// 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 General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the: Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+package com.threerings.getdown.net;
import java.io.FileOutputStream;
import java.io.IOException;
@@ -59,8 +79,7 @@ public class HTTPDownloader extends Downloader
throws IOException
{
// download the resource from the specified URL
- HttpURLConnection ucon = (HttpURLConnection)
- rsrc.getRemote().openConnection();
+ HttpURLConnection ucon = (HttpURLConnection)rsrc.getRemote().openConnection();
ucon.connect();
// make sure we got a satisfactory response code
diff --git a/src/java/com/threerings/getdown/launcher/TorrentDownloader.java b/src/java/com/threerings/getdown/net/TorrentDownloader.java
similarity index 85%
rename from src/java/com/threerings/getdown/launcher/TorrentDownloader.java
rename to src/java/com/threerings/getdown/net/TorrentDownloader.java
index 1a8cabf..912ea5a 100644
--- a/src/java/com/threerings/getdown/launcher/TorrentDownloader.java
+++ b/src/java/com/threerings/getdown/net/TorrentDownloader.java
@@ -1,4 +1,24 @@
-package com.threerings.getdown.launcher;
+//
+// $Id$
+//
+// Getdown - application installer, patcher and launcher
+// Copyright (C) 2004-2006 Three Rings Design, Inc.
+//
+// This program is free software; you can redistribute it and/or modify it
+// under the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 2 of the License, or (at your option)
+// any later version.
+//
+// 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 General Public License for
+// more details.
+//
+// You should have received a copy of the GNU General Public License along with
+// this program; if not, write to the: Free Software Foundation, Inc.,
+// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+
+package com.threerings.getdown.net;
import java.io.IOException;
import java.util.HashMap;