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