New and improved Getdown! Now with better status and error reporting.

This commit is contained in:
Michael Bayne
2004-07-19 11:59:06 +00:00
parent b87a59464a
commit 884f4100ee
3 changed files with 85 additions and 27 deletions
@@ -1,5 +1,5 @@
//
// $Id: Application.java,v 1.12 2004/07/14 13:44:49 mdb Exp $
// $Id: Application.java,v 1.13 2004/07/19 11:59:06 mdb Exp $
package com.threerings.getdown.data;
@@ -64,6 +64,14 @@ public class Application
public String background;
}
/** Used by {@link #verifyMetadata} to communicate status in
* circumstances where it needs to take network actions. */
public static interface StatusDisplay
{
/** Requests that the specified status message be displayed. */
public void updateStatus (String message);
}
/**
* Creates an application instance which records the location of the
* <code>getdown.txt</code> configuration file from the supplied
@@ -386,7 +394,7 @@ public class Application
* @exception IOException thrown if we encounter an unrecoverable
* error while verifying the metadata.
*/
public boolean verifyMetadata ()
public boolean verifyMetadata (StatusDisplay status)
throws IOException
{
Log.info("Verifying application: " + _vappbase);
@@ -413,18 +421,25 @@ public class Application
// to revalidate all of our resources as one or more of them
// have also changed
String olddig = (_digest == null) ? "" : _digest.getMetaDigest();
downloadControlFile(Digest.DIGEST_FILE);
_digest = new Digest(_appdir);
if (!olddig.equals(_digest.getMetaDigest())) {
Log.info("Unversioned digest changed. Revalidating...");
clearValidationMarkers();
try {
downloadControlFile(Digest.DIGEST_FILE);
_digest = new Digest(_appdir);
if (!olddig.equals(_digest.getMetaDigest())) {
Log.info("Unversioned digest changed. Revalidating...");
clearValidationMarkers();
}
} catch (IOException ioe) {
Log.warning("Failed to refresh non-versioned digest: " +
ioe.getMessage() + ". Proceeding...");
}
}
} else if (_digest == null) {
// if we failed to load the digest, try to redownload the
// digest file and give it another good college try; this time
// we allow exceptions to propagate up to the caller as there
// is nothing else we can do to recover
// regardless of whether we're versioned, if we failed to read the
// digest from disk, try to redownload the digest file and give it
// another good college try; this time we allow exceptions to
// propagate up to the caller as there is nothing else we can do
if (_digest == null) {
status.updateStatus("m.updating_metadata");
downloadControlFile(Digest.DIGEST_FILE);
_digest = new Digest(_appdir);
}
@@ -432,6 +447,7 @@ public class Application
// now verify the contents of our main config file
Resource crsrc = getConfigResource();
if (!_digest.validateResource(crsrc, null)) {
status.updateStatus("m.updating_metadata");
// attempt to redownload the file; again we pass errors up to
// our caller because we have no recourse to recovery
downloadControlFile(CONFIG_FILE);
@@ -462,8 +478,6 @@ public class Application
StreamUtil.close(fin);
}
// next parse any custom user interface information
// finally let the caller know if we need an update
return _version != _targetVersion;
}
@@ -1,5 +1,5 @@
//
// $Id: Getdown.java,v 1.11 2004/07/14 14:04:44 mdb Exp $
// $Id: Getdown.java,v 1.12 2004/07/19 11:59:06 mdb Exp $
package com.threerings.getdown.launcher;
@@ -24,6 +24,7 @@ import java.util.ResourceBundle;
// import org.apache.commons.io.TeeOutputStream;
import com.samskivert.swing.util.SwingUtil;
import com.samskivert.text.MessageUtil;
import com.samskivert.util.StringUtil;
import com.threerings.getdown.Log;
@@ -37,6 +38,7 @@ import com.threerings.getdown.util.ProgressObserver;
* deployment system.
*/
public class Getdown extends Thread
implements Application.StatusDisplay
{
public Getdown (File appDir)
{
@@ -53,6 +55,7 @@ public class Getdown extends Thread
_ifc = _app.init();
} catch (IOException ioe) {
Log.warning("Failed to parse 'getdown.txt': " + ioe);
updateStatus("m.init_failed");
_app.attemptRecovery();
_ifc = _app.init();
}
@@ -60,8 +63,8 @@ public class Getdown extends Thread
for (int ii = 0; ii < MAX_LOOPS; ii++) {
// make sure we have the desired version and that the
// metadata files are valid...
setStatus("m.validating", -1, -1L);
if (_app.verifyMetadata()) {
setStatus("m.validating", -1, -1L, false);
if (_app.verifyMetadata(this)) {
Log.info("Application requires update.");
update();
// loop back again and reverify the metadata
@@ -69,6 +72,7 @@ public class Getdown extends Thread
}
// now verify our resources...
setStatus("m.validating", -1, -1L, false);
List failures = _app.verifyResources(_progobs);
if (failures == null) {
Log.info("Resources verified.");
@@ -83,14 +87,26 @@ public class Getdown extends Thread
}
Log.warning("Pants! We couldn't get the job done.");
// TODO: throw exception
throw new IOException("m.unable_to_repair");
} catch (Exception e) {
Log.logStackTrace(e);
// TODO: display error to user
String msg = e.getMessage();
if (msg == null) {
msg = "m.unknown_error";
} else if (!msg.startsWith("m.")) {
msg = MessageUtil.tcompose("m.init_error", msg);
}
updateStatus(msg);
}
}
// documentation inherited from interface
public void updateStatus (String message)
{
setStatus(message, -1, -1L, true);
}
/**
* Called if the application is determined to be of an old version.
*/
@@ -109,7 +125,7 @@ public class Getdown extends Thread
download(list);
// and apply it...
setStatus("m.patching", -1, -1L);
updateStatus("m.patching");
Patcher patcher = new Patcher();
patcher.patch(patch.getLocal().getParentFile(),
patch.getLocal(), _progobs);
@@ -143,11 +159,11 @@ public class Getdown extends Thread
// create a downloader to download our resources
Downloader.Observer obs = new Downloader.Observer() {
public void resolvingDownloads () {
setStatus("m.resolving", -1, -1L);
updateStatus("m.resolving");
}
public void downloadProgress (int percent, long remaining) {
setStatus("m.downloading", percent, remaining);
setStatus("m.downloading", percent, remaining, true);
if (percent == 100) {
synchronized (lock) {
lock.notify();
@@ -159,7 +175,7 @@ public class Getdown extends Thread
String msg = MessageFormat.format(
_msgs.getString("m.failure"),
new Object[] { e.getMessage() });
setStatus(msg, -1, -1L);
updateStatus(msg);
Log.warning("Download failed [rsrc=" + rsrc + "].");
Log.logStackTrace(e);
synchronized (lock) {
@@ -186,7 +202,7 @@ public class Getdown extends Thread
*/
protected void launch ()
{
setStatus("m.launching", 100, -1L);
setStatus("m.launching", 100, -1L, false);
try {
Process proc = _app.createProcess();
@@ -235,8 +251,12 @@ public class Getdown extends Thread
}
protected void setStatus (final String message, final int percent,
final long remaining)
final long remaining, boolean createUI)
{
if (_status == null && createUI) {
createInterface();
}
if (_status != null) {
EventQueue.invokeLater(new Runnable() {
public void run () {
@@ -294,7 +314,7 @@ public class Getdown extends Thread
/** Used to pass progress on to our user interface. */
protected ProgressObserver _progobs = new ProgressObserver() {
public void progress (final int percent) {
setStatus(null, percent, -1L);
setStatus(null, percent, -1L, false);
}
};
@@ -1,5 +1,5 @@
#
# $Id: messages.properties,v 1.2 2004/07/14 13:44:49 mdb Exp $
# $Id: messages.properties,v 1.3 2004/07/19 11:59:06 mdb Exp $
#
# Getdown translation messages
@@ -13,3 +13,27 @@ m.launching = Launching...
m.complete = {0}% complete
m.complete_remain = {0}% complete {1}s remaining
m.updating_metadata = Downloading control files...
m.init_failed = Our configuration file is missing or corrupt. Attempting \
to download a new copy...
m.unable_to_repair = We were unable to download the necessary files after \
five attempts. You can try running the application again, but if it \
fails you may need to uninstall and reinstall.
m.unknown_error = The application has failed to launch due to some strange \
error from which we could not recover. Please visit the support section \
of the website for information on how to recover.
m.init_error = The application as failed to launch due to the following \
error:\n{0}\n\nPlease visit the support section of the website for \
information on how to handle such problems.
# application/digest errors
m.missing_appbase = The configuration file is missing the 'appbase'.
m.invalid_version = The configuration file specifies an invalid version.
m.invalid_appbase = The configuration file specifies an invalid 'appbase'.
m.missing_class = The configuration file is missing the application class.
m.missing_code = The configuration file specifies no code resources.
m.invalid_digest_file = The digest file is invalid.