package org.nocket.gen.resources;
import java.util.Locale;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import org.apache.wicket.core.util.resource.UrlResourceStream;
import org.apache.wicket.core.util.resource.locator.IResourceNameIterator;
import org.apache.wicket.core.util.resource.locator.IResourceStreamLocator;
import org.apache.wicket.request.resource.ResourceReference.Key;
import org.apache.wicket.util.lang.Args;
import org.apache.wicket.util.resource.FileResourceStream;
import org.apache.wicket.util.resource.IResourceStream;
/**
* This resource stream locator is mainly a copy-paste-construct from Wicket's
* CachingResourceStreamLocator. As usual, Wicket defines a lot of stuff final,
* package-visible, and private, so that we can't simply derive from
* CachingResourceStreamLocator.<br>
* The only difference is a function which allows to remove a stream reference
* in order to re-locate it after having created the resource on the fly.
*
* @author less02
*/
public class DMDCachingResourceStreamLocator implements IResourceStreamLocator {
private final ConcurrentMap<Key, DMDResourceStreamReferenceI> cache;
private final IResourceStreamLocator delegate;
/**
* Construct.
*
* @param resourceStreamLocator
* the delegate
*/
public DMDCachingResourceStreamLocator(final IResourceStreamLocator resourceStreamLocator) {
Args.notNull(resourceStreamLocator, "resourceStreamLocator");
delegate = resourceStreamLocator;
cache = new ConcurrentHashMap<Key, DMDResourceStreamReferenceI>();
}
/**
* {@inheritDoc}
*
* Checks for {@link DMDResourceStreamReferenceI} in the cache and returns
* <code>null</code> if the result is
* {@link DMDNullResourceStreamReference#INSTANCE}, or
* {@link FileResourceStream} / {@link UrlResourceStream} if there is an
* entry in the cache. Otherwise asks the delegate to find one and puts it
* in the cache.
*/
public IResourceStream locate(Class<?> clazz, String path) {
Key key = new Key(clazz.getName(), path, null, null, null);
DMDResourceStreamReferenceI resourceStreamReference = cache.get(key);
final IResourceStream result;
if (resourceStreamReference == null) {
result = delegate.locate(clazz, path);
updateCache(key, result);
} else {
result = resourceStreamReference.getReference();
}
return result;
}
/**
* This is the only new thing in here which is not present in Wicket's
* CachingResourceStreamLocator class. The key is explicitely removed from
* the cache if already present, before calling
* {@link #locate(Class, String)} to force a re-allocation of the resource.
*/
public IResourceStream relocate(Class<?> clazz, String path) {
Key key = new Key(clazz.getName(), path, null, null, null);
cache.remove(key);
return locate(clazz, path);
}
private void updateCache(Key key, IResourceStream stream) {
if (null == stream) {
cache.put(key, DMDNullResourceStreamReference.INSTANCE);
} else if (stream instanceof FileResourceStream) {
FileResourceStream fileResourceStream = (FileResourceStream) stream;
cache.put(key, new DMDFileResourceStreamReference(fileResourceStream));
} else if (stream instanceof UrlResourceStream) {
UrlResourceStream urlResourceStream = (UrlResourceStream) stream;
cache.put(key, new DMDUrlResourceStreamReference(urlResourceStream));
}
}
public IResourceStream locate(Class<?> scope, String path, String style, String variation,
Locale locale, String extension, boolean strict) {
Key key = new Key(scope.getName(), path, locale, style, variation);
DMDResourceStreamReferenceI resourceStreamReference = cache.get(key);
final IResourceStream result;
if (resourceStreamReference == null) {
result = delegate.locate(scope, path, style, variation, locale, extension, strict);
updateCache(key, result);
} else {
result = resourceStreamReference.getReference();
}
return result;
}
public IResourceNameIterator newResourceNameIterator(String path, Locale locale, String style,
String variation, String extension, boolean strict) {
return delegate.newResourceNameIterator(path, locale, style, variation, extension, strict);
}
public void drop(Class<?> scope, String... keyStrings) {
for (String keyString : keyStrings) {
Key key = new Key(scope.getName(), keyString, null, null, null);
cache.remove(key);
}
}
}