From 884f4100ee0d196e87cc2d3eff97a9eb0d731234 Mon Sep 17 00:00:00 2001 From: Michael Bayne Date: Mon, 19 Jul 2004 11:59:06 +0000 Subject: [PATCH] New and improved Getdown! Now with better status and error reporting. --- .../threerings/getdown/data/Application.java | 42 ++++++++++++------ .../threerings/getdown/launcher/Getdown.java | 44 ++++++++++++++----- .../threerings/getdown/messages.properties | 26 ++++++++++- 3 files changed, 85 insertions(+), 27 deletions(-) diff --git a/src/java/com/threerings/getdown/data/Application.java b/src/java/com/threerings/getdown/data/Application.java index 9c0ea44..6f9515b 100644 --- a/src/java/com/threerings/getdown/data/Application.java +++ b/src/java/com/threerings/getdown/data/Application.java @@ -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 * getdown.txt 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; } diff --git a/src/java/com/threerings/getdown/launcher/Getdown.java b/src/java/com/threerings/getdown/launcher/Getdown.java index cdc799b..39ecdbf 100644 --- a/src/java/com/threerings/getdown/launcher/Getdown.java +++ b/src/java/com/threerings/getdown/launcher/Getdown.java @@ -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); } }; diff --git a/src/java/com/threerings/getdown/messages.properties b/src/java/com/threerings/getdown/messages.properties index 697cab9..788b6db 100644 --- a/src/java/com/threerings/getdown/messages.properties +++ b/src/java/com/threerings/getdown/messages.properties @@ -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.