Tidy up new resources stuff a bit.
The one major change here is that Getdown.isUpdateAvailable/install() are no longer static. GetdownApp has a start() method that you can call if you want to get the Getdown reference back. You can call isUpdateAvailable() on that. It was super weird that you would call GetdownApp.main() and then just call some static methods after that.
This commit is contained in:
@@ -35,7 +35,7 @@ public class Resource
|
||||
_path = path;
|
||||
_remote = remote;
|
||||
_local = local;
|
||||
_local_new = new File(local.toString() + "_new");
|
||||
_localNew = new File(local.toString() + "_new");
|
||||
String lpath = _local.getPath();
|
||||
_marker = new File(lpath + "v");
|
||||
|
||||
@@ -67,9 +67,12 @@ public class Resource
|
||||
return _local;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the location of the to-be-installed new version of this resource.
|
||||
*/
|
||||
public File getLocalNew ()
|
||||
{
|
||||
return _local_new;
|
||||
return _localNew;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,18 +112,14 @@ public class Resource
|
||||
* Computes the MD5 hash of this resource's underlying file.
|
||||
* <em>Note:</em> This is both CPU and I/O intensive.
|
||||
*/
|
||||
public String computeDigest (MessageDigest md, ProgressObserver obs)
|
||||
throws IOException
|
||||
public String computeDigest (MessageDigest md, ProgressObserver obs) throws IOException
|
||||
{
|
||||
File file;
|
||||
if (_local.toString().toLowerCase().endsWith(Application.CONFIG_FILE))
|
||||
file = _local;
|
||||
else {
|
||||
if (_local_new.exists())
|
||||
file = _local_new;
|
||||
else
|
||||
file = _local;
|
||||
}
|
||||
File file;
|
||||
if (_local.toString().toLowerCase().endsWith(Application.CONFIG_FILE)) {
|
||||
file = _local;
|
||||
} else {
|
||||
file = _localNew.exists() ? _localNew : _local;
|
||||
}
|
||||
return computeDigest(file, md, obs);
|
||||
}
|
||||
|
||||
@@ -309,7 +308,7 @@ public class Resource
|
||||
|
||||
protected String _path;
|
||||
protected URL _remote;
|
||||
protected File _local, _local_new, _marker, _unpacked;
|
||||
protected File _local, _localNew, _marker, _unpacked;
|
||||
protected boolean _unpack, _isJar, _isPacked200Jar;
|
||||
|
||||
/** Used to sort the entries in a jar file. */
|
||||
|
||||
@@ -49,8 +49,11 @@ public class SysProps
|
||||
return System.getProperty("silent") != null;
|
||||
}
|
||||
|
||||
public static boolean install () {
|
||||
return System.getProperty("no_install") == null;
|
||||
/** If true, Getdown does not automatically install updates after downloading them. It waits
|
||||
* for the application to call {@link Getdown#install}.
|
||||
* Usage: {@code -Dno_install}. */
|
||||
public static boolean noInstall () {
|
||||
return System.getProperty("no_install") != null;
|
||||
}
|
||||
|
||||
/** If true, Getdown installs the app without ever bringing up a UI and then launches it.
|
||||
|
||||
@@ -101,11 +101,11 @@ public abstract class Getdown extends Thread
|
||||
// If the silent property exists, install without bringing up any gui. If it equals
|
||||
// launch, start the application after installing. Otherwise, just install and exit.
|
||||
_silent = SysProps.silent();
|
||||
_install = SysProps.install();
|
||||
if (_silent) {
|
||||
_launchInSilent = SysProps.launchInSilent();
|
||||
}
|
||||
_delay = SysProps.startDelay();
|
||||
_noInstall = SysProps.noInstall();
|
||||
} catch (SecurityException se) {
|
||||
// don't freak out, just assume non-silent and no delay; we're probably already
|
||||
// recovering from a security failure
|
||||
@@ -128,6 +128,39 @@ public abstract class Getdown extends Thread
|
||||
_startup = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if there are pending new resources, waiting to be installed.
|
||||
*/
|
||||
public boolean isUpdateAvailable ()
|
||||
{
|
||||
return _readyToInstall && !_toBeInstalledResouces.isEmpty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Installs the currently pending new resources.
|
||||
*/
|
||||
public void install () throws IOException, InterruptedException
|
||||
{
|
||||
if (_readyToInstall) {
|
||||
log.info("Installing downloaded resources:");
|
||||
for (Resource resource : _toBeInstalledResouces) {
|
||||
File source = resource.getLocalNew(), dest = resource.getLocal();
|
||||
log.info("- " + source);
|
||||
if (!FileUtil.renameTo(source, dest)) {
|
||||
throw new IOException("Failed to rename " + source + " to " + dest);
|
||||
}
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException("m.applet_stopped");
|
||||
}
|
||||
}
|
||||
_toBeInstalledResouces.clear();
|
||||
_readyToInstall = false;
|
||||
log.info("Install completed.");
|
||||
} else {
|
||||
log.info("Nothing to install.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This is used by the applet which always needs a user interface and wants to load it as soon
|
||||
* as possible.
|
||||
@@ -411,9 +444,9 @@ public abstract class Getdown extends Thread
|
||||
|
||||
// we'll keep track of all the resources we unpack
|
||||
Set<Resource> unpacked = new HashSet<Resource>();
|
||||
|
||||
toBeInstalledResouces = new ArrayList<Resource>();
|
||||
readyToInstall = false;
|
||||
|
||||
_toBeInstalledResouces = new ArrayList<Resource>();
|
||||
_readyToInstall = false;
|
||||
|
||||
//setStep(Step.START);
|
||||
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
||||
@@ -447,7 +480,6 @@ public abstract class Getdown extends Thread
|
||||
setStep(Step.VERIFY_RESOURCES);
|
||||
setStatusAsync("m.validating", -1, -1L, false);
|
||||
List<Resource> failures = _app.verifyResources(_progobs, alreadyValid, unpacked);
|
||||
addToBeInstalledResources(failures);
|
||||
if (failures == null) {
|
||||
log.info("Resources verified.");
|
||||
|
||||
@@ -477,9 +509,11 @@ public abstract class Getdown extends Thread
|
||||
}
|
||||
}
|
||||
|
||||
readyToInstall = true;
|
||||
if (_install)
|
||||
install();
|
||||
// assuming we're not doing anything funny, install the update
|
||||
_readyToInstall = true;
|
||||
if (!_noInstall) {
|
||||
install();
|
||||
}
|
||||
|
||||
// Only launch if we aren't in silent mode. Some mystery program starting out
|
||||
// of the blue would be disconcerting.
|
||||
@@ -496,6 +530,13 @@ public abstract class Getdown extends Thread
|
||||
return;
|
||||
}
|
||||
|
||||
// we have failures, those will be redownloaded so we note them as to-be-installed
|
||||
for (Resource r : failures) {
|
||||
if (!_toBeInstalledResouces.contains(r)) {
|
||||
_toBeInstalledResouces.add(r);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
// if any of our resources have already been marked valid this is not a first
|
||||
// time install and we don't want to enable tracking
|
||||
@@ -509,6 +550,7 @@ public abstract class Getdown extends Thread
|
||||
download(failures);
|
||||
|
||||
reportTrackingEvent("app_complete", -1);
|
||||
|
||||
} finally {
|
||||
_enableTracking = false;
|
||||
}
|
||||
@@ -541,16 +583,7 @@ public abstract class Getdown extends Thread
|
||||
}
|
||||
}
|
||||
|
||||
private void addToBeInstalledResources(List<Resource> resources) {
|
||||
if (resources == null)
|
||||
return;
|
||||
else
|
||||
for (Resource r : resources)
|
||||
if (!toBeInstalledResouces.contains(r))
|
||||
toBeInstalledResouces.add(r);
|
||||
}
|
||||
|
||||
// documentation inherited from interface
|
||||
// documentation inherited from interface
|
||||
public void updateStatus (String message)
|
||||
{
|
||||
setStatusAsync(message, -1, -1L, true);
|
||||
@@ -773,32 +806,7 @@ public abstract class Getdown extends Thread
|
||||
throw new MultipleGetdownRunning();
|
||||
}
|
||||
}
|
||||
|
||||
public static void install ()
|
||||
throws IOException, InterruptedException
|
||||
{
|
||||
if (readyToInstall) {
|
||||
log.info("Installing downloaded resources:");
|
||||
for (Resource resource : toBeInstalledResouces) {
|
||||
log.info(resource);
|
||||
if (!FileUtil.renameTo(resource.getLocalNew(), resource.getLocal()))
|
||||
throw new IOException("Failed to rename(" + resource.getLocalNew() + ", " + resource.getLocal() + ")");
|
||||
if (Thread.interrupted()) {
|
||||
throw new InterruptedException("m.applet_stopped");
|
||||
}
|
||||
}
|
||||
toBeInstalledResouces.clear();
|
||||
readyToInstall = false;
|
||||
log.info("Install completed.");
|
||||
} else {
|
||||
log.info("Nothing to install.");
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isUpdateAvailable() {
|
||||
return readyToInstall && !toBeInstalledResouces.isEmpty();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called to launch the application if everything is determined to be ready to go.
|
||||
*/
|
||||
@@ -1263,10 +1271,13 @@ public abstract class Getdown extends Thread
|
||||
|
||||
protected boolean _dead;
|
||||
protected boolean _silent;
|
||||
protected boolean _install;
|
||||
protected boolean _noInstall;
|
||||
protected boolean _launchInSilent;
|
||||
protected long _startup;
|
||||
|
||||
protected List<Resource> _toBeInstalledResouces;
|
||||
protected boolean _readyToInstall;
|
||||
|
||||
protected boolean _enableTracking = true;
|
||||
protected int _reportedProgress = 0;
|
||||
|
||||
@@ -1284,6 +1295,4 @@ public abstract class Getdown extends Thread
|
||||
protected static final long PLAY_AGAIN_TIME = 3000L;
|
||||
protected static final String PROXY_REGISTRY =
|
||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
|
||||
protected static List<Resource> toBeInstalledResouces;
|
||||
protected static boolean readyToInstall;
|
||||
}
|
||||
|
||||
@@ -36,6 +36,20 @@ public class GetdownApp
|
||||
{
|
||||
public static void main (String[] argv)
|
||||
{
|
||||
try {
|
||||
start(argv);
|
||||
} catch (Exception e) {
|
||||
log.warning("main() failed.", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs Getdown as an application, using the arguments supplie as {@code argv}.
|
||||
* @return the {@code Getdown} instance that is running. {@link Getdown#start} will have been
|
||||
* called on it.
|
||||
* @throws Exception if anything goes wrong starting Getdown.
|
||||
*/
|
||||
public static Getdown start (String[] argv) throws Exception {
|
||||
int aidx = 0;
|
||||
List<String> args = Arrays.asList(argv);
|
||||
|
||||
@@ -91,118 +105,114 @@ public class GetdownApp
|
||||
log.info("-- Cur dir: " + System.getProperty("user.dir"));
|
||||
log.info("---------------------------------------------");
|
||||
|
||||
try {
|
||||
Getdown app = new Getdown(appDir, appId, null, null, appArgs) {
|
||||
@Override
|
||||
protected Container createContainer () {
|
||||
// create our user interface, and display it
|
||||
String title = StringUtil.isBlank(_ifc.name) ? "" : _ifc.name;
|
||||
if (_frame == null) {
|
||||
_frame = new JFrame(title);
|
||||
_frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing (WindowEvent evt) {
|
||||
handleWindowClose();
|
||||
}
|
||||
});
|
||||
_frame.setUndecorated(_ifc.hideDecorations);
|
||||
_frame.setResizable(false);
|
||||
} else {
|
||||
_frame.setTitle(title);
|
||||
_frame.getContentPane().removeAll();
|
||||
}
|
||||
|
||||
if (_ifc.iconImages != null) {
|
||||
ArrayList<Image> icons = new ArrayList<Image>();
|
||||
for (String path : _ifc.iconImages) {
|
||||
Image img = loadImage(path);
|
||||
if (img == null) {
|
||||
log.warning("Error loading icon image", "path", path);
|
||||
} else {
|
||||
icons.add(img);
|
||||
}
|
||||
Getdown app = new Getdown(appDir, appId, null, null, appArgs) {
|
||||
@Override
|
||||
protected Container createContainer () {
|
||||
// create our user interface, and display it
|
||||
String title = StringUtil.isBlank(_ifc.name) ? "" : _ifc.name;
|
||||
if (_frame == null) {
|
||||
_frame = new JFrame(title);
|
||||
_frame.addWindowListener(new WindowAdapter() {
|
||||
@Override
|
||||
public void windowClosing (WindowEvent evt) {
|
||||
handleWindowClose();
|
||||
}
|
||||
if (icons.isEmpty()) {
|
||||
log.warning("Failed to load any icons", "iconImages", _ifc.iconImages);
|
||||
});
|
||||
_frame.setUndecorated(_ifc.hideDecorations);
|
||||
_frame.setResizable(false);
|
||||
} else {
|
||||
_frame.setTitle(title);
|
||||
_frame.getContentPane().removeAll();
|
||||
}
|
||||
|
||||
if (_ifc.iconImages != null) {
|
||||
ArrayList<Image> icons = new ArrayList<Image>();
|
||||
for (String path : _ifc.iconImages) {
|
||||
Image img = loadImage(path);
|
||||
if (img == null) {
|
||||
log.warning("Error loading icon image", "path", path);
|
||||
} else {
|
||||
SwingUtil.setFrameIcons(_frame, icons);
|
||||
icons.add(img);
|
||||
}
|
||||
}
|
||||
|
||||
_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
return _frame.getContentPane();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showContainer () {
|
||||
if (_frame != null) {
|
||||
_frame.pack();
|
||||
SwingUtil.centerWindow(_frame);
|
||||
_frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void disposeContainer () {
|
||||
if (_frame != null) {
|
||||
_frame.dispose();
|
||||
_frame = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showDocument (String url) {
|
||||
String[] cmdarray;
|
||||
if (RunAnywhere.isWindows()) {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.indexOf("9") != -1 || osName.indexOf("Me") != -1) {
|
||||
cmdarray = new String[] {
|
||||
"command.com", "/c", "start", "\"" + url + "\"" };
|
||||
} else {
|
||||
cmdarray = new String[] {
|
||||
"cmd.exe", "/c", "start", "\"\"", "\"" + url + "\"" };
|
||||
}
|
||||
} else if (RunAnywhere.isMacOS()) {
|
||||
cmdarray = new String[] { "open", url };
|
||||
} else { // Linux, Solaris, etc.
|
||||
cmdarray = new String[] { "firefox", url };
|
||||
}
|
||||
try {
|
||||
Runtime.getRuntime().exec(cmdarray);
|
||||
} catch (Exception e) {
|
||||
log.warning("Failed to open browser.", "cmdarray", cmdarray, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit (int exitCode) {
|
||||
// if we're running the app in the same JVM, don't call System.exit, but do
|
||||
// make double sure that the download window is closed.
|
||||
if (invokeDirect()) {
|
||||
disposeContainer();
|
||||
if (icons.isEmpty()) {
|
||||
log.warning("Failed to load any icons", "iconImages", _ifc.iconImages);
|
||||
} else {
|
||||
System.exit(exitCode);
|
||||
SwingUtil.setFrameIcons(_frame, icons);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fail (String message) {
|
||||
// if the frame was set to be undecorated, make window decoration available
|
||||
// to allow the user to close the window
|
||||
if (_frame != null && _frame.isUndecorated()) {
|
||||
_frame.dispose();
|
||||
_frame.setUndecorated(false);
|
||||
showContainer();
|
||||
}
|
||||
super.fail(message);
|
||||
_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
|
||||
return _frame.getContentPane();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void showContainer () {
|
||||
if (_frame != null) {
|
||||
_frame.pack();
|
||||
SwingUtil.centerWindow(_frame);
|
||||
_frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
||||
protected JFrame _frame;
|
||||
};
|
||||
app.start();
|
||||
@Override
|
||||
protected void disposeContainer () {
|
||||
if (_frame != null) {
|
||||
_frame.dispose();
|
||||
_frame = null;
|
||||
}
|
||||
}
|
||||
|
||||
} catch (Exception e) {
|
||||
log.warning("main() failed.", e);
|
||||
}
|
||||
@Override
|
||||
protected void showDocument (String url) {
|
||||
String[] cmdarray;
|
||||
if (RunAnywhere.isWindows()) {
|
||||
String osName = System.getProperty("os.name");
|
||||
if (osName.indexOf("9") != -1 || osName.indexOf("Me") != -1) {
|
||||
cmdarray = new String[] {
|
||||
"command.com", "/c", "start", "\"" + url + "\"" };
|
||||
} else {
|
||||
cmdarray = new String[] {
|
||||
"cmd.exe", "/c", "start", "\"\"", "\"" + url + "\"" };
|
||||
}
|
||||
} else if (RunAnywhere.isMacOS()) {
|
||||
cmdarray = new String[] { "open", url };
|
||||
} else { // Linux, Solaris, etc.
|
||||
cmdarray = new String[] { "firefox", url };
|
||||
}
|
||||
try {
|
||||
Runtime.getRuntime().exec(cmdarray);
|
||||
} catch (Exception e) {
|
||||
log.warning("Failed to open browser.", "cmdarray", cmdarray, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void exit (int exitCode) {
|
||||
// if we're running the app in the same JVM, don't call System.exit, but do
|
||||
// make double sure that the download window is closed.
|
||||
if (invokeDirect()) {
|
||||
disposeContainer();
|
||||
} else {
|
||||
System.exit(exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void fail (String message) {
|
||||
// if the frame was set to be undecorated, make window decoration available
|
||||
// to allow the user to close the window
|
||||
if (_frame != null && _frame.isUndecorated()) {
|
||||
_frame.dispose();
|
||||
_frame.setUndecorated(false);
|
||||
showContainer();
|
||||
}
|
||||
super.fail(message);
|
||||
}
|
||||
|
||||
protected JFrame _frame;
|
||||
};
|
||||
app.start();
|
||||
return app;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,9 @@ public class FileUtil extends com.samskivert.util.FileUtil
|
||||
fin = new FileInputStream(source);
|
||||
fout = new FileOutputStream(dest);
|
||||
StreamUtil.copy(fin, fout);
|
||||
fin.close(); // needed otherwise cannot delete source
|
||||
// close the input stream now so we can delete 'source'
|
||||
fin.close();
|
||||
fin = null;
|
||||
if (!source.delete()) {
|
||||
log.warning("Failed to delete " + source +
|
||||
" after brute force copy to " + dest + ".");
|
||||
|
||||
Reference in New Issue
Block a user