Use ConcurrentHashMap to cache fetchers, on platforms that support it.
This commit is contained in:
@@ -3,6 +3,8 @@
|
||||
|
||||
package com.samskivert.mustache;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -11,6 +13,7 @@ import java.util.Map;
|
||||
*/
|
||||
public class BasicCollector implements Mustache.Collector
|
||||
{
|
||||
@Override
|
||||
public Iterator<?> toIterator (final Object value) {
|
||||
if (value instanceof Iterable<?>) {
|
||||
return ((Iterable<?>)value).iterator();
|
||||
@@ -21,8 +24,8 @@ public class BasicCollector implements Mustache.Collector
|
||||
return null;
|
||||
}
|
||||
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name)
|
||||
{
|
||||
@Override
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
|
||||
// support both .name and this.name to fetch members
|
||||
if (name == Template.DOT_NAME || name == Template.THIS_NAME) {
|
||||
return THIS_FETCHER;
|
||||
@@ -35,6 +38,11 @@ public class BasicCollector implements Mustache.Collector
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <K,V> Map<K,V> createFetcherCache () {
|
||||
return Collections.synchronizedMap(new HashMap<K,V>());
|
||||
}
|
||||
|
||||
protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() {
|
||||
public Object get (Object ctx, String name) throws Exception {
|
||||
return ((Map<?,?>)ctx).get(name);
|
||||
|
||||
@@ -9,6 +9,8 @@ import java.lang.reflect.Method;
|
||||
|
||||
import java.util.AbstractList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* The default collector used by JMustache.
|
||||
@@ -34,8 +36,7 @@ public class DefaultCollector extends BasicCollector
|
||||
}
|
||||
|
||||
@Override
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name)
|
||||
{
|
||||
public Mustache.VariableFetcher createFetcher (Object ctx, String name) {
|
||||
Mustache.VariableFetcher fetcher = super.createFetcher(ctx, name);
|
||||
if (fetcher != null) return fetcher;
|
||||
|
||||
@@ -61,8 +62,12 @@ public class DefaultCollector extends BasicCollector
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Method getMethod (Class<?> clazz, String name)
|
||||
{
|
||||
@Override
|
||||
public <K,V> Map<K,V> createFetcherCache () {
|
||||
return new ConcurrentHashMap<K,V>();
|
||||
}
|
||||
|
||||
protected Method getMethod (Class<?> clazz, String name) {
|
||||
Method m;
|
||||
try {
|
||||
m = clazz.getDeclaredMethod(name);
|
||||
@@ -95,8 +100,7 @@ public class DefaultCollector extends BasicCollector
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Field getField (Class<?> clazz, String name)
|
||||
{
|
||||
protected Field getField (Class<?> clazz, String name) {
|
||||
Field f;
|
||||
try {
|
||||
f = clazz.getDeclaredField(name);
|
||||
|
||||
@@ -11,6 +11,7 @@ import java.io.Writer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Provides <a href="http://mustache.github.com/">Mustache</a> templating services.
|
||||
@@ -160,6 +161,11 @@ public class Mustache
|
||||
* never be null. The fetcher will be cached and reused for future contexts for which
|
||||
* {@code octx.getClass().equals(nctx.getClass()}. */
|
||||
VariableFetcher createFetcher (Object ctx, String name);
|
||||
|
||||
/** Creates a map to be used to cache {@link VariableFetcher} instances. The GWT-compatible
|
||||
* collector returns a HashMap here, but the reflection based fetcher (which only works on
|
||||
* the JVM and Android, returns a concurrent hashmap. */
|
||||
<K,V> Map<K,V> createFetcherCache ();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -73,6 +73,7 @@ public class Template
|
||||
{
|
||||
_segs = segs;
|
||||
_compiler = compiler;
|
||||
_fcache = _compiler.collector.createFetcherCache();
|
||||
}
|
||||
|
||||
protected void executeSegs (Context ctx, Writer out) throws MustacheException
|
||||
@@ -190,10 +191,7 @@ public class Template
|
||||
}
|
||||
|
||||
Key key = new Key(data.getClass(), name);
|
||||
Mustache.VariableFetcher fetcher;
|
||||
synchronized (_fcache) {
|
||||
fetcher = _fcache.get(key);
|
||||
}
|
||||
Mustache.VariableFetcher fetcher = _fcache.get(key);
|
||||
if (fetcher != null) {
|
||||
try {
|
||||
return fetcher.get(data, name);
|
||||
@@ -213,9 +211,7 @@ public class Template
|
||||
|
||||
try {
|
||||
Object value = fetcher.get(data, name);
|
||||
synchronized (_fcache) {
|
||||
_fcache.put(key, fetcher);
|
||||
}
|
||||
_fcache.put(key, fetcher);
|
||||
return value;
|
||||
} catch (Exception e) {
|
||||
throw new MustacheException(
|
||||
@@ -236,8 +232,7 @@ public class Template
|
||||
|
||||
protected final Segment[] _segs;
|
||||
protected final Mustache.Compiler _compiler;
|
||||
protected final Map<Key, Mustache.VariableFetcher> _fcache =
|
||||
new HashMap<Key, Mustache.VariableFetcher>();
|
||||
protected final Map<Key, Mustache.VariableFetcher> _fcache;
|
||||
|
||||
protected static class Context
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user