Merge pull request #172 from vatsal22/Predownloads

Use presource=[resource] to "predownload" resource
This commit is contained in:
Michael Bayne
2018-11-30 14:49:56 -08:00
committed by GitHub
6 changed files with 101 additions and 19 deletions
@@ -510,12 +510,12 @@ public class Application
* discovered later, the caller can use the application base to download a new {@code * discovered later, the caller can use the application base to download a new {@code
* getdown.txt} file and try again. * getdown.txt} file and try again.
* *
* @return a configured UpdateInterface instance that will be used to configure the update UI. * @return a configured Config instance that contains information from the config file.
* *
* @exception IOException thrown if there is an error reading the file or an error encountered * @exception IOException thrown if there is an error reading the file or an error encountered
* during its parsing. * during its parsing.
*/ */
public UpdateInterface init (boolean checkPlatform) public Config init (boolean checkPlatform)
throws IOException throws IOException
{ {
Config config = null; Config config = null;
@@ -672,6 +672,7 @@ public class Application
parseResources(config, "resource", Resource.NORMAL, _resources); parseResources(config, "resource", Resource.NORMAL, _resources);
parseResources(config, "uresource", Resource.UNPACK, _resources); parseResources(config, "uresource", Resource.UNPACK, _resources);
parseResources(config, "xresource", Resource.EXEC, _resources); parseResources(config, "xresource", Resource.EXEC, _resources);
parseResources(config, "presource", Resource.PREDOWNLOAD, _resources);
// parse our auxiliary resource groups // parse our auxiliary resource groups
for (String auxgroup : config.getList("auxgroups")) { for (String auxgroup : config.getList("auxgroups")) {
@@ -720,6 +721,15 @@ public class Application
_maxConcDownloads = Math.max(1, config.getInt("max_concurrent_downloads", _maxConcDownloads = Math.max(1, config.getInt("max_concurrent_downloads",
SysProps.threadPoolSize())); SysProps.threadPoolSize()));
return config;
}
/**
* Sets various properties using an UpdateInterface based on {@code config}
* @param config Information to base the UpdateInterface off
* @return a configured UpdateInterface instance that will be used to configure the update UI
*/
public UpdateInterface initUpdateInterface(Config config) {
// parse and return our application config // parse and return our application config
UpdateInterface ui = new UpdateInterface(config); UpdateInterface ui = new UpdateInterface(config);
_name = ui.name; _name = ui.name;
@@ -1169,7 +1179,7 @@ public class Application
clearValidationMarkers(); clearValidationMarkers();
// if the new copy validates, reinitialize ourselves; otherwise report baffling hoseage // if the new copy validates, reinitialize ourselves; otherwise report baffling hoseage
if (_digest.validateResource(crsrc, null)) { if (_digest.validateResource(crsrc, null)) {
init(true); initUpdateInterface(init(true));
} else { } else {
log.warning(CONFIG_FILE + " failed to validate even after redownloading. " + log.warning(CONFIG_FILE + " failed to validate even after redownloading. " +
"Blindly forging onward."); "Blindly forging onward.");
@@ -35,12 +35,15 @@ public class Resource implements Comparable<Resource>
* unpacked resource will first be cleared of files before unpacking. */ * unpacked resource will first be cleared of files before unpacking. */
CLEAN, CLEAN,
/** Indicates that the resource should be marked executable. */ /** Indicates that the resource should be marked executable. */
EXEC EXEC,
/** Indicates that the resource should be downloaded before a UI is displayed. */
PREDOWNLOAD
}; };
public static final EnumSet<Attr> NORMAL = EnumSet.noneOf(Attr.class); public static final EnumSet<Attr> NORMAL = EnumSet.noneOf(Attr.class);
public static final EnumSet<Attr> UNPACK = EnumSet.of(Attr.UNPACK); public static final EnumSet<Attr> UNPACK = EnumSet.of(Attr.UNPACK);
public static final EnumSet<Attr> EXEC = EnumSet.of(Attr.EXEC); public static final EnumSet<Attr> EXEC = EnumSet.of(Attr.EXEC);
public static final EnumSet<Attr> PREDOWNLOAD = EnumSet.of(Attr.PREDOWNLOAD);
/** /**
* Computes the MD5 hash of the supplied file. * Computes the MD5 hash of the supplied file.
@@ -201,6 +204,14 @@ public class Resource implements Comparable<Resource>
return _attrs.contains(Attr.UNPACK) && !SysProps.noUnpack(); return _attrs.contains(Attr.UNPACK) && !SysProps.noUnpack();
} }
/**
* Returns true if this resource should be predownloaded.
*/
public boolean shouldPredownload ()
{
return _attrs.contains(Attr.PREDOWNLOAD);
}
/** /**
* Computes the MD5 hash of this resource's underlying file. * Computes the MD5 hash of this resource's underlying file.
* <em>Note:</em> This is both CPU and I/O intensive. * <em>Note:</em> This is both CPU and I/O intensive.
@@ -256,16 +267,27 @@ public class Resource implements Comparable<Resource>
/** /**
* Installs the {@code getLocalNew} version of this resource to {@code getLocal}. * Installs the {@code getLocalNew} version of this resource to {@code getLocal}.
* @param validate Validate resource after installing?
*/ */
public void install () throws IOException { public void install (boolean validate) throws IOException {
File source = getLocalNew(), dest = getLocal(); File source = getLocalNew(), dest = getLocal();
log.info("- " + source); log.info("- " + source);
if (!FileUtil.renameTo(source, dest)) { if (!FileUtil.renameTo(source, dest)) {
throw new IOException("Failed to rename " + source + " to " + dest); throw new IOException("Failed to rename " + source + " to " + dest);
} }
applyAttrs(); applyAttrs();
if (validate){
markAsValid(); markAsValid();
} }
}
/**
* Same as calling {@link #install(boolean)} with {@code true}
*/
public void install () throws IOException {
install(true);
}
/** /**
* Unpacks this resource file into the directory that contains it. * Unpacks this resource file into the directory that contains it.
@@ -60,13 +60,13 @@ public class Differ
} }
Application oapp = new Application(new EnvConfig(ovdir)); Application oapp = new Application(new EnvConfig(ovdir));
oapp.init(false); oapp.initUpdateInterface(oapp.init(false));
ArrayList<Resource> orsrcs = new ArrayList<>(); ArrayList<Resource> orsrcs = new ArrayList<>();
orsrcs.addAll(oapp.getCodeResources()); orsrcs.addAll(oapp.getCodeResources());
orsrcs.addAll(oapp.getResources()); orsrcs.addAll(oapp.getResources());
Application napp = new Application(new EnvConfig(nvdir)); Application napp = new Application(new EnvConfig(nvdir));
napp.init(false); napp.initUpdateInterface(napp.init(false));
ArrayList<Resource> nrsrcs = new ArrayList<>(); ArrayList<Resource> nrsrcs = new ArrayList<>();
nrsrcs.addAll(napp.getCodeResources()); nrsrcs.addAll(napp.getCodeResources());
nrsrcs.addAll(napp.getResources()); nrsrcs.addAll(napp.getResources());
@@ -75,7 +75,7 @@ public class Digester
// create our application and instruct it to parse its business // create our application and instruct it to parse its business
Application app = new Application(new EnvConfig(appdir)); Application app = new Application(new EnvConfig(appdir));
app.init(false); app.initUpdateInterface(app.init(false));
List<Resource> rsrcs = new ArrayList<>(); List<Resource> rsrcs = new ArrayList<>();
rsrcs.add(app.getConfigResource()); rsrcs.add(app.getConfigResource());
@@ -33,8 +33,6 @@ import java.net.HttpURLConnection;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.security.cert.Certificate;
import java.util.*; import java.util.*;
import ca.beq.util.win32.registry.RegistryKey; import ca.beq.util.win32.registry.RegistryKey;
@@ -279,7 +277,9 @@ public abstract class Getdown extends Thread
// to get some sort of interface configuration and the appbase URL // to get some sort of interface configuration and the appbase URL
log.info("Checking whether we need to use a proxy..."); log.info("Checking whether we need to use a proxy...");
try { try {
_ifc = _app.init(true); Config config = _app.init(true);
doPredownloads(_app.getResources());
_ifc = _app.initUpdateInterface(config);
} catch (IOException ioe) { } catch (IOException ioe) {
// no worries // no worries
} }
@@ -339,6 +339,34 @@ public abstract class Getdown extends Thread
} }
} }
/**
* Finds resources from {@code resources} that have a {@code PREDOWNLOAD} attribute,
* then downloads and installs them (without verifying them)
* @param resources resources to predownload
*/
protected void doPredownloads (Collection<Resource> resources) {
List<Resource> predownloads = new ArrayList<>();
for(Resource rsrc: resources) {
if(rsrc.shouldPredownload() && !rsrc.getLocal().exists()) {
predownloads.add(rsrc);
}
}
try {
download(predownloads);
for(Resource rsrc: predownloads) {
// Install but don't validate yet
rsrc.install(false);
}
} catch (IOException ioe) {
log.warning("Failed to predownload resources. Continuing...", ioe);
}
}
/** /**
* Does the actual application validation, update and launching business. * Does the actual application validation, update and launching business.
*/ */
@@ -352,15 +380,23 @@ public abstract class Getdown extends Thread
try { try {
// first parses our application deployment file // first parses our application deployment file
try { try {
_ifc = _app.init(true); Config config = _app.init(true);
doPredownloads(_app.getResources());
_ifc = _app.initUpdateInterface(config);
} catch (IOException ioe) { } catch (IOException ioe) {
log.warning("Failed to initialize: " + ioe); log.warning("Failed to initialize: " + ioe);
_app.attemptRecovery(this); _app.attemptRecovery(this);
// and re-initalize // and re-initalize
_ifc = _app.init(true); Config config = _app.init(true);
doPredownloads(_app.getResources());
_ifc = _app.initUpdateInterface(config);
// now force our UI to be recreated with the updated info // now force our UI to be recreated with the updated info
createInterfaceAsync(true); createInterfaceAsync(true);
setIcons(); // Force icons to be displayed
} }
if (!_app.lockForUpdates()) { if (!_app.lockForUpdates()) {
throw new MultipleGetdownRunning(); throw new MultipleGetdownRunning();
} }
@@ -567,6 +603,12 @@ public abstract class Getdown extends Thread
} }
} }
/**
* Force app to (re)set icons
*/
protected abstract void setIcons();
/** /**
* Downloads and installs an Java VM bundled with the application. This is called if we are not * Downloads and installs an Java VM bundled with the application. This is called if we are not
* running with the necessary Java version. * running with the necessary Java version.
@@ -678,7 +720,8 @@ public abstract class Getdown extends Thread
// finally update our metadata files... // finally update our metadata files...
_app.updateMetadata(); _app.updateMetadata();
// ...and reinitialize the application // ...and reinitialize the application
_ifc = _app.init(true); Config config = _app.init(true);
_ifc = _app.initUpdateInterface(config);
} }
/** /**
@@ -24,7 +24,6 @@ import javax.swing.JFrame;
import javax.swing.WindowConstants; import javax.swing.WindowConstants;
import com.samskivert.swing.util.SwingUtil; import com.samskivert.swing.util.SwingUtil;
import com.threerings.getdown.data.Digest;
import com.threerings.getdown.data.EnvConfig; import com.threerings.getdown.data.EnvConfig;
import com.threerings.getdown.data.SysProps; import com.threerings.getdown.data.SysProps;
import com.threerings.getdown.util.LaunchUtil; import com.threerings.getdown.util.LaunchUtil;
@@ -125,6 +124,15 @@ public class GetdownApp
_frame.getContentPane().removeAll(); _frame.getContentPane().removeAll();
} }
setIcons();
_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
return _frame.getContentPane();
}
protected void setIcons() {
if(_frame == null) return;
if (_ifc.iconImages != null) { if (_ifc.iconImages != null) {
ArrayList<Image> icons = new ArrayList<>(); ArrayList<Image> icons = new ArrayList<>();
for (String path : _ifc.iconImages) { for (String path : _ifc.iconImages) {
@@ -140,10 +148,9 @@ public class GetdownApp
} else { } else {
_frame.setIconImages(icons); _frame.setIconImages(icons);
} }
} else {
log.info("No icons found to load...");
} }
_frame.setDefaultCloseOperation(WindowConstants.DO_NOTHING_ON_CLOSE);
return _frame.getContentPane();
} }
@Override @Override