Merge pull request #60 from runiter/master
Avoid corrupted resources when download is interrupted
This commit is contained in:
@@ -35,6 +35,7 @@ public class Resource
|
|||||||
_path = path;
|
_path = path;
|
||||||
_remote = remote;
|
_remote = remote;
|
||||||
_local = local;
|
_local = local;
|
||||||
|
_local_new = new File(local.toString() + "_new");
|
||||||
String lpath = _local.getPath();
|
String lpath = _local.getPath();
|
||||||
_marker = new File(lpath + "v");
|
_marker = new File(lpath + "v");
|
||||||
|
|
||||||
@@ -66,6 +67,11 @@ public class Resource
|
|||||||
return _local;
|
return _local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public File getLocalNew ()
|
||||||
|
{
|
||||||
|
return _local_new;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the location of the unpacked resource.
|
* Returns the location of the unpacked resource.
|
||||||
*/
|
*/
|
||||||
@@ -106,7 +112,16 @@ public class Resource
|
|||||||
public String computeDigest (MessageDigest md, ProgressObserver obs)
|
public String computeDigest (MessageDigest md, ProgressObserver obs)
|
||||||
throws IOException
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -284,7 +299,7 @@ public class Resource
|
|||||||
|
|
||||||
protected static boolean isJar (String path)
|
protected static boolean isJar (String path)
|
||||||
{
|
{
|
||||||
return path.endsWith(".jar");
|
return path.endsWith(".jar") || path.endsWith(".jar_new");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static boolean isPacked200Jar (String path)
|
protected static boolean isPacked200Jar (String path)
|
||||||
@@ -294,7 +309,7 @@ public class Resource
|
|||||||
|
|
||||||
protected String _path;
|
protected String _path;
|
||||||
protected URL _remote;
|
protected URL _remote;
|
||||||
protected File _local, _marker, _unpacked;
|
protected File _local, _local_new, _marker, _unpacked;
|
||||||
protected boolean _unpack, _isJar, _isPacked200Jar;
|
protected boolean _unpack, _isJar, _isPacked200Jar;
|
||||||
|
|
||||||
/** Used to sort the entries in a jar file. */
|
/** Used to sort the entries in a jar file. */
|
||||||
|
|||||||
@@ -49,6 +49,10 @@ public class SysProps
|
|||||||
return System.getProperty("silent") != null;
|
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.
|
/** If true, Getdown installs the app without ever bringing up a UI and then launches it.
|
||||||
* Usage: {@code -Dsilent=launch}. */
|
* Usage: {@code -Dsilent=launch}. */
|
||||||
public static boolean launchInSilent () {
|
public static boolean launchInSilent () {
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ import com.threerings.getdown.net.HTTPDownloader;
|
|||||||
import com.threerings.getdown.tools.Patcher;
|
import com.threerings.getdown.tools.Patcher;
|
||||||
import com.threerings.getdown.util.ConfigUtil;
|
import com.threerings.getdown.util.ConfigUtil;
|
||||||
import com.threerings.getdown.util.ConnectionUtil;
|
import com.threerings.getdown.util.ConnectionUtil;
|
||||||
|
import com.threerings.getdown.util.FileUtil;
|
||||||
import com.threerings.getdown.util.LaunchUtil;
|
import com.threerings.getdown.util.LaunchUtil;
|
||||||
import com.threerings.getdown.util.ProgressAggregator;
|
import com.threerings.getdown.util.ProgressAggregator;
|
||||||
import com.threerings.getdown.util.ProgressObserver;
|
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
|
// 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.
|
// launch, start the application after installing. Otherwise, just install and exit.
|
||||||
_silent = SysProps.silent();
|
_silent = SysProps.silent();
|
||||||
|
_install = SysProps.install();
|
||||||
if (_silent) {
|
if (_silent) {
|
||||||
_launchInSilent = SysProps.launchInSilent();
|
_launchInSilent = SysProps.launchInSilent();
|
||||||
}
|
}
|
||||||
@@ -409,6 +411,9 @@ public abstract class Getdown extends Thread
|
|||||||
|
|
||||||
// we'll keep track of all the resources we unpack
|
// we'll keep track of all the resources we unpack
|
||||||
Set<Resource> unpacked = new HashSet<Resource>();
|
Set<Resource> unpacked = new HashSet<Resource>();
|
||||||
|
|
||||||
|
toBeInstalledResouces = new ArrayList<Resource>();
|
||||||
|
readyToInstall = false;
|
||||||
|
|
||||||
//setStep(Step.START);
|
//setStep(Step.START);
|
||||||
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
for (int ii = 0; ii < MAX_LOOPS; ii++) {
|
||||||
@@ -442,6 +447,7 @@ public abstract class Getdown extends Thread
|
|||||||
setStep(Step.VERIFY_RESOURCES);
|
setStep(Step.VERIFY_RESOURCES);
|
||||||
setStatusAsync("m.validating", -1, -1L, false);
|
setStatusAsync("m.validating", -1, -1L, false);
|
||||||
List<Resource> failures = _app.verifyResources(_progobs, alreadyValid, unpacked);
|
List<Resource> failures = _app.verifyResources(_progobs, alreadyValid, unpacked);
|
||||||
|
addToBeInstalledResources(failures);
|
||||||
if (failures == null) {
|
if (failures == null) {
|
||||||
log.info("Resources verified.");
|
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
|
// Only launch if we aren't in silent mode. Some mystery program starting out
|
||||||
// of the blue would be disconcerting.
|
// of the blue would be disconcerting.
|
||||||
if (!_silent || _launchInSilent) {
|
if (!_silent || _launchInSilent) {
|
||||||
@@ -531,7 +541,16 @@ public abstract class Getdown extends Thread
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// documentation inherited from interface
|
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
|
||||||
public void updateStatus (String message)
|
public void updateStatus (String message)
|
||||||
{
|
{
|
||||||
setStatusAsync(message, -1, -1L, true);
|
setStatusAsync(message, -1, -1L, true);
|
||||||
@@ -754,7 +773,32 @@ public abstract class Getdown extends Thread
|
|||||||
throw new MultipleGetdownRunning();
|
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.
|
* Called to launch the application if everything is determined to be ready to go.
|
||||||
*/
|
*/
|
||||||
@@ -1219,6 +1263,7 @@ public abstract class Getdown extends Thread
|
|||||||
|
|
||||||
protected boolean _dead;
|
protected boolean _dead;
|
||||||
protected boolean _silent;
|
protected boolean _silent;
|
||||||
|
protected boolean _install;
|
||||||
protected boolean _launchInSilent;
|
protected boolean _launchInSilent;
|
||||||
protected long _startup;
|
protected long _startup;
|
||||||
|
|
||||||
@@ -1239,4 +1284,6 @@ public abstract class Getdown extends Thread
|
|||||||
protected static final long PLAY_AGAIN_TIME = 3000L;
|
protected static final long PLAY_AGAIN_TIME = 3000L;
|
||||||
protected static final String PROXY_REGISTRY =
|
protected static final String PROXY_REGISTRY =
|
||||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings";
|
||||||
|
protected static List<Resource> toBeInstalledResouces;
|
||||||
|
protected static boolean readyToInstall;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class HTTPDownloader extends Downloader
|
|||||||
long currentSize = 0L;
|
long currentSize = 0L;
|
||||||
try {
|
try {
|
||||||
in = conn.getInputStream();
|
in = conn.getInputStream();
|
||||||
out = new FileOutputStream(rsrc.getLocal());
|
out = new FileOutputStream(rsrc.getLocalNew());
|
||||||
int read;
|
int read;
|
||||||
|
|
||||||
// TODO: look to see if we have a download info file
|
// TODO: look to see if we have a download info file
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ public class FileUtil extends com.samskivert.util.FileUtil
|
|||||||
fin = new FileInputStream(source);
|
fin = new FileInputStream(source);
|
||||||
fout = new FileOutputStream(dest);
|
fout = new FileOutputStream(dest);
|
||||||
StreamUtil.copy(fin, fout);
|
StreamUtil.copy(fin, fout);
|
||||||
|
fin.close(); // needed otherwise cannot delete source
|
||||||
if (!source.delete()) {
|
if (!source.delete()) {
|
||||||
log.warning("Failed to delete " + source +
|
log.warning("Failed to delete " + source +
|
||||||
" after brute force copy to " + dest + ".");
|
" after brute force copy to " + dest + ".");
|
||||||
|
|||||||
Reference in New Issue
Block a user