e1f4b19e37
git-svn-id: svn+ssh://src.earth.threerings.net/narya/trunk@2138 542714f4-19e9-0310-aa3c-eee0fc999fb1
191 lines
5.8 KiB
Java
191 lines
5.8 KiB
Java
//
|
|
// $Id: ResourceBundle.java,v 1.7 2003/01/14 02:51:40 mdb Exp $
|
|
|
|
package com.threerings.resource;
|
|
|
|
import java.io.BufferedOutputStream;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileNotFoundException;
|
|
import java.io.FileOutputStream;
|
|
import java.io.IOException;
|
|
import java.io.InputStream;
|
|
|
|
import java.util.jar.JarEntry;
|
|
import java.util.jar.JarFile;
|
|
|
|
import com.samskivert.io.NestableIOException;
|
|
import com.samskivert.util.StringUtil;
|
|
|
|
import org.apache.commons.io.StreamUtils;
|
|
|
|
/**
|
|
* A resource bundle provides access to the resources in a jar file.
|
|
*/
|
|
public class ResourceBundle
|
|
{
|
|
/**
|
|
* Constructs a resource bundle with the supplied jar file.
|
|
*
|
|
* @param source a file object that references our source jar file.
|
|
*/
|
|
public ResourceBundle (File source)
|
|
{
|
|
_source = source;
|
|
_sourceLastMod = source.lastModified();
|
|
}
|
|
|
|
/**
|
|
* Returns the {@link File} from which resources are fetched for this
|
|
* bundle.
|
|
*/
|
|
public File getSource ()
|
|
{
|
|
return _source;
|
|
}
|
|
|
|
/**
|
|
* Fetches the named resource from this bundle. The path should be
|
|
* specified as a relative, platform independent path (forward
|
|
* slashes). For example <code>sounds/scream.au</code>.
|
|
*
|
|
* @param path the path to the resource in this jar file.
|
|
*
|
|
* @return an input stream from which the resource can be loaded or
|
|
* null if no such resource exists.
|
|
*
|
|
* @exception IOException thrown if an error occurs locating the
|
|
* resource in the jar file.
|
|
*/
|
|
public InputStream getResource (String path)
|
|
throws IOException
|
|
{
|
|
// unpack our resources into a temp directory so that we can load
|
|
// them quickly and the file system can cache them sensibly
|
|
File rfile = getResourceFile(path);
|
|
return (rfile == null) ? null : new FileInputStream(rfile);
|
|
}
|
|
|
|
/**
|
|
* Returns a file from which the specified resource can be loaded.
|
|
* This method will unpack the resource into a temporary directory and
|
|
* return a reference to that file.
|
|
*
|
|
* @param path the path to the resource in this jar file.
|
|
*
|
|
* @return a file from which the resource can be loaded or null if no
|
|
* such resource exists.
|
|
*/
|
|
public File getResourceFile (String path)
|
|
throws IOException
|
|
{
|
|
resolveJarFile();
|
|
|
|
// compute the path to our temporary file
|
|
String tpath = StringUtil.md5hex(_source.getPath() + "%" + path);
|
|
File tfile = new File(_tmpdir, 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
|
|
JarEntry entry = _jarSource.getJarEntry(path);
|
|
if (entry == null) {
|
|
return null;
|
|
}
|
|
|
|
// System.out.println("Unpacking " + path);
|
|
// copy the resource into the temporary file
|
|
BufferedOutputStream fout =
|
|
new BufferedOutputStream(new FileOutputStream(tfile));
|
|
InputStream jin = _jarSource.getInputStream(entry);
|
|
StreamUtils.pipe(jin, fout);
|
|
jin.close();
|
|
fout.close();
|
|
|
|
return tfile;
|
|
}
|
|
|
|
/**
|
|
* Returns true if this resource bundle contains the resource with the
|
|
* specified path. This avoids actually loading the resource, in the
|
|
* event that the caller only cares to know that the resource exists.
|
|
*/
|
|
public boolean containsResource (String path)
|
|
{
|
|
try {
|
|
resolveJarFile();
|
|
return (_jarSource.getJarEntry(path) != null);
|
|
} catch (IOException ioe) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Returns a string representation of this resource bundle.
|
|
*/
|
|
public String toString ()
|
|
{
|
|
try {
|
|
resolveJarFile();
|
|
return "[path=" + _jarSource.getName() +
|
|
", entries=" + _jarSource.size() + "]";
|
|
} catch (IOException ioe) {
|
|
return "[file=" + _source + ", ioe=" + ioe + "]";
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Creates the internal jar file reference if we've not already got
|
|
* it; we do this lazily so as to avoid any jar- or zip-file-related
|
|
* antics until and unless doing so is required, and because the
|
|
* resource manager would like to be able to create bundles before the
|
|
* associated files have been fully downloaded.
|
|
*/
|
|
protected void resolveJarFile ()
|
|
throws IOException
|
|
{
|
|
try {
|
|
if (_jarSource == null) {
|
|
_jarSource = new JarFile(_source);
|
|
}
|
|
|
|
} catch (IOException ioe) {
|
|
throw new NestableIOException(
|
|
"Failed to resolve resource bundle jar file " +
|
|
"[file=" + _source + "]", ioe);
|
|
}
|
|
}
|
|
|
|
/** The file from which we construct our jar file. */
|
|
protected File _source;
|
|
|
|
/** The last modified time of our source jar file. */
|
|
protected long _sourceLastMod;
|
|
|
|
/** The directory into which our contents are unpacked, if we are
|
|
* unpacked. */
|
|
protected File _unpackDir;
|
|
|
|
/** The jar file from which we load resources. */
|
|
protected JarFile _jarSource;
|
|
|
|
/** A directory in which we temporarily unpack our resource files. */
|
|
protected static File _tmpdir;
|
|
|
|
static {
|
|
String tmpdir = System.getProperty("java.io.tmpdir");
|
|
if (tmpdir == null) {
|
|
Log.info("No system defined temp directory. Faking it.");
|
|
tmpdir = System.getProperty("user.dir");
|
|
}
|
|
_tmpdir = new File(tmpdir, ".narcache");
|
|
if (!_tmpdir.exists()) {
|
|
Log.info("Creating narya temp cache directory '" + _tmpdir + "'.");
|
|
_tmpdir.mkdir();
|
|
}
|
|
}
|
|
}
|