diff --git a/src/main/java/com/threerings/getdown/data/Resource.java b/src/main/java/com/threerings/getdown/data/Resource.java index 688db55..b5657dc 100644 --- a/src/main/java/com/threerings/getdown/data/Resource.java +++ b/src/main/java/com/threerings/getdown/data/Resource.java @@ -13,7 +13,6 @@ import java.util.Comparator; import java.util.List; import java.util.jar.JarEntry; import java.util.jar.JarFile; -import java.util.jar.JarInputStream; import com.samskivert.io.StreamUtil; import com.samskivert.util.StringUtil; @@ -36,6 +35,7 @@ public class Resource _path = path; _remote = remote; _local = local; + _local_new = new File(local.toString() + "_new"); String lpath = _local.getPath(); _marker = new File(lpath + "v"); @@ -67,6 +67,11 @@ public class Resource return _local; } + public File getLocalNew () + { + return _local_new; + } + /** * Returns the location of the unpacked resource. */ @@ -107,7 +112,16 @@ public class Resource public String computeDigest (MessageDigest md, ProgressObserver obs) throws IOException { - return computeDigest(_local, md, obs); + File file; + if (_local.toString().toLowerCase().endsWith(Application.CONFIG_FILE)) + file = _local; + else { + if (_local_new.exists()) + file = _local_new; + else + file = _local; + } + return computeDigest(file, md, obs); } /** @@ -292,7 +306,7 @@ public class Resource protected static boolean isJar (String path) { - return path.endsWith(".jar"); + return path.endsWith(".jar") || path.endsWith(".jar_new"); } protected static boolean isPacked200Jar (String path) @@ -302,7 +316,7 @@ public class Resource protected String _path; protected URL _remote; - protected File _local, _marker, _unpacked; + protected File _local, _local_new, _marker, _unpacked; protected boolean _unpack, _isJar, _isPacked200Jar; /** Used to sort the entries in a jar file. */ diff --git a/src/main/java/com/threerings/getdown/data/SysProps.java b/src/main/java/com/threerings/getdown/data/SysProps.java index 6dfdf9c..39381b0 100644 --- a/src/main/java/com/threerings/getdown/data/SysProps.java +++ b/src/main/java/com/threerings/getdown/data/SysProps.java @@ -49,6 +49,10 @@ public class SysProps return System.getProperty("silent") != null; } + public static boolean install () { + return System.getProperty("no_install") == null; + } + /** If true, Getdown installs the app without ever bringing up a UI and then launches it. * Usage: {@code -Dsilent=launch}. */ public static boolean launchInSilent () { diff --git a/src/main/java/com/threerings/getdown/launcher/Getdown.java b/src/main/java/com/threerings/getdown/launcher/Getdown.java index 3afc3a9..df5d1ad 100644 --- a/src/main/java/com/threerings/getdown/launcher/Getdown.java +++ b/src/main/java/com/threerings/getdown/launcher/Getdown.java @@ -68,6 +68,7 @@ import com.threerings.getdown.net.HTTPDownloader; import com.threerings.getdown.tools.Patcher; import com.threerings.getdown.util.ConfigUtil; import com.threerings.getdown.util.ConnectionUtil; +import com.threerings.getdown.util.FileUtil; import com.threerings.getdown.util.LaunchUtil; import com.threerings.getdown.util.ProgressAggregator; import com.threerings.getdown.util.ProgressObserver; @@ -100,6 +101,7 @@ 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(); } @@ -409,6 +411,9 @@ public abstract class Getdown extends Thread // we'll keep track of all the resources we unpack Set unpacked = new HashSet(); + + toBeInstalledResouces = new ArrayList(); + readyToInstall = false; //setStep(Step.START); for (int ii = 0; ii < MAX_LOOPS; ii++) { @@ -442,6 +447,7 @@ public abstract class Getdown extends Thread setStep(Step.VERIFY_RESOURCES); setStatusAsync("m.validating", -1, -1L, false); List failures = _app.verifyResources(_progobs, alreadyValid, unpacked); + addToBeInstalledResources(failures); if (failures == null) { log.info("Resources verified."); @@ -471,6 +477,10 @@ public abstract class Getdown extends Thread } } + readyToInstall = true; + if (_install) + install(); + // Only launch if we aren't in silent mode. Some mystery program starting out // of the blue would be disconcerting. if (!_silent || _launchInSilent) { @@ -531,7 +541,16 @@ public abstract class Getdown extends Thread } } - // documentation inherited from interface + private void addToBeInstalledResources(List resources) { + if (resources == null) + return; + else + for (Resource r : resources) + if (!toBeInstalledResouces.contains(r)) + toBeInstalledResouces.add(r); + } + + // documentation inherited from interface public void updateStatus (String message) { setStatusAsync(message, -1, -1L, true); @@ -754,7 +773,28 @@ 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."); + } + } + /** * Called to launch the application if everything is determined to be ready to go. */ @@ -1219,6 +1259,7 @@ public abstract class Getdown extends Thread protected boolean _dead; protected boolean _silent; + protected boolean _install; protected boolean _launchInSilent; protected long _startup; @@ -1239,4 +1280,6 @@ 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 toBeInstalledResouces; + protected static boolean readyToInstall; } diff --git a/src/main/java/com/threerings/getdown/net/HTTPDownloader.java b/src/main/java/com/threerings/getdown/net/HTTPDownloader.java index 738d064..286ebc5 100644 --- a/src/main/java/com/threerings/getdown/net/HTTPDownloader.java +++ b/src/main/java/com/threerings/getdown/net/HTTPDownloader.java @@ -78,7 +78,7 @@ public class HTTPDownloader extends Downloader long currentSize = 0L; try { in = conn.getInputStream(); - out = new FileOutputStream(rsrc.getLocal()); + out = new FileOutputStream(rsrc.getLocalNew()); int read; // TODO: look to see if we have a download info file diff --git a/src/main/java/com/threerings/getdown/util/FileUtil.java b/src/main/java/com/threerings/getdown/util/FileUtil.java index c957e59..efde120 100644 --- a/src/main/java/com/threerings/getdown/util/FileUtil.java +++ b/src/main/java/com/threerings/getdown/util/FileUtil.java @@ -57,6 +57,7 @@ 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 if (!source.delete()) { log.warning("Failed to delete " + source + " after brute force copy to " + dest + ".");