com.threerings.resource
Class ResourceManager

java.lang.Object
  extended by com.threerings.resource.ResourceManager

public class ResourceManager
extends Object

The resource manager is responsible for maintaining a repository of resources that are synchronized with a remote source. This is accomplished in the form of sets of jar files (resource bundles) that contain resources and that are updated from a remote resource repository via HTTP. These resource bundles are organized into resource sets. A resource set contains one or more resource bundles and is defined much like a classpath.

The resource manager can load resources from the default resource set, and can make available named resource sets to entities that wish to do their own resource loading. If the resource manager fails to locate a resource in the default resource set, it falls back to loading the resource via the classloader (which will search the classpath).

Applications that wish to make use of resource sets and their associated bundles must call initBundles(java.lang.String, java.lang.String, com.threerings.resource.ResourceManager.InitObserver) after constructing the resource manager, providing the path to a resource definition file which describes these resource sets. The definition file will be loaded and the resource bundles defined within will be loaded relative to the resource directory. The bundles will be cached in the user's home directory and only reloaded when the source resources have been updated. The resource definition file looks something like the following:

 resource.set.default = sets/misc/config.jar: \
                        sets/misc/icons.jar
 resource.set.tiles = sets/tiles/ground.jar: \
                      sets/tiles/objects.jar: \
                      /global/resources/tiles/ground.jar: \
                      /global/resources/tiles/objects.jar
 resource.set.sounds = sets/sounds/sfx.jar: \
                       sets/sounds/music.jar: \
                       /global/resources/sounds/sfx.jar: \
                       /global/resources/sounds/music.jar
 

All resource set definitions are prefixed with resource.set. and all text following that string is considered to be the name of the resource set. The resource set named default is the default resource set and is the one that is searched for resources is a call to getResource(String).

When a resource is loaded from a resource set, the set is searched in the order that entries are specified in the definition.


Nested Class Summary
static class ResourceManager.AWTInitObserver
          An adapter that wraps an ResourceManager.InitObserver and routes all method invocations to the AWT thread.
static interface ResourceManager.InitObserver
          Provides facilities for notifying an observer of the resource unpacking process.
static interface ResourceManager.ModificationObserver
          Notifies observers of modifications to resources (as indicated by a change to their File.lastModified() property).
protected static class ResourceManager.ObservedResource
          Contains the state of an observed file resource.
protected static class ResourceManager.ResourceModifiedOp
          An observer op that calls ResourceManager.ModificationObserver.resourceModified(java.lang.String, long).
protected static class ResourceManager.Unpacker
          Used to unpack bundles on a separate thread.
 
Field Summary
protected  ResourceBundle[] _default
          Our default resource set.
protected  ClassLoader _loader
          The classloader we use for classpath-based resource loading.
protected  String _localePrefix
          Locale to search for locale-specific resources, if any.
protected  String _networkRootPath
          The root path we give to network bundles for all resources they're interested in.
protected  HashMap<String,ResourceManager.ObservedResource> _observed
          Maps resource paths to observed file resources.
protected  File _rdir
          The directory that contains our resource bundles.
protected static ResourceManager.ResourceModifiedOp _resourceModifiedOp
          A reusable instance of ResourceManager.ResourceModifiedOp.
protected  String _rootPath
          The prefix we prepend to resource paths before attempting to load them from the classpath.
protected  HashMap<String,ResourceBundle[]> _sets
          A table of our resource sets.
protected  boolean _unpack
          Whether or not to unpack our resource bundles.
protected static String DEFAULT_RESOURCE_SET
          The name of the default resource set.
protected static String FILE_SET_TYPE
          Resource set type indicating the resources should be loaded from local files.
protected static String NETWORK_SET_TYPE
          Resource set type indicating the resources should be loaded over the network.
protected static String RESOURCE_SET_PREFIX
          The prefix of configuration entries that describe a resource set.
protected static String RESOURCE_SET_TYPE_PREFIX
          The prefix of configuration entries that describe a resource set.
 
Constructor Summary
ResourceManager(String resourceRoot)
          Constructs a resource manager which will load resources via the classloader, prepending resourceRoot to their path.
ResourceManager(String resourceRoot, ClassLoader loader)
          Creates a resource manager with the specified class loader via which to load classes.
ResourceManager(String resourceRoot, String networkResourceRoot)
          Creates a resource manager with a root path to resources over the network.
ResourceManager(String fileResourceRoot, String networkResourceRoot, ClassLoader loader)
          Creates a resource manager with a root path to resources over the network and the specified class loader via which to load classes.
 
Method Summary
 void activateResourceProtocol()
          Registers a protocol handler with URL to handle resource: URLs.
 void addModificationObserver(String path, ResourceManager.ModificationObserver obs)
          Adds a modification observer for the specified resource.
 boolean checkBundle(String path)
          Checks to see if the specified bundle exists, is unpacked and is ready to be used.
 void checkForModifications()
          Checks all observed resources for changes to their File.lastModified() properties, notifying their listeners if the files have been modified since the last call to this method.
protected  FileResourceBundle createFileResourceBundle(File source, boolean delay, boolean unpack)
          Creates an appropriate bundle for fetching resources from files.
protected  ResourceBundle createNetworkResourceBundle(String root, String path, Set<String> rsrcList)
          Creates an appropriate bundle for fetching resources from the network.
protected  ResourceBundle createResourceBundle(String setType, String path, List<ResourceBundle> dlist)
          Creates a ResourceBundle based on the supplied definition information.
 ClassLoader getClassLoader()
          Returns the class loader being used to load resources if/when there are no resource bundles from which to load them.
 BufferedImage getImageResource(String path)
          Fetches and decodes the specified resource into a BufferedImage.
 BufferedImage getImageResource(String rset, String path)
          Fetches and decodes the specified resource into a BufferedImage.
protected  InputStream getInputStreamFromClasspath(String fullyQualifiedPath)
          Returns an InputStream from this manager's classloader for the given path.
 String getLocalePrefix()
          Returns where we're currently looking for locale-specific resources.
protected static int getNumericJavaVersion(String verstr)
          Converts the java version string to a more comparable numeric version number.
 InputStream getResource(String path)
          Fetches a resource from the local repository.
 InputStream getResource(String rset, String path)
          Returns an input stream from which the requested resource can be loaded.
 File getResourceFile(String path)
          Given a path relative to the resource directory, the path is properly jimmied (assuming we always use /) and combined with the resource directory to yield a File object that can be used to access the resource.
 HashSet<String> getResourceList()
          If we have a full list of the resources available, we return it.
 String getResourcePath(File file)
          Given a file within the resource directory, returns a resource path that can be passed to getResourceFile(java.lang.String) to locate the resource.
 ResourceBundle[] getResourceSet(String name)
          Returns a reference to the resource set with the specified name, or null if no set exists with that name.
 void initBundles(String resourceDir, String configPath, ResourceManager.InitObserver initObs)
          Initializes the bundle sets to be made available by this resource manager.
 void initResourceDir(String resourceDir)
          (Re)initializes the directory to search for resource files.
protected  Properties loadConfig(String configPath)
          Loads the configuration properties for our resource sets.
protected static BufferedImage loadImage(File file, boolean useFastIO)
          Loads an image from the supplied file.
protected static BufferedImage loadImage(InputStream iis)
          Loads an image from the supplied input stream.
static BufferedImage loadImage(InputStream iis, boolean useFastIO)
          Loads an image from the given input stream.
 void removeModificationObserver(String path, ResourceManager.ModificationObserver obs)
          Removes a modification observer from the list maintained for the specified resource.
 void resolveBundle(String path, ResultListener<FileResourceBundle> listener)
          Resolve the specified bundle (the bundle file must already exist in the appropriate place on the file system) and return it on the specified result listener.
protected  void resolveResourceSet(String setName, String definition, String setType, List<ResourceBundle> dlist)
          Loads up a resource set based on the supplied definition information.
 void setClassLoader(ClassLoader loader)
          Configures the class loader this manager should use to load resources if/when there are no bundles from which to load them.
 void setLocalePrefix(String prefix)
          Set where we should look for locale-specific resources.
 void setUnpackResources(boolean unpackResources)
          Configures whether we unpack our resource bundles or not.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

_loader

protected ClassLoader _loader
The classloader we use for classpath-based resource loading.


_rdir

protected File _rdir
The directory that contains our resource bundles.


_rootPath

protected String _rootPath
The prefix we prepend to resource paths before attempting to load them from the classpath.


_networkRootPath

protected String _networkRootPath
The root path we give to network bundles for all resources they're interested in.


_unpack

protected boolean _unpack
Whether or not to unpack our resource bundles.


_default

protected ResourceBundle[] _default
Our default resource set.


_sets

protected HashMap<String,ResourceBundle[]> _sets
A table of our resource sets.


_localePrefix

protected String _localePrefix
Locale to search for locale-specific resources, if any.


_observed

protected HashMap<String,ResourceManager.ObservedResource> _observed
Maps resource paths to observed file resources.


_resourceModifiedOp

protected static ResourceManager.ResourceModifiedOp _resourceModifiedOp
A reusable instance of ResourceManager.ResourceModifiedOp.


RESOURCE_SET_PREFIX

protected static final String RESOURCE_SET_PREFIX
The prefix of configuration entries that describe a resource set.

See Also:
Constant Field Values

RESOURCE_SET_TYPE_PREFIX

protected static final String RESOURCE_SET_TYPE_PREFIX
The prefix of configuration entries that describe a resource set.

See Also:
Constant Field Values

DEFAULT_RESOURCE_SET

protected static final String DEFAULT_RESOURCE_SET
The name of the default resource set.

See Also:
Constant Field Values

FILE_SET_TYPE

protected static final String FILE_SET_TYPE
Resource set type indicating the resources should be loaded from local files.

See Also:
Constant Field Values

NETWORK_SET_TYPE

protected static final String NETWORK_SET_TYPE
Resource set type indicating the resources should be loaded over the network.

See Also:
Constant Field Values
Constructor Detail

ResourceManager

public ResourceManager(String resourceRoot)
Constructs a resource manager which will load resources via the classloader, prepending resourceRoot to their path.

Parameters:
resourceRoot - the path to prepend to resource paths prior to attempting to load them via the classloader. When resources are bundled into the default resource bundle, they don't need this prefix, but if they're to be loaded from the classpath, it's likely that they'll live in some sort of resources directory to isolate them from the rest of the files in the classpath. This is not a platform dependent path (forward slash is always used to separate path elements).

ResourceManager

public ResourceManager(String resourceRoot,
                       ClassLoader loader)
Creates a resource manager with the specified class loader via which to load classes. See ResourceManager(String) for further documentation.


ResourceManager

public ResourceManager(String resourceRoot,
                       String networkResourceRoot)
Creates a resource manager with a root path to resources over the network. See ResourceManager(String) for further documentation.


ResourceManager

public ResourceManager(String fileResourceRoot,
                       String networkResourceRoot,
                       ClassLoader loader)
Creates a resource manager with a root path to resources over the network and the specified class loader via which to load classes. See ResourceManager(String) for further documentation.

Method Detail

activateResourceProtocol

public void activateResourceProtocol()
Registers a protocol handler with URL to handle resource: URLs. The URLs take the form:
resource://bundle_name/resource_path
Resources from the default bundle can be loaded via:
resource:///resource_path


getLocalePrefix

public String getLocalePrefix()
Returns where we're currently looking for locale-specific resources.


setLocalePrefix

public void setLocalePrefix(String prefix)
Set where we should look for locale-specific resources.


setUnpackResources

public void setUnpackResources(boolean unpackResources)
Configures whether we unpack our resource bundles or not. This must be called before initBundles(java.lang.String, java.lang.String, com.threerings.resource.ResourceManager.InitObserver). One can also pass the -Dno_unpack_resources=true system property to disable resource unpacking.


initBundles

public void initBundles(String resourceDir,
                        String configPath,
                        ResourceManager.InitObserver initObs)
                 throws IOException
Initializes the bundle sets to be made available by this resource manager. Applications that wish to make use of resource bundles should call this method after constructing the resource manager.

Parameters:
resourceDir - the base directory to which the paths in the supplied configuration file are relative. If this is null, the system property resource_dir will be used, if available.
configPath - the path (relative to the resource dir) of the resource definition file.
initObs - a bundle initialization observer to notify of unpacking progress and success or failure, or null if the caller doesn't care to be informed; note that in the latter case, the calling thread will block until bundle unpacking is complete.
Throws:
IOException - thrown if we are unable to read our resource manager configuration.

initResourceDir

public void initResourceDir(String resourceDir)
(Re)initializes the directory to search for resource files.

Parameters:
resourceDir - the directory path, or null to set the resource dir to the value of the resource_dir system property.

getResourceFile

public File getResourceFile(String path)
Given a path relative to the resource directory, the path is properly jimmied (assuming we always use /) and combined with the resource directory to yield a File object that can be used to access the resource.

Returns:
a file referencing the specified resource or null if the resource manager was never configured with a resource directory.

getResourcePath

public String getResourcePath(File file)
Given a file within the resource directory, returns a resource path that can be passed to getResourceFile(java.lang.String) to locate the resource.

Returns:
a path referencing the specified resource or null if either the resource manager was never configured with a resource directory or the file is not contained within the resource directory.

checkBundle

public boolean checkBundle(String path)
Checks to see if the specified bundle exists, is unpacked and is ready to be used.


resolveBundle

public void resolveBundle(String path,
                          ResultListener<FileResourceBundle> listener)
Resolve the specified bundle (the bundle file must already exist in the appropriate place on the file system) and return it on the specified result listener. Note that the result listener may be notified before this method returns on the caller's thread if the bundle is already resolved, or it may be notified on a brand new thread if the bundle requires unpacking.


getClassLoader

public ClassLoader getClassLoader()
Returns the class loader being used to load resources if/when there are no resource bundles from which to load them.


setClassLoader

public void setClassLoader(ClassLoader loader)
Configures the class loader this manager should use to load resources if/when there are no bundles from which to load them.


getResource

public InputStream getResource(String path)
                        throws IOException
Fetches a resource from the local repository.

Parameters:
path - the path to the resource (ie. "config/miso.properties"). This should not begin with a slash.
Throws:
IOException - thrown if a problem occurs locating or reading the resource.

getImageResource

public BufferedImage getImageResource(String path)
                               throws IOException
Fetches and decodes the specified resource into a BufferedImage.

Throws:
FileNotFoundException - thrown if the resource could not be located in any of the bundles in the specified set, or if the specified set does not exist.
IOException - thrown if a problem occurs locating or reading the resource.

getResource

public InputStream getResource(String rset,
                               String path)
                        throws IOException
Returns an input stream from which the requested resource can be loaded. Note: this performs a linear search of all of the bundles in the set and returns the first resource found with the specified path, thus it is not extremely efficient and will behave unexpectedly if you use the same paths in different resource bundles.

Throws:
FileNotFoundException - thrown if the resource could not be located in any of the bundles in the specified set, or if the specified set does not exist.
IOException - thrown if a problem occurs locating or reading the resource.

getImageResource

public BufferedImage getImageResource(String rset,
                                      String path)
                               throws IOException
Fetches and decodes the specified resource into a BufferedImage.

Throws:
FileNotFoundException - thrown if the resource could not be located in any of the bundles in the specified set, or if the specified set does not exist.
IOException - thrown if a problem occurs locating or reading the resource.

getResourceSet

public ResourceBundle[] getResourceSet(String name)
Returns a reference to the resource set with the specified name, or null if no set exists with that name. Services that wish to load their own resources can allow the resource manager to load up a resource set for them, from which they can easily load their resources.


addModificationObserver

public void addModificationObserver(String path,
                                    ResourceManager.ModificationObserver obs)
Adds a modification observer for the specified resource. Note that only a weak reference to the observer will be retained, and thus this will not prevent the observer from being garbage-collected.


removeModificationObserver

public void removeModificationObserver(String path,
                                       ResourceManager.ModificationObserver obs)
Removes a modification observer from the list maintained for the specified resource.


checkForModifications

public void checkForModifications()
Checks all observed resources for changes to their File.lastModified() properties, notifying their listeners if the files have been modified since the last call to this method.


loadConfig

protected Properties loadConfig(String configPath)
                         throws IOException
Loads the configuration properties for our resource sets.

Throws:
IOException

getResourceList

public HashSet<String> getResourceList()
If we have a full list of the resources available, we return it. A return value of null means that we do not know what's available and we'll have to try all possibilities. This is fine for most applications.


resolveResourceSet

protected void resolveResourceSet(String setName,
                                  String definition,
                                  String setType,
                                  List<ResourceBundle> dlist)
Loads up a resource set based on the supplied definition information.


createResourceBundle

protected ResourceBundle createResourceBundle(String setType,
                                              String path,
                                              List<ResourceBundle> dlist)
Creates a ResourceBundle based on the supplied definition information.


createFileResourceBundle

protected FileResourceBundle createFileResourceBundle(File source,
                                                      boolean delay,
                                                      boolean unpack)
Creates an appropriate bundle for fetching resources from files.


createNetworkResourceBundle

protected ResourceBundle createNetworkResourceBundle(String root,
                                                     String path,
                                                     Set<String> rsrcList)
Creates an appropriate bundle for fetching resources from the network.


loadImage

protected static BufferedImage loadImage(File file,
                                         boolean useFastIO)
                                  throws IOException
Loads an image from the supplied file. Supports FastImageIO files and formats supported by ImageIO and will load the appropriate one based on the useFastIO param.

Throws:
IOException

getInputStreamFromClasspath

protected InputStream getInputStreamFromClasspath(String fullyQualifiedPath)
Returns an InputStream from this manager's classloader for the given path.


loadImage

public static BufferedImage loadImage(InputStream iis,
                                      boolean useFastIO)
                               throws IOException
Loads an image from the given input stream. Supports formats supported by ImageIO as well as FastImageIO based on the useFastIO param.

Throws:
IOException

loadImage

protected static BufferedImage loadImage(InputStream iis)
                                  throws IOException
Loads an image from the supplied input stream. Supports formats supported by ImageIO but not FastImageIO.

Throws:
IOException

getNumericJavaVersion

protected static int getNumericJavaVersion(String verstr)
Converts the java version string to a more comparable numeric version number.