diff --git a/src/main/java/com/samskivert/mustache/BasicCollector.java b/src/main/java/com/samskivert/mustache/BasicCollector.java index a444cee..e5e1bcb 100644 --- a/src/main/java/com/samskivert/mustache/BasicCollector.java +++ b/src/main/java/com/samskivert/mustache/BasicCollector.java @@ -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 Map createFetcherCache () { + return Collections.synchronizedMap(new HashMap()); + } + protected static final Mustache.VariableFetcher MAP_FETCHER = new Mustache.VariableFetcher() { public Object get (Object ctx, String name) throws Exception { return ((Map)ctx).get(name); diff --git a/src/main/java/com/samskivert/mustache/DefaultCollector.java b/src/main/java/com/samskivert/mustache/DefaultCollector.java index 7b02197..1f0b276 100644 --- a/src/main/java/com/samskivert/mustache/DefaultCollector.java +++ b/src/main/java/com/samskivert/mustache/DefaultCollector.java @@ -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 Map createFetcherCache () { + return new ConcurrentHashMap(); + } + + 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); diff --git a/src/main/java/com/samskivert/mustache/Mustache.java b/src/main/java/com/samskivert/mustache/Mustache.java index 52d6df1..c581804 100644 --- a/src/main/java/com/samskivert/mustache/Mustache.java +++ b/src/main/java/com/samskivert/mustache/Mustache.java @@ -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 Mustache 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. */ + Map createFetcherCache (); } /** diff --git a/src/main/java/com/samskivert/mustache/Template.java b/src/main/java/com/samskivert/mustache/Template.java index ea0f629..1df18af 100644 --- a/src/main/java/com/samskivert/mustache/Template.java +++ b/src/main/java/com/samskivert/mustache/Template.java @@ -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 _fcache = - new HashMap(); + protected final Map _fcache; protected static class Context {