Further progress on versioned application upgrades.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Application.java,v 1.8 2004/07/07 16:18:23 mdb Exp $
|
||||
// $Id: Application.java,v 1.9 2004/07/13 02:42:52 mdb Exp $
|
||||
|
||||
package com.threerings.getdown.data;
|
||||
|
||||
@@ -83,7 +83,7 @@ public class Application
|
||||
try {
|
||||
return createResource(CONFIG_FILE);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Booched appbase '" + _appbase + "'!?");
|
||||
throw new RuntimeException("Booched appbase '" + _vappbase + "'!?");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -105,6 +105,32 @@ public class Application
|
||||
return _resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a resource that can be used to download a patch file that
|
||||
* will bring this application from its current version to the target
|
||||
* version.
|
||||
*/
|
||||
public Resource getPatchResource ()
|
||||
{
|
||||
if (_targetVersion <= _version) {
|
||||
Log.warning("Requested patch resource for up-to-date or " +
|
||||
"non-versioned appliation [cvers=" + _version +
|
||||
", tvers=" + _targetVersion + "].");
|
||||
return null;
|
||||
}
|
||||
|
||||
String pfile = "patch" + _version + ".dat";
|
||||
try {
|
||||
URL remote = new URL(createVAppBase(_targetVersion), pfile);
|
||||
return new Resource(pfile, remote, getLocalPath(pfile));
|
||||
} catch (Exception e) {
|
||||
Log.warning("Failed to create patch resource path [pfile=" + pfile +
|
||||
", appbase=" + _appbase + ", tvers=" + _targetVersion +
|
||||
", error=" + e + "].");
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Instructs the application to parse its <code>getdown.txt</code>
|
||||
* configuration and prepare itself for operation. The application
|
||||
@@ -140,19 +166,13 @@ public class Application
|
||||
// first determine our application base, this way if anything goes
|
||||
// wrong later in the process, our caller can use the appbase to
|
||||
// download a new configuration file
|
||||
String appbase = (String)cdata.get("appbase");
|
||||
if (appbase == null) {
|
||||
_appbase = (String)cdata.get("appbase");
|
||||
if (_appbase == null) {
|
||||
throw new IOException("m.missing_appbase");
|
||||
}
|
||||
try {
|
||||
// make sure there's a trailing slash
|
||||
if (!appbase.endsWith("/")) {
|
||||
appbase = appbase + "/";
|
||||
}
|
||||
_appbase = new URL(appbase);
|
||||
} catch (Exception e) {
|
||||
String err = MessageUtil.tcompose("m.invalid_appbase", appbase);
|
||||
throw new NestableIOException(err, e);
|
||||
if (!_appbase.endsWith("/")) {
|
||||
_appbase = _appbase + "/";
|
||||
}
|
||||
|
||||
// extract our version information
|
||||
@@ -167,16 +187,15 @@ public class Application
|
||||
}
|
||||
|
||||
// if we are a versioned deployment, create a versioned appbase
|
||||
if (_version < 0) {
|
||||
_vappbase = _appbase;
|
||||
} else {
|
||||
try {
|
||||
_vappbase = new URL(
|
||||
StringUtil.replace(_appbase.toString(), "%VERSION%", vstr));
|
||||
} catch (MalformedURLException mue) {
|
||||
String err = MessageUtil.tcompose("m.invalid_appbase", appbase);
|
||||
throw new NestableIOException(err, mue);
|
||||
if (_version < 0) {
|
||||
_vappbase = new URL(_appbase);
|
||||
} else {
|
||||
_vappbase = createVAppBase(_version);
|
||||
}
|
||||
} catch (MalformedURLException mue) {
|
||||
String err = MessageUtil.tcompose("m.invalid_appbase", _appbase);
|
||||
throw new NestableIOException(err, mue);
|
||||
}
|
||||
|
||||
// determine our application class name
|
||||
@@ -271,6 +290,30 @@ public class Application
|
||||
downloadControlFile(CONFIG_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Downloads and replaces the <code>getdown.txt</code> and
|
||||
* <code>digest.txt</code> files with those for the target version of
|
||||
* our application.
|
||||
*/
|
||||
public void updateMetadata ()
|
||||
throws IOException
|
||||
{
|
||||
try {
|
||||
// update our versioned application base with the target version
|
||||
_vappbase = createVAppBase(_targetVersion);
|
||||
} catch (MalformedURLException mue) {
|
||||
String err = MessageUtil.tcompose("m.invalid_appbase", _appbase);
|
||||
throw new NestableIOException(err, mue);
|
||||
}
|
||||
|
||||
// now re-download our control files; we download the digest first
|
||||
// so that if it fails, our config file will still reference the
|
||||
// old version and re-running the updater will start the whole
|
||||
// process over again
|
||||
downloadControlFile(Digest.DIGEST_FILE);
|
||||
downloadControlFile(CONFIG_FILE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the process associated with this application definition.
|
||||
*/
|
||||
@@ -345,7 +388,7 @@ public class Application
|
||||
public boolean verifyMetadata ()
|
||||
throws IOException
|
||||
{
|
||||
Log.info("Verifying application: " + _appbase);
|
||||
Log.info("Verifying application: " + _vappbase);
|
||||
Log.info("Version: " + _version);
|
||||
Log.info("Class: " + _class);
|
||||
// Log.info("Code: " + StringUtil.toString(_codes.iterator()));
|
||||
@@ -439,6 +482,25 @@ public class Application
|
||||
return (failures.size() == 0) ? null : failures;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears all validation marker files.
|
||||
*/
|
||||
public void clearValidationMarkers ()
|
||||
{
|
||||
clearValidationMarkers(_codes.iterator());
|
||||
clearValidationMarkers(_resources.iterator());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a versioned application base URL for the specified version.
|
||||
*/
|
||||
protected URL createVAppBase (int version)
|
||||
throws MalformedURLException
|
||||
{
|
||||
return new URL(
|
||||
StringUtil.replace(_appbase, "%VERSION%", "" + version));
|
||||
}
|
||||
|
||||
/** A helper function used by {@link #verifyResources()}. */
|
||||
protected void verifyResources (Iterator rsrcs, List failures)
|
||||
{
|
||||
@@ -463,13 +525,6 @@ public class Application
|
||||
}
|
||||
}
|
||||
|
||||
/** Clears all validation marker files. */
|
||||
protected void clearValidationMarkers ()
|
||||
{
|
||||
clearValidationMarkers(_codes.iterator());
|
||||
clearValidationMarkers(_resources.iterator());
|
||||
}
|
||||
|
||||
/** Clears all validation marker files for the resources in the
|
||||
* supplied iterator. */
|
||||
protected void clearValidationMarkers (Iterator iter)
|
||||
@@ -493,7 +548,7 @@ public class Application
|
||||
targetURL = getRemoteURL(path);
|
||||
} catch (Exception e) {
|
||||
Log.warning("Requested to download invalid control file " +
|
||||
"[appbase=" + _appbase + ", path=" + path +
|
||||
"[appbase=" + _vappbase + ", path=" + path +
|
||||
", error=" + e + "].");
|
||||
throw new NestableIOException("Invalid path '" + path + "'.", e);
|
||||
}
|
||||
@@ -567,7 +622,8 @@ public class Application
|
||||
|
||||
protected int _version = -1;
|
||||
protected int _targetVersion = -1;
|
||||
protected URL _appbase, _vappbase;
|
||||
protected String _appbase;
|
||||
protected URL _vappbase;
|
||||
protected String _class;
|
||||
|
||||
protected ArrayList _codes = new ArrayList();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
//
|
||||
// $Id: Getdown.java,v 1.6 2004/07/07 10:45:20 mdb Exp $
|
||||
// $Id: Getdown.java,v 1.7 2004/07/13 02:42:52 mdb Exp $
|
||||
|
||||
package com.threerings.getdown.launcher;
|
||||
|
||||
@@ -16,6 +16,7 @@ import java.io.IOException;
|
||||
import java.io.PrintStream;
|
||||
|
||||
import java.text.MessageFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
@@ -43,6 +44,7 @@ public class Getdown
|
||||
public void run ()
|
||||
{
|
||||
try {
|
||||
// first parses our application deployment file
|
||||
try {
|
||||
_ifc = _app.init();
|
||||
} catch (IOException ioe) {
|
||||
@@ -52,29 +54,35 @@ public class Getdown
|
||||
}
|
||||
|
||||
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
||||
// make sure we have the desired version and that the
|
||||
// metadata files are valid...
|
||||
if (_app.verifyMetadata()) {
|
||||
Log.info("Application requires update.");
|
||||
update();
|
||||
// loop back again and reverify the metadata
|
||||
continue;
|
||||
}
|
||||
|
||||
} else {
|
||||
Log.info("Metadata verified.");
|
||||
// now verify our resources...
|
||||
List failures = _app.verifyResources();
|
||||
if (failures == null) {
|
||||
Log.info("Resources verified.");
|
||||
launch();
|
||||
return;
|
||||
}
|
||||
|
||||
} else {
|
||||
// redownload any that are corrupt or invalid...
|
||||
Log.info(failures.size() + " rsrcs require update.");
|
||||
download(failures);
|
||||
// now we'll loop back and try it all again
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Log.warning("Pants! We couldn't get the job done.");
|
||||
// TODO: throw exception
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.logStackTrace(e);
|
||||
// TODO: display error to user
|
||||
}
|
||||
}
|
||||
|
||||
@@ -82,7 +90,30 @@ public class Getdown
|
||||
* Called if the application is determined to be of an old version.
|
||||
*/
|
||||
protected void update ()
|
||||
throws IOException
|
||||
{
|
||||
// first clear all validation markers
|
||||
_app.clearValidationMarkers();
|
||||
|
||||
// attempt to download the patch file
|
||||
Resource patch = _app.getPatchResource();
|
||||
if (patch != null) {
|
||||
// download the patch file...
|
||||
ArrayList list = new ArrayList();
|
||||
list.add(patch);
|
||||
download(list);
|
||||
|
||||
// and apply it...
|
||||
// TODO
|
||||
}
|
||||
// if the patch resource is null, that means something was booched
|
||||
// in the application, so we skip the patching process but update
|
||||
// the metadata which will result in a "brute force" upgrade
|
||||
|
||||
// finally update our metadata files...
|
||||
_app.updateMetadata();
|
||||
// ...and reinitialize the application
|
||||
_ifc = _app.init();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -196,16 +227,21 @@ public class Getdown
|
||||
|
||||
public static void main (String[] args)
|
||||
{
|
||||
// ensure the proper parameters are passed
|
||||
// maybe they specified the appdir in a system property
|
||||
String adarg = System.getProperty("appdir");
|
||||
// if not, check for a command line argument
|
||||
if (StringUtil.blank(adarg)) {
|
||||
if (args.length != 1) {
|
||||
System.err.println("Usage: java -jar getdown.jar app_dir");
|
||||
System.exit(-1);
|
||||
}
|
||||
adarg = args[0];
|
||||
}
|
||||
|
||||
// ensure a valid directory was supplied
|
||||
File appDir = new File(args[0]);
|
||||
File appDir = new File(adarg);
|
||||
if (!appDir.exists() || !appDir.isDirectory()) {
|
||||
Log.warning("Invalid app_dir '" + args[0] + "'.");
|
||||
Log.warning("Invalid app_dir '" + adarg + "'.");
|
||||
System.exit(-1);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user