Screw unpacking our bundles on the fly. Just unpack them once when they
are downloaded and leave them be until the bundle is updated. git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2612 542714f4-19e9-0310-aa3c-eee0fc999fb1
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ResourceBundle.java,v 1.15 2003/05/20 16:29:36 mdb Exp $
|
// $Id: ResourceBundle.java,v 1.16 2003/05/27 07:52:45 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.resource;
|
package com.threerings.resource;
|
||||||
|
|
||||||
@@ -11,10 +11,12 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
import java.util.jar.JarEntry;
|
import java.util.jar.JarEntry;
|
||||||
import java.util.jar.JarFile;
|
import java.util.jar.JarFile;
|
||||||
|
|
||||||
import com.samskivert.io.NestableIOException;
|
import com.samskivert.io.NestableIOException;
|
||||||
|
import com.samskivert.io.StreamUtil;
|
||||||
import com.samskivert.util.FileUtil;
|
import com.samskivert.util.FileUtil;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
|
||||||
@@ -32,7 +34,7 @@ public class ResourceBundle
|
|||||||
*/
|
*/
|
||||||
public ResourceBundle (File source)
|
public ResourceBundle (File source)
|
||||||
{
|
{
|
||||||
this(source, false);
|
this(source, false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -41,10 +43,17 @@ public class ResourceBundle
|
|||||||
* @param source a file object that references our source jar file.
|
* @param source a file object that references our source jar file.
|
||||||
* @param delay if true, the bundle will wait until someone calls
|
* @param delay if true, the bundle will wait until someone calls
|
||||||
* {@link #sourceIsReady} before allowing access to its resources.
|
* {@link #sourceIsReady} before allowing access to its resources.
|
||||||
|
* @param unpack if true the bundle will unpack itself into a
|
||||||
|
* temporary directory
|
||||||
*/
|
*/
|
||||||
public ResourceBundle (File source, boolean delay)
|
public ResourceBundle (File source, boolean delay, boolean unpack)
|
||||||
{
|
{
|
||||||
_source = source;
|
_source = source;
|
||||||
|
if (unpack) {
|
||||||
|
String root = stripSuffix(source.getPath());
|
||||||
|
_unpacked = new File(root + ".stamp");
|
||||||
|
_cache = new File(root);
|
||||||
|
}
|
||||||
|
|
||||||
if (!delay) {
|
if (!delay) {
|
||||||
sourceIsReady();
|
sourceIsReady();
|
||||||
@@ -68,6 +77,92 @@ public class ResourceBundle
|
|||||||
{
|
{
|
||||||
// make a note of our source's last modification time
|
// make a note of our source's last modification time
|
||||||
_sourceLastMod = _source.lastModified();
|
_sourceLastMod = _source.lastModified();
|
||||||
|
|
||||||
|
// if we are unpacking files, the time to do so is now
|
||||||
|
if (_unpacked != null && _unpacked.lastModified() != _sourceLastMod) {
|
||||||
|
boolean resolved = false;
|
||||||
|
try {
|
||||||
|
resolved = !resolveJarFile();
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Failure resolving jar file '" + _source +
|
||||||
|
"': " + ioe + ".");
|
||||||
|
}
|
||||||
|
if (!resolved) {
|
||||||
|
String errmsg = "Source ready but failed to resolve jar " +
|
||||||
|
"[source=" + _source + "]";
|
||||||
|
throw new IllegalStateException(errmsg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.info("Unpacking into " + _cache + "...");
|
||||||
|
if (!_cache.exists()) {
|
||||||
|
if (!_cache.mkdir()) {
|
||||||
|
Log.warning("Failed to create bundle cache directory '" +
|
||||||
|
_cache + "'.");
|
||||||
|
// we are hopelessly fucked
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
FileUtil.recursiveClean(_cache);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean failure = false;
|
||||||
|
Enumeration entries = _jarSource.entries();
|
||||||
|
while (entries.hasMoreElements()) {
|
||||||
|
JarEntry entry = (JarEntry)entries.nextElement();
|
||||||
|
File efile = new File(_cache, entry.getName());
|
||||||
|
|
||||||
|
// if we're unpacking a normal jar file, it will have
|
||||||
|
// special path entries that allow us to create our
|
||||||
|
// directories first
|
||||||
|
if (entry.isDirectory()) {
|
||||||
|
if (!efile.exists() && !efile.mkdir()) {
|
||||||
|
Log.warning("Failed to create bundle entry path '" +
|
||||||
|
efile + "'.");
|
||||||
|
failure = true;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// but some do not, so we want to ensure that our
|
||||||
|
// directories exist prior to getting down and funky
|
||||||
|
File parent = new File(efile.getParent());
|
||||||
|
if (!parent.exists() && !parent.mkdirs()) {
|
||||||
|
Log.warning("Failed to create bundle entry parent '" +
|
||||||
|
parent + "'.");
|
||||||
|
failure = true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
BufferedOutputStream fout = null;
|
||||||
|
InputStream jin = null;
|
||||||
|
try {
|
||||||
|
fout = new BufferedOutputStream(
|
||||||
|
new FileOutputStream(efile));
|
||||||
|
jin = _jarSource.getInputStream(entry);
|
||||||
|
StreamUtils.pipe(jin, fout);
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Failure unpacking " + efile + ": " + ioe);
|
||||||
|
failure = true;
|
||||||
|
} finally {
|
||||||
|
StreamUtil.close(jin);
|
||||||
|
StreamUtil.close(fout);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if everything unpacked smoothly, create our unpack stamp
|
||||||
|
if (!failure) {
|
||||||
|
try {
|
||||||
|
_unpacked.createNewFile();
|
||||||
|
if (!_unpacked.setLastModified(_sourceLastMod)) {
|
||||||
|
Log.warning("Failed to set last mod on stamp file '" +
|
||||||
|
_unpacked + "'.");
|
||||||
|
}
|
||||||
|
} catch (IOException ioe) {
|
||||||
|
Log.warning("Failure creating stamp file '" + _unpacked +
|
||||||
|
"': " + ioe + ".");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -109,15 +204,6 @@ public class ResourceBundle
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute the path to our temporary file
|
|
||||||
String tpath = StringUtil.md5hex(_source.getPath() + "%" + path);
|
|
||||||
File tfile = new File(getCacheDir(), tpath);
|
|
||||||
if (tfile.exists() && (tfile.lastModified() > _sourceLastMod)) {
|
|
||||||
// System.out.println("Using cached " + _source.getPath() +
|
|
||||||
// ":" + path);
|
|
||||||
return tfile;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make sure said resource exists in the first place
|
// make sure said resource exists in the first place
|
||||||
JarEntry entry = _jarSource.getJarEntry(path);
|
JarEntry entry = _jarSource.getJarEntry(path);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
@@ -125,7 +211,18 @@ public class ResourceBundle
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
// System.out.println("Unpacking " + path);
|
// if we have been unpacked, return our unpacked file
|
||||||
|
if (_cache != null) {
|
||||||
|
return new File(_cache, path);
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, we unpack resources as needed into a temp directory
|
||||||
|
String tpath = StringUtil.md5hex(_source.getPath() + "%" + path);
|
||||||
|
File tfile = new File(getCacheDir(), tpath);
|
||||||
|
if (tfile.exists() && (tfile.lastModified() > _sourceLastMod)) {
|
||||||
|
return tfile;
|
||||||
|
}
|
||||||
|
|
||||||
// copy the resource into the temporary file
|
// copy the resource into the temporary file
|
||||||
BufferedOutputStream fout =
|
BufferedOutputStream fout =
|
||||||
new BufferedOutputStream(new FileOutputStream(tfile));
|
new BufferedOutputStream(new FileOutputStream(tfile));
|
||||||
@@ -241,15 +338,29 @@ public class ResourceBundle
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Strips the .jar off of jar file paths. */
|
||||||
|
protected static String stripSuffix (String path)
|
||||||
|
{
|
||||||
|
if (path.endsWith(".jar")) {
|
||||||
|
return path.substring(0, path.length()-4);
|
||||||
|
} else {
|
||||||
|
// we have to change the path somehow
|
||||||
|
return path + "-cache";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/** The file from which we construct our jar file. */
|
/** The file from which we construct our jar file. */
|
||||||
protected File _source;
|
protected File _source;
|
||||||
|
|
||||||
/** The last modified time of our source jar file. */
|
/** The last modified time of our source jar file. */
|
||||||
protected long _sourceLastMod;
|
protected long _sourceLastMod;
|
||||||
|
|
||||||
/** The directory into which our contents are unpacked, if we are
|
/** A file whose timestamp indicates whether or not our existing jar
|
||||||
* unpacked. */
|
* file has been unpacked. */
|
||||||
protected File _unpackDir;
|
protected File _unpacked;
|
||||||
|
|
||||||
|
/** A directory into which we unpack files from our bundle. */
|
||||||
|
protected File _cache;
|
||||||
|
|
||||||
/** The jar file from which we load resources. */
|
/** The jar file from which we load resources. */
|
||||||
protected JarFile _jarSource;
|
protected JarFile _jarSource;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
//
|
//
|
||||||
// $Id: ResourceManager.java,v 1.28 2003/05/05 18:02:37 mdb Exp $
|
// $Id: ResourceManager.java,v 1.29 2003/05/27 07:52:45 mdb Exp $
|
||||||
|
|
||||||
package com.threerings.resource;
|
package com.threerings.resource;
|
||||||
|
|
||||||
@@ -114,6 +114,13 @@ public class ResourceManager
|
|||||||
*/
|
*/
|
||||||
public void downloadProgress (int percent, long remaining);
|
public void downloadProgress (int percent, long remaining);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called following the call to {@link #dowloadProgress} of 100
|
||||||
|
* percent completion to indicate that we have validated and
|
||||||
|
* unpacked our bundles and are fully ready to go.
|
||||||
|
*/
|
||||||
|
public void downloadComplete ();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called if a failure occurs while checking for an update or
|
* Called if a failure occurs while checking for an update or
|
||||||
* downloading all resource sets.
|
* downloading all resource sets.
|
||||||
@@ -282,12 +289,17 @@ public class ResourceManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void downloadProgress (int percent, long remaining) {
|
public void downloadProgress (int percent, long remaining) {
|
||||||
if (percent == 100) {
|
// nothing for now
|
||||||
bundlesDownloaded();
|
}
|
||||||
synchronized (lock) {
|
|
||||||
// wake things up as the download is finished
|
public void postDownloadHook () {
|
||||||
lock.notify();
|
bundlesDownloaded();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void downloadComplete () {
|
||||||
|
synchronized (lock) {
|
||||||
|
// wake things up as the download is finished
|
||||||
|
lock.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,12 +346,17 @@ public class ResourceManager
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void downloadProgress (int percent, long remaining) {
|
public void downloadProgress (int percent, long remaining) {
|
||||||
if (percent == 100) {
|
|
||||||
bundlesDownloaded();
|
|
||||||
}
|
|
||||||
obs.downloadProgress(percent, remaining);
|
obs.downloadProgress(percent, remaining);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void postDownloadHook () {
|
||||||
|
bundlesDownloaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void downloadComplete () {
|
||||||
|
obs.downloadComplete();
|
||||||
|
}
|
||||||
|
|
||||||
public void downloadFailed (DownloadDescriptor desc, Exception e) {
|
public void downloadFailed (DownloadDescriptor desc, Exception e) {
|
||||||
obs.downloadFailed(e);
|
obs.downloadFailed(e);
|
||||||
}
|
}
|
||||||
@@ -492,7 +509,7 @@ public class ResourceManager
|
|||||||
|
|
||||||
// finally, add the file that will be cached to the set as
|
// finally, add the file that will be cached to the set as
|
||||||
// a resource bundle
|
// a resource bundle
|
||||||
set.add(new ResourceBundle(cfile, true));
|
set.add(new ResourceBundle(cfile, true, true));
|
||||||
|
|
||||||
} catch (MalformedURLException mue) {
|
} catch (MalformedURLException mue) {
|
||||||
Log.warning("Unable to create URL for resource " +
|
Log.warning("Unable to create URL for resource " +
|
||||||
|
|||||||
Reference in New Issue
Block a user