Added methods to observe resource files for changes to their
last-modified timestamps (by manual polling). git-svn-id: svn+ssh://src.earth.threerings.net/nenya/trunk@650 ed5b42cb-e716-0410-a449-f6a68f950b19
This commit is contained in:
@@ -34,7 +34,9 @@ import java.util.ArrayList;
|
|||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -47,10 +49,14 @@ import javax.imageio.ImageIO;
|
|||||||
import javax.imageio.stream.ImageInputStream;
|
import javax.imageio.stream.ImageInputStream;
|
||||||
import javax.imageio.stream.MemoryCacheImageInputStream;
|
import javax.imageio.stream.MemoryCacheImageInputStream;
|
||||||
|
|
||||||
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
import com.samskivert.io.StreamUtil;
|
import com.samskivert.io.StreamUtil;
|
||||||
import com.samskivert.net.PathUtil;
|
import com.samskivert.net.PathUtil;
|
||||||
|
import com.samskivert.util.ObserverList;
|
||||||
import com.samskivert.util.ResultListener;
|
import com.samskivert.util.ResultListener;
|
||||||
import com.samskivert.util.StringUtil;
|
import com.samskivert.util.StringUtil;
|
||||||
|
import com.samskivert.util.WeakObserverList;
|
||||||
|
|
||||||
import static com.threerings.resource.Log.log;
|
import static com.threerings.resource.Log.log;
|
||||||
|
|
||||||
@@ -141,6 +147,21 @@ public class ResourceManager
|
|||||||
protected InitObserver _obs;
|
protected InitObserver _obs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies observers of modifications to resources (as indicated by a change to their
|
||||||
|
* {@link File#lastModified} property).
|
||||||
|
*/
|
||||||
|
public interface ModificationObserver
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Notes that a resource has been modified.
|
||||||
|
*
|
||||||
|
* @param path the path of the resource.
|
||||||
|
* @param lastModified the resource's new timestamp.
|
||||||
|
*/
|
||||||
|
public void resourceModified (String path, long lastModified);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a resource manager which will load resources via the classloader, prepending
|
* Constructs a resource manager which will load resources via the classloader, prepending
|
||||||
* <code>resourceRoot</code> to their path.
|
* <code>resourceRoot</code> to their path.
|
||||||
@@ -702,6 +723,52 @@ public class ResourceManager
|
|||||||
return _sets.get(name);
|
return _sets.get(name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
public void addModificationObserver (String path, ModificationObserver obs)
|
||||||
|
{
|
||||||
|
ObservedResource resource = _observed.get(path);
|
||||||
|
if (resource == null) {
|
||||||
|
File file = getResourceFile(path);
|
||||||
|
if (file == null) {
|
||||||
|
return; // only resource files will ever be modified
|
||||||
|
}
|
||||||
|
_observed.put(path, resource = new ObservedResource(file));
|
||||||
|
}
|
||||||
|
resource.observers.add(obs);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a modification observer from the list maintained for the specified resource.
|
||||||
|
*/
|
||||||
|
public void removeModificationObserver (String path, ModificationObserver obs)
|
||||||
|
{
|
||||||
|
ObservedResource resource = _observed.get(path);
|
||||||
|
if (resource != null) {
|
||||||
|
resource.observers.remove(obs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks all observed resources for changes to their {@link File#lastModified} properties,
|
||||||
|
* notifying their listeners if the files have been modified since the last call to this
|
||||||
|
* method.
|
||||||
|
*/
|
||||||
|
public void checkForModifications ()
|
||||||
|
{
|
||||||
|
for (Iterator<Map.Entry<String, ObservedResource>> it = _observed.entrySet().iterator();
|
||||||
|
it.hasNext(); ) {
|
||||||
|
Map.Entry<String, ObservedResource> entry = it.next();
|
||||||
|
ObservedResource resource = entry.getValue();
|
||||||
|
if (resource.checkForModification(entry.getKey())) {
|
||||||
|
it.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the configuration properties for our resource sets.
|
* Loads the configuration properties for our resource sets.
|
||||||
*/
|
*/
|
||||||
@@ -914,6 +981,65 @@ public class ResourceManager
|
|||||||
protected InitObserver _obs;
|
protected InitObserver _obs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** Contains the state of an observed file resource. */
|
||||||
|
protected static class ObservedResource
|
||||||
|
{
|
||||||
|
/** The observers listening for modifications to this resource. */
|
||||||
|
public WeakObserverList<ModificationObserver> observers =
|
||||||
|
WeakObserverList.newFastUnsafe();
|
||||||
|
|
||||||
|
public ObservedResource (File file)
|
||||||
|
{
|
||||||
|
_file = file;
|
||||||
|
_lastModified = file.lastModified();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks for a modification to the observed resource, notifying the observers if
|
||||||
|
* one is detected.
|
||||||
|
*
|
||||||
|
* @param path the path of the resource (to forward to observers).
|
||||||
|
* @return <code>true</code> if the list of observers is empty and the resource should be
|
||||||
|
* removed from the observed list, <code>false</code> if it should remain in the list.
|
||||||
|
*/
|
||||||
|
public boolean checkForModification (String path)
|
||||||
|
{
|
||||||
|
long newLastModified = _file.lastModified();
|
||||||
|
if (newLastModified > _lastModified) {
|
||||||
|
_resourceModifiedOp.init(path, _lastModified = newLastModified);
|
||||||
|
observers.apply(_resourceModifiedOp);
|
||||||
|
} else {
|
||||||
|
// TODO: uncomment when we get this method into samskivert
|
||||||
|
// observers.prune();
|
||||||
|
}
|
||||||
|
return observers.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected File _file;
|
||||||
|
protected long _lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** An observer op that calls {@link ModificationObserver#resourceModified}. */
|
||||||
|
protected static class ResourceModifiedOp
|
||||||
|
implements ObserverList.ObserverOp<ModificationObserver>
|
||||||
|
{
|
||||||
|
public void init (String path, long lastModified)
|
||||||
|
{
|
||||||
|
_path = path;
|
||||||
|
_lastModified = lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
|
// documentation inherited from interface ObserverOp
|
||||||
|
public boolean apply (ModificationObserver obs)
|
||||||
|
{
|
||||||
|
obs.resourceModified(_path, _lastModified);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String _path;
|
||||||
|
protected long _lastModified;
|
||||||
|
}
|
||||||
|
|
||||||
/** The classloader we use for classpath-based resource loading. */
|
/** The classloader we use for classpath-based resource loading. */
|
||||||
protected ClassLoader _loader;
|
protected ClassLoader _loader;
|
||||||
|
|
||||||
@@ -934,11 +1060,17 @@ public class ResourceManager
|
|||||||
protected ResourceBundle[] _default = new ResourceBundle[0];
|
protected ResourceBundle[] _default = new ResourceBundle[0];
|
||||||
|
|
||||||
/** A table of our resource sets. */
|
/** A table of our resource sets. */
|
||||||
protected HashMap<String, ResourceBundle[]> _sets = new HashMap<String, ResourceBundle[]>();
|
protected HashMap<String, ResourceBundle[]> _sets = Maps.newHashMap();
|
||||||
|
|
||||||
/** Locale to search for locale-specific resources, if any. */
|
/** Locale to search for locale-specific resources, if any. */
|
||||||
protected String _localePrefix = null;
|
protected String _localePrefix = null;
|
||||||
|
|
||||||
|
/** Maps resource paths to observed file resources. */
|
||||||
|
protected HashMap<String, ObservedResource> _observed = Maps.newHashMap();
|
||||||
|
|
||||||
|
/** A reusable instance of {@link ResourceModifiedOp}. */
|
||||||
|
protected static ResourceModifiedOp _resourceModifiedOp = new ResourceModifiedOp();
|
||||||
|
|
||||||
/** The prefix of configuration entries that describe a resource set. */
|
/** The prefix of configuration entries that describe a resource set. */
|
||||||
protected static final String RESOURCE_SET_PREFIX = "resource.set.";
|
protected static final String RESOURCE_SET_PREFIX = "resource.set.";
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user