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; package com.threerings.getdown.data;
@@ -64,6 +64,14 @@ public class Application
public String background; 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 * Creates an application instance which records the location of the
* <code>getdown.txt</code> configuration file from the supplied * <code>getdown.txt</code> configuration file from the supplied
@@ -386,7 +394,7 @@ public class Application
* @exception IOException thrown if we encounter an unrecoverable * @exception IOException thrown if we encounter an unrecoverable
* error while verifying the metadata. * error while verifying the metadata.
*/ */
public boolean verifyMetadata () public boolean verifyMetadata (StatusDisplay status)
throws IOException throws IOException
{ {
Log.info("Verifying application: " + _vappbase); Log.info("Verifying application: " + _vappbase);
@@ -413,18 +421,25 @@ public class Application
// to revalidate all of our resources as one or more of them // to revalidate all of our resources as one or more of them
// have also changed // have also changed
String olddig = (_digest == null) ? "" : _digest.getMetaDigest(); String olddig = (_digest == null) ? "" : _digest.getMetaDigest();
downloadControlFile(Digest.DIGEST_FILE); try {
_digest = new Digest(_appdir); downloadControlFile(Digest.DIGEST_FILE);
if (!olddig.equals(_digest.getMetaDigest())) { _digest = new Digest(_appdir);
Log.info("Unversioned digest changed. Revalidating..."); if (!olddig.equals(_digest.getMetaDigest())) {
clearValidationMarkers(); 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) { // regardless of whether we're versioned, if we failed to read the
// if we failed to load the digest, try to redownload the // digest from disk, try to redownload the digest file and give it
// digest file and give it another good college try; this time // another good college try; this time we allow exceptions to
// we allow exceptions to propagate up to the caller as there // propagate up to the caller as there is nothing else we can do
// is nothing else we can do to recover if (_digest == null) {
status.updateStatus("m.updating_metadata");
downloadControlFile(Digest.DIGEST_FILE); downloadControlFile(Digest.DIGEST_FILE);
_digest = new Digest(_appdir); _digest = new Digest(_appdir);
} }
@@ -432,6 +447,7 @@ public class Application
// now verify the contents of our main config file // now verify the contents of our main config file
Resource crsrc = getConfigResource(); Resource crsrc = getConfigResource();
if (!_digest.validateResource(crsrc, null)) { if (!_digest.validateResource(crsrc, null)) {
status.updateStatus("m.updating_metadata");
// attempt to redownload the file; again we pass errors up to // attempt to redownload the file; again we pass errors up to
// our caller because we have no recourse to recovery // our caller because we have no recourse to recovery
downloadControlFile(CONFIG_FILE); downloadControlFile(CONFIG_FILE);
@@ -462,8 +478,6 @@ public class Application
StreamUtil.close(fin); StreamUtil.close(fin);
} }
// next parse any custom user interface information
// finally let the caller know if we need an update // finally let the caller know if we need an update
return _version != _targetVersion; 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; package com.threerings.getdown.launcher;
@@ -24,6 +24,7 @@ import java.util.ResourceBundle;
// import org.apache.commons.io.TeeOutputStream; // import org.apache.commons.io.TeeOutputStream;
import com.samskivert.swing.util.SwingUtil; import com.samskivert.swing.util.SwingUtil;
import com.samskivert.text.MessageUtil;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.getdown.Log; import com.threerings.getdown.Log;
@@ -37,6 +38,7 @@ import com.threerings.getdown.util.ProgressObserver;
* deployment system. * deployment system.
*/ */
public class Getdown extends Thread public class Getdown extends Thread
implements Application.StatusDisplay
{ {
public Getdown (File appDir) public Getdown (File appDir)
{ {
@@ -53,6 +55,7 @@ public class Getdown extends Thread
_ifc = _app.init(); _ifc = _app.init();
} catch (IOException ioe) { } catch (IOException ioe) {
Log.warning("Failed to parse 'getdown.txt': " + ioe); Log.warning("Failed to parse 'getdown.txt': " + ioe);
updateStatus("m.init_failed");
_app.attemptRecovery(); _app.attemptRecovery();
_ifc = _app.init(); _ifc = _app.init();
} }
@@ -60,8 +63,8 @@ public class Getdown extends Thread
for (int ii = 0; ii < MAX_LOOPS; ii++) { for (int ii = 0; ii < MAX_LOOPS; ii++) {
// make sure we have the desired version and that the // make sure we have the desired version and that the
// metadata files are valid... // metadata files are valid...
setStatus("m.validating", -1, -1L); setStatus("m.validating", -1, -1L, false);
if (_app.verifyMetadata()) { if (_app.verifyMetadata(this)) {
Log.info("Application requires update."); Log.info("Application requires update.");
update(); update();
// loop back again and reverify the metadata // loop back again and reverify the metadata
@@ -69,6 +72,7 @@ public class Getdown extends Thread
} }
// now verify our resources... // now verify our resources...
setStatus("m.validating", -1, -1L, false);
List failures = _app.verifyResources(_progobs); List failures = _app.verifyResources(_progobs);
if (failures == null) { if (failures == null) {
Log.info("Resources verified."); Log.info("Resources verified.");
@@ -83,14 +87,26 @@ public class Getdown extends Thread
} }
Log.warning("Pants! We couldn't get the job done."); Log.warning("Pants! We couldn't get the job done.");
// TODO: throw exception throw new IOException("m.unable_to_repair");
} catch (Exception e) { } catch (Exception e) {
Log.logStackTrace(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. * Called if the application is determined to be of an old version.
*/ */
@@ -109,7 +125,7 @@ public class Getdown extends Thread
download(list); download(list);
// and apply it... // and apply it...
setStatus("m.patching", -1, -1L); updateStatus("m.patching");
Patcher patcher = new Patcher(); Patcher patcher = new Patcher();
patcher.patch(patch.getLocal().getParentFile(), patcher.patch(patch.getLocal().getParentFile(),
patch.getLocal(), _progobs); patch.getLocal(), _progobs);
@@ -143,11 +159,11 @@ public class Getdown extends Thread
// create a downloader to download our resources // create a downloader to download our resources
Downloader.Observer obs = new Downloader.Observer() { Downloader.Observer obs = new Downloader.Observer() {
public void resolvingDownloads () { public void resolvingDownloads () {
setStatus("m.resolving", -1, -1L); updateStatus("m.resolving");
} }
public void downloadProgress (int percent, long remaining) { public void downloadProgress (int percent, long remaining) {
setStatus("m.downloading", percent, remaining); setStatus("m.downloading", percent, remaining, true);
if (percent == 100) { if (percent == 100) {
synchronized (lock) { synchronized (lock) {
lock.notify(); lock.notify();
@@ -159,7 +175,7 @@ public class Getdown extends Thread
String msg = MessageFormat.format( String msg = MessageFormat.format(
_msgs.getString("m.failure"), _msgs.getString("m.failure"),
new Object[] { e.getMessage() }); new Object[] { e.getMessage() });
setStatus(msg, -1, -1L); updateStatus(msg);
Log.warning("Download failed [rsrc=" + rsrc + "]."); Log.warning("Download failed [rsrc=" + rsrc + "].");
Log.logStackTrace(e); Log.logStackTrace(e);
synchronized (lock) { synchronized (lock) {
@@ -186,7 +202,7 @@ public class Getdown extends Thread
*/ */
protected void launch () protected void launch ()
{ {
setStatus("m.launching", 100, -1L); setStatus("m.launching", 100, -1L, false);
try { try {
Process proc = _app.createProcess(); Process proc = _app.createProcess();
@@ -235,8 +251,12 @@ public class Getdown extends Thread
} }
protected void setStatus (final String message, final int percent, 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) { if (_status != null) {
EventQueue.invokeLater(new Runnable() { EventQueue.invokeLater(new Runnable() {
public void run () { public void run () {
@@ -294,7 +314,7 @@ public class Getdown extends Thread
/** Used to pass progress on to our user interface. */ /** Used to pass progress on to our user interface. */
protected ProgressObserver _progobs = new ProgressObserver() { protected ProgressObserver _progobs = new ProgressObserver() {
public void progress (final int percent) { 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 # Getdown translation messages
@@ -13,3 +13,27 @@ m.launching = Launching...
m.complete = {0}% complete m.complete = {0}% complete
m.complete_remain = {0}% complete {1}s remaining 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.