Repository: incubator-freemarker Updated Branches: refs/heads/2.3-gae 277956d94 -> c253e33d2
Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Some code cleanup. Project: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/commit/c253e33d Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/c253e33d Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/c253e33d Branch: refs/heads/2.3-gae Commit: c253e33d22db9365e3c134f59110bf20c0872670 Parents: 277956d Author: ddekany <[email protected]> Authored: Sun Dec 4 17:55:56 2016 +0100 Committer: ddekany <[email protected]> Committed: Sun Dec 4 21:31:17 2016 +0100 ---------------------------------------------------------------------- .../java/freemarker/ext/beans/BeanModel.java | 88 +++++++++----------- .../freemarker/ext/beans/ClassIntrospector.java | 1 - .../template/AdapterTemplateModel.java | 2 +- .../freemarker/template/SimpleSequence.java | 2 +- 4 files changed, 42 insertions(+), 51 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/ext/beans/BeanModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/ext/beans/BeanModel.java b/src/main/java/freemarker/ext/beans/BeanModel.java index ba3dc62..24f8590 100644 --- a/src/main/java/freemarker/ext/beans/BeanModel.java +++ b/src/main/java/freemarker/ext/beans/BeanModel.java @@ -80,10 +80,9 @@ implements } }; - // Cached template models that implement member properties and methods for this - // instance. Keys are FeatureDescriptor instances (from classCache values), - // values are either ReflectionMethodModels/ReflectionScalarModels - private HashMap memberMap; + // I've tried to use a volatile ConcurrentHashMap field instead of HashMap + synchronized(this), but oddly it was + // a bit slower, at least on Java 8 u66. + private HashMap<Object, TemplateModel> memberCache; /** * Creates a new model that wraps the specified object. Note that there are @@ -192,7 +191,7 @@ implements } } - private void logNoSuchKey(String key, Map keyMap) { + private void logNoSuchKey(String key, Map<?, ?> keyMap) { LOG.debug("Key " + StringUtil.jQuoteNoXSS(key) + " was not found on instance of " + object.getClass().getName() + ". Introspection information for " + "the class is: " + keyMap); @@ -207,71 +206,64 @@ implements } private TemplateModel invokeThroughDescriptor(Object desc, Map<Object, Object> classInfo) - throws IllegalAccessException, - InvocationTargetException, - TemplateModelException { - // See if this particular instance has a cached implementation - // for the requested feature descriptor - TemplateModel member; + throws IllegalAccessException, InvocationTargetException, TemplateModelException { + // See if this particular instance has a cached implementation for the requested feature descriptor + TemplateModel cachedModel; synchronized (this) { - if (memberMap != null) { - member = (TemplateModel) memberMap.get(desc); - } else { - member = null; - } + cachedModel = memberCache != null ? memberCache.get(desc) : null; } - if (member != null) - return member; + if (cachedModel != null) { + return cachedModel; + } - TemplateModel retval = UNKNOWN; + TemplateModel resultModel = UNKNOWN; if (desc instanceof IndexedPropertyDescriptor) { - Method readMethod = - ((IndexedPropertyDescriptor) desc).getIndexedReadMethod(); - retval = member = + Method readMethod = ((IndexedPropertyDescriptor) desc).getIndexedReadMethod(); + resultModel = cachedModel = new SimpleMethodModel(object, readMethod, ClassIntrospector.getArgTypes(classInfo, readMethod), wrapper); } else if (desc instanceof PropertyDescriptor) { PropertyDescriptor pd = (PropertyDescriptor) desc; - retval = wrapper.invokeMethod(object, pd.getReadMethod(), null); - // (member == null) condition remains, as we don't cache these + resultModel = wrapper.invokeMethod(object, pd.getReadMethod(), null); + // cachedModel remains null, as we don't cache these } else if (desc instanceof Field) { - retval = wrapper.wrap(((Field) desc).get(object)); - // (member == null) condition remains, as we don't cache these + resultModel = wrapper.wrap(((Field) desc).get(object)); + // cachedModel remains null, as we don't cache these } else if (desc instanceof Method) { Method method = (Method) desc; - retval = member = new SimpleMethodModel(object, method, - ClassIntrospector.getArgTypes(classInfo, method), wrapper); + resultModel = cachedModel = new SimpleMethodModel( + object, method, ClassIntrospector.getArgTypes(classInfo, method), wrapper); } else if (desc instanceof OverloadedMethods) { - retval = member = - new OverloadedMethodsModel(object, (OverloadedMethods) desc, wrapper); + resultModel = cachedModel = new OverloadedMethodsModel( + object, (OverloadedMethods) desc, wrapper); } - // If new cacheable member was created, cache it - if (member != null) { + // If new cachedModel was created, cache it + if (cachedModel != null) { synchronized (this) { - if (memberMap == null) { - memberMap = new HashMap(); + if (memberCache == null) { + memberCache = new HashMap<Object, TemplateModel>(); } - memberMap.put(desc, member); + memberCache.put(desc, cachedModel); } } - return retval; + return resultModel; } void clearMemberCache() { synchronized (this) { - memberMap = null; + memberCache = null; } } - protected TemplateModel invokeGenericGet(Map keyMap, Class clazz, String key) - throws IllegalAccessException, - InvocationTargetException, + protected TemplateModel invokeGenericGet(Map/*<Object, Object>*/ classInfo, Class<?> clazz, String key) + throws IllegalAccessException, InvocationTargetException, TemplateModelException { - Method genericGet = (Method) keyMap.get(ClassIntrospector.GENERIC_GET_KEY); - if (genericGet == null) + Method genericGet = (Method) classInfo.get(ClassIntrospector.GENERIC_GET_KEY); + if (genericGet == null) { return UNKNOWN; + } return wrapper.invokeMethod(object, genericGet, new Object[] { key }); } @@ -295,13 +287,13 @@ implements return ((String) object).length() == 0; } if (object instanceof Collection) { - return ((Collection) object).isEmpty(); + return ((Collection<?>) object).isEmpty(); } if (object instanceof Iterator && wrapper.is2324Bugfixed()) { - return !((Iterator) object).hasNext(); + return !((Iterator<?>) object).hasNext(); } if (object instanceof Map) { - return ((Map) object).isEmpty(); + return ((Map<?,?>) object).isEmpty(); } return object == null || Boolean.FALSE.equals(object); } @@ -310,7 +302,7 @@ implements * Returns the same as {@link #getWrappedObject()}; to ensure that, this method will be final starting from 2.4. * This behavior of {@link BeanModel} is assumed by some FreeMarker code. */ - public Object getAdaptedObject(Class hint) { + public Object getAdaptedObject(Class<?> hint) { return object; // return getWrappedObject(); starting from 2.4 } @@ -327,7 +319,7 @@ implements } public TemplateCollectionModel values() throws TemplateModelException { - List values = new ArrayList(size()); + List<Object> values = new ArrayList<Object>(size()); TemplateModelIterator it = keys().iterator(); while (it.hasNext()) { String key = ((TemplateScalarModel) it.next()).getAsString(); @@ -363,7 +355,7 @@ implements * interface. Subclasses that override <tt>invokeGenericGet</tt> to * provide additional hash keys should also override this method. */ - protected Set keySet() { + protected Set/*<Object>*/ keySet() { return wrapper.getClassIntrospector().keySet(object.getClass()); } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/ext/beans/ClassIntrospector.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/ext/beans/ClassIntrospector.java b/src/main/java/freemarker/ext/beans/ClassIntrospector.java index c852636..7c08e49 100644 --- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java +++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java @@ -28,7 +28,6 @@ import java.beans.PropertyDescriptor; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; -import java.lang.reflect.AccessibleObject; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/template/AdapterTemplateModel.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/AdapterTemplateModel.java b/src/main/java/freemarker/template/AdapterTemplateModel.java index fb76d22..2f32cae 100644 --- a/src/main/java/freemarker/template/AdapterTemplateModel.java +++ b/src/main/java/freemarker/template/AdapterTemplateModel.java @@ -45,5 +45,5 @@ public interface AdapterTemplateModel extends TemplateModel { * @return the underlying object, or its value accommodated for the hint * class. */ - public Object getAdaptedObject(Class hint); + public Object getAdaptedObject(Class<?> hint); } http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/c253e33d/src/main/java/freemarker/template/SimpleSequence.java ---------------------------------------------------------------------- diff --git a/src/main/java/freemarker/template/SimpleSequence.java b/src/main/java/freemarker/template/SimpleSequence.java index 0cc9411..e0ea945 100644 --- a/src/main/java/freemarker/template/SimpleSequence.java +++ b/src/main/java/freemarker/template/SimpleSequence.java @@ -161,7 +161,7 @@ public class SimpleSequence extends WrappingTemplateModel implements TemplateSeq * using {@link DefaultListAdapter} instead. * * @param collection - * The collection containing the initial items of this sequence. A shalow copy of this collection is made + * The collection containing the initial items of the sequence. A shallow copy of this collection is made * immediately for internal use (thus, later modification on the parameter collection won't be visible in * the resulting sequence). The items however, will be only wrapped with the {@link ObjectWrapper} * lazily, when first needed.
