Added the ability to add dynamic bundles which can be downloaded and added

in while the game is running.


git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2668 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
Ray Greenwell
2003-06-19 01:30:27 +00:00
parent b4f2c4c526
commit 3d8e053a7f
@@ -1,8 +1,10 @@
// //
// $Id: ResourceManager.java,v 1.30 2003/05/29 16:35:59 mdb Exp $ // $Id: ResourceManager.java,v 1.31 2003/06/19 01:30:27 ray Exp $
package com.threerings.resource; package com.threerings.resource;
import java.awt.EventQueue;
import java.io.BufferedInputStream; import java.io.BufferedInputStream;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@@ -27,6 +29,7 @@ import javax.imageio.stream.FileImageInputStream;
import javax.imageio.stream.ImageInputStream; import javax.imageio.stream.ImageInputStream;
import javax.imageio.stream.MemoryCacheImageInputStream; import javax.imageio.stream.MemoryCacheImageInputStream;
import com.samskivert.util.ResultListener;
import com.samskivert.util.StringUtil; import com.samskivert.util.StringUtil;
import com.threerings.resource.DownloadManager.DownloadDescriptor; import com.threerings.resource.DownloadManager.DownloadDescriptor;
@@ -236,16 +239,15 @@ public class ResourceManager
resourceURL += "/"; resourceURL += "/";
} }
URL rurl = null;
try { try {
rurl = new URL(resourceURL); _rurl = new URL(resourceURL);
} catch (MalformedURLException mue) { } catch (MalformedURLException mue) {
Log.warning("Invalid resource URL [url=" + resourceURL + Log.warning("Invalid resource URL [url=" + resourceURL +
", error=" + mue + "]."); ", error=" + mue + "].");
} }
// load up our configuration // load up our configuration
Properties config = loadConfig(rurl, configPath); Properties config = loadConfig(configPath);
// resolve the configured resource sets // resolve the configured resource sets
ArrayList dlist = new ArrayList(); ArrayList dlist = new ArrayList();
@@ -256,7 +258,7 @@ public class ResourceManager
continue; continue;
} }
String setName = key.substring(RESOURCE_SET_PREFIX.length()); String setName = key.substring(RESOURCE_SET_PREFIX.length());
resolveResourceSet(rurl, setName, config.getProperty(key), dlist); resolveResourceSet(setName, config.getProperty(key), dlist);
} }
// start the download, blocking if we've no observer // start the download, blocking if we've no observer
@@ -268,6 +270,97 @@ public class ResourceManager
} }
} }
/**
* Create the resource bundle for the specified set and path.
*/
protected ResourceBundle createResourceBundle (String setName, String path)
{
createCacheDirectory(setName);
File cfile = new File(genCachePath(setName, path));
return new ResourceBundle(cfile, true, true);
}
/**
* Checks to see if the specified dynamic bundle is already here
* and ready to roll.
*/
public boolean checkDynamicBundle (String path)
{
return createResourceBundle(DYNAMIC_BUNDLE_SET, path).isUnpacked();
}
/**
* Resolve the specified dynamic bundle and return it on the specified
* result listener.
*/
public void resolveDynamicBundle (String path,
final ResultListener listener)
{
URL burl;
try {
burl = new URL(_rurl, path);
} catch (MalformedURLException mue) {
listener.requestFailed(mue);
return;
}
final ResourceBundle bundle = createResourceBundle(
DYNAMIC_BUNDLE_SET, path);
if (bundle.isUnpacked()) {
bundle.sourceIsReady();
listener.requestCompleted(bundle);
return;
}
// slap this on the list for retrieval or update by the
// download manager
ArrayList list = new ArrayList();
list.add(new DownloadDescriptor(burl, bundle.getSource()));
// TODO: There should only be one download manager for all dynamic
// bundles, with each bundle waiting its turn to use it.
DownloadObserver obs = new DownloadObserver() {
public boolean notifyOnAWTThread () {
return false;
}
public void resolvingDownloads () {
}
public void downloadProgress (int percent, long remaining) {
}
public void postDownloadHook () {
}
public void downloadComplete ()
{
bundle.sourceIsReady();
EventQueue.invokeLater(new Runnable() {
public void run () {
listener.requestCompleted(bundle);
}
});
}
public void downloadFailed (
DownloadDescriptor desc, final Exception e)
{
Log.warning("Failed to download file " +
"[desc=" + desc + ", e=" + e + "].");
EventQueue.invokeLater(new Runnable() {
public void run () {
listener.requestFailed(e);
}
});
}
};
DownloadManager dlmgr = new DownloadManager();
dlmgr.download(list, true, obs);
}
/** /**
* Downloads the files in the supplied download list, blocking the * Downloads the files in the supplied download list, blocking the
* calling thread until the download is complete or a failure has * calling thread until the download is complete or a failure has
@@ -383,20 +476,20 @@ public class ResourceManager
* Loads up the most recent version of the resource manager * Loads up the most recent version of the resource manager
* configuration. * configuration.
*/ */
protected Properties loadConfig (URL resourceURL, String configPath) protected Properties loadConfig (String configPath)
{ {
Properties config = new Properties(); Properties config = new Properties();
URL curl = null; URL curl = null;
try { try {
if (configPath != null) { if (configPath != null) {
curl = new URL(resourceURL, configPath); curl = new URL(_rurl, configPath);
config.load(curl.openStream()); config.load(curl.openStream());
} }
} catch (MalformedURLException mue) { } catch (MalformedURLException mue) {
Log.warning("Unable to construct config URL " + Log.warning("Unable to construct config URL " +
"[resourceURL=" + resourceURL + "[resourceURL=" + _rurl +
", configPath=" + configPath + ", configPath=" + configPath +
", error=" + mue + "]."); ", error=" + mue + "].");
@@ -416,7 +509,7 @@ public class ResourceManager
* @return true if the directory was successfully created (or was * @return true if the directory was successfully created (or was
* already there), false if we failed to create it. * already there), false if we failed to create it.
*/ */
protected boolean createCacheDirectory (URL resourceURL, String setName) protected boolean createCacheDirectory (String setName)
{ {
// compute the path to the top-level cache directory if we haven't // compute the path to the top-level cache directory if we haven't
// already been so configured // already been so configured
@@ -430,8 +523,7 @@ public class ResourceManager
// next incorporate the resource URL into the cache path so // next incorporate the resource URL into the cache path so
// that files fetched from different resource roots do not // that files fetched from different resource roots do not
// overwrite one another // overwrite one another
_cachePath += StringUtil.md5hex(resourceURL.toString()) + _cachePath += StringUtil.md5hex(_rurl.toString()) + File.separator;
File.separator;
if (!createDirectory(_cachePath)) { if (!createDirectory(_cachePath)) {
return false; return false;
} }
@@ -473,8 +565,7 @@ public class ResourceManager
* Generates the name of the bundle cache file given the name of the * Generates the name of the bundle cache file given the name of the
* resource set to which it belongs and the relative path URL. * resource set to which it belongs and the relative path URL.
*/ */
protected String genCachePath ( protected String genCachePath (String setName, String resourcePath)
URL resourceURL, String setName, String resourcePath)
{ {
return _cachePath + setName + File.separator + return _cachePath + setName + File.separator +
StringUtil.replace(resourcePath, "/", "-"); StringUtil.replace(resourcePath, "/", "-");
@@ -485,7 +576,7 @@ public class ResourceManager
* information. * information.
*/ */
protected void resolveResourceSet ( protected void resolveResourceSet (
URL resourceURL, String setName, String definition, List dlist) String setName, String definition, List dlist)
{ {
StringTokenizer tok = new StringTokenizer(definition, ":"); StringTokenizer tok = new StringTokenizer(definition, ":");
ArrayList set = new ArrayList(); ArrayList set = new ArrayList();
@@ -495,13 +586,13 @@ public class ResourceManager
URL burl = null; URL burl = null;
try { try {
burl = new URL(resourceURL, path); burl = new URL(_rurl, path);
// make sure the cache directory exists for this set // make sure the cache directory exists for this set
createCacheDirectory(resourceURL, setName); createCacheDirectory(setName);
// compute the path to the cache file for this bundle // compute the path to the cache file for this bundle
File cfile = new File(genCachePath(resourceURL, setName, path)); File cfile = new File(genCachePath(setName, path));
// slap this on the list for retrieval or update by the // slap this on the list for retrieval or update by the
// download manager // download manager
@@ -692,6 +783,9 @@ public class ResourceManager
/** The classloader we use for classpath-based resource loading. */ /** The classloader we use for classpath-based resource loading. */
protected ClassLoader _loader; protected ClassLoader _loader;
/** The url via which we download our bundles. */
protected URL _rurl;
/** The prefix we prepend to resource paths before attempting to load /** The prefix we prepend to resource paths before attempting to load
* them from the classpath. */ * them from the classpath. */
protected String _rootPath; protected String _rootPath;
@@ -717,4 +811,7 @@ public class ResourceManager
/** The name of our resource bundle cache directory. */ /** The name of our resource bundle cache directory. */
protected static final String CACHE_PATH = ".narya"; protected static final String CACHE_PATH = ".narya";
/** The name of the resource set where we store dynamic bundles. */
protected static final String DYNAMIC_BUNDLE_SET = "_dynamic";
} }