You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@freemarker.apache.org by dd...@apache.org on 2016/12/04 12:19:48 UTC

incubator-freemarker git commit: Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Replaceding freemarker.ext.util.IdentityHashMap usages with java.util.IdentityHashMap. Some internal naming cleanup.

Repository: incubator-freemarker
Updated Branches:
  refs/heads/2.3-gae 5be880de5 -> 277956d94


Utilizing Java 5 generics at some places where it doesn't break backward compatibility. Replaceding freemarker.ext.util.IdentityHashMap usages with java.util.IdentityHashMap. Some internal naming 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/277956d9
Tree: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/tree/277956d9
Diff: http://git-wip-us.apache.org/repos/asf/incubator-freemarker/diff/277956d9

Branch: refs/heads/2.3-gae
Commit: 277956d94a5e5972f47f24188ea1c48b13d6b70b
Parents: 5be880d
Author: ddekany <dd...@apache.org>
Authored: Sat Dec 3 19:29:35 2016 +0100
Committer: ddekany <dd...@apache.org>
Committed: Sun Dec 4 13:19:27 2016 +0100

----------------------------------------------------------------------
 src/main/java/freemarker/core/NewBI.java        |   8 +-
 .../debug/impl/RmiDebuggedEnvironmentImpl.java  |   2 +-
 .../freemarker/ext/beans/ArgumentTypes.java     |  75 +++++----
 .../java/freemarker/ext/beans/BeanModel.java    |   6 +-
 .../java/freemarker/ext/beans/BeansWrapper.java |  87 ++++++-----
 .../ext/beans/BeansWrapperBuilder.java          |  17 +-
 .../freemarker/ext/beans/ClassIntrospector.java | 156 ++++++++++---------
 .../java/freemarker/ext/beans/_BeansAPI.java    |  70 +++++----
 .../freemarker/ext/util/IdentityHashMap.java    |   9 +-
 .../java/freemarker/ext/util/ModelCache.java    |  19 ++-
 .../template/DefaultObjectWrapper.java          |  23 +--
 .../template/DefaultObjectWrapperBuilder.java   |  18 ++-
 .../template/ObjectWrapperAndUnwrapper.java     |   2 +-
 .../java/freemarker/template/_TemplateAPI.java  |   2 -
 14 files changed, 264 insertions(+), 230 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/core/NewBI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/core/NewBI.java b/src/main/java/freemarker/core/NewBI.java
index c7842de..eddd823 100644
--- a/src/main/java/freemarker/core/NewBI.java
+++ b/src/main/java/freemarker/core/NewBI.java
@@ -21,6 +21,7 @@ package freemarker.core;
 
 import java.util.List;
 
+import freemarker.ext.beans.BeanModel;
 import freemarker.ext.beans.BeansWrapper;
 import freemarker.template.ObjectWrapper;
 import freemarker.template.Template;
@@ -35,8 +36,7 @@ import freemarker.template.TemplateModelException;
  */
 class NewBI extends BuiltIn {
     
-    static final Class BEAN_MODEL_CLASS = freemarker.ext.beans.BeanModel.class;
-    static Class JYTHON_MODEL_CLASS;
+    static Class<?> JYTHON_MODEL_CLASS;
     static {
         try {
             JYTHON_MODEL_CLASS = Class.forName("freemarker.ext.jython.JythonModel");
@@ -53,7 +53,7 @@ class NewBI extends BuiltIn {
 
     class ConstructorFunction implements TemplateMethodModelEx {
 
-        private final Class cl;
+        private final Class<?> cl;
         private final Environment env;
         
         public ConstructorFunction(String classname, Environment env, Template template) throws TemplateException {
@@ -63,7 +63,7 @@ class NewBI extends BuiltIn {
                 throw new _MiscTemplateException(NewBI.this, env,
                         "Class ", cl.getName(), " does not implement freemarker.template.TemplateModel");
             }
-            if (BEAN_MODEL_CLASS.isAssignableFrom(cl)) {
+            if (BeanModel.class.isAssignableFrom(cl)) {
                 throw new _MiscTemplateException(NewBI.this, env,
                         "Bean Models cannot be instantiated using the ?", key, " built-in");
             }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java b/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
index 8bb1b3c..ec6e5a4 100644
--- a/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
+++ b/src/main/java/freemarker/debug/impl/RmiDebuggedEnvironmentImpl.java
@@ -27,6 +27,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
@@ -38,7 +39,6 @@ import freemarker.core.Configurable;
 import freemarker.core.Environment;
 import freemarker.debug.DebugModel;
 import freemarker.debug.DebuggedEnvironment;
-import freemarker.ext.util.IdentityHashMap;
 import freemarker.template.Configuration;
 import freemarker.template.SimpleCollection;
 import freemarker.template.SimpleScalar;

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/ArgumentTypes.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/ArgumentTypes.java b/src/main/java/freemarker/ext/beans/ArgumentTypes.java
index 11f1b77..e383259 100644
--- a/src/main/java/freemarker/ext/beans/ArgumentTypes.java
+++ b/src/main/java/freemarker/ext/beans/ArgumentTypes.java
@@ -54,7 +54,7 @@ final class ArgumentTypes {
     /**
      * The types of the arguments; for varags this contains the exploded list (not the array). 
      */
-    private final Class[] types;
+    private final Class<?>[] types;
     
     private final boolean bugfixed;
     
@@ -65,7 +65,7 @@ final class ArgumentTypes {
      */
     ArgumentTypes(Object[] args, boolean bugfixed) {
         int ln = args.length;
-        Class[] typesTmp = new Class[ln];
+        Class<?>[] typesTmp = new Class[ln];
         for (int i = 0; i < ln; ++i) {
             Object arg = args[i];
             typesTmp[i] = arg == null
@@ -109,22 +109,21 @@ final class ArgumentTypes {
      *         {@link EmptyCallableMemberDescriptor#AMBIGUOUS_METHOD}. 
      */
     MaybeEmptyCallableMemberDescriptor getMostSpecific(
-            List/*<ReflectionCallableMemberDescriptor>*/ memberDescs, boolean varArg) {
-        LinkedList/*<ReflectionCallableMemberDescriptor>*/ applicables = getApplicables(memberDescs, varArg);
+            List<ReflectionCallableMemberDescriptor> memberDescs, boolean varArg) {
+        LinkedList<CallableMemberDescriptor> applicables = getApplicables(memberDescs, varArg);
         if (applicables.isEmpty()) {
             return EmptyCallableMemberDescriptor.NO_SUCH_METHOD;
         }
         if (applicables.size() == 1) {
-            return (CallableMemberDescriptor) applicables.getFirst();
+            return applicables.getFirst();
         }
         
-        LinkedList/*<CallableMemberDescriptor>*/ maximals = new LinkedList();
-        for (Iterator applicablesIter = applicables.iterator(); applicablesIter.hasNext(); ) {
-            CallableMemberDescriptor applicable = (CallableMemberDescriptor) applicablesIter.next();
+        LinkedList<CallableMemberDescriptor> maximals = new LinkedList<CallableMemberDescriptor>();
+        for (CallableMemberDescriptor applicable : applicables) {
             boolean lessSpecific = false;
-            for (Iterator maximalsIter = maximals.iterator(); 
+            for (Iterator<CallableMemberDescriptor> maximalsIter = maximals.iterator(); 
                 maximalsIter.hasNext(); ) {
-                CallableMemberDescriptor maximal = (CallableMemberDescriptor) maximalsIter.next();
+                CallableMemberDescriptor maximal = maximalsIter.next();
                 final int cmpRes = compareParameterListPreferability(
                         applicable.getParamTypes(), maximal.getParamTypes(), varArg); 
                 if (cmpRes > 0) {
@@ -140,7 +139,7 @@ final class ArgumentTypes {
         if (maximals.size() > 1) {
             return EmptyCallableMemberDescriptor.AMBIGUOUS_METHOD;
         }
-        return (CallableMemberDescriptor) maximals.getFirst();
+        return maximals.getFirst();
     }
 
     /**
@@ -174,7 +173,7 @@ final class ArgumentTypes {
      * @return More than 0 if the first parameter list is preferred, less then 0 if the other is preferred,
      *        0 if there's no decision 
      */
-    int compareParameterListPreferability(Class[] paramTypes1, Class[] paramTypes2, boolean varArg) {
+    int compareParameterListPreferability(Class<?>[] paramTypes1, Class<?>[] paramTypes2, boolean varArg) {
         final int argTypesLen = types.length; 
         final int paramTypes1Len = paramTypes1.length;
         final int paramTypes2Len = paramTypes2.length;
@@ -191,19 +190,19 @@ final class ArgumentTypes {
             int paramList2VeryStrongWinCnt = 0;
             int firstWinerParamList = 0;
             for (int i = 0; i < argTypesLen; i++) {
-                final Class paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
-                final Class paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
+                final Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
+                final Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
                 
                 final int winerParam;  // 1 => paramType1; -1 => paramType2; 0 => draw
                 if (paramType1 == paramType2) {
                     winerParam = 0;
                 } else {
-                    final Class argType = types[i];
+                    final Class<?> argType = types[i];
                     final boolean argIsNum = Number.class.isAssignableFrom(argType);
                     
                     final int numConvPrice1;
                     if (argIsNum && ClassUtil.isNumerical(paramType1)) {
-                        final Class nonPrimParamType1 = paramType1.isPrimitive()
+                        final Class<?> nonPrimParamType1 = paramType1.isPrimitive()
                                 ? ClassUtil.primitiveClassToBoxingClass(paramType1) : paramType1; 
                         numConvPrice1 = OverloadedNumberUtil.getArgumentConversionPrice(argType, nonPrimParamType1);
                     } else {
@@ -215,7 +214,7 @@ final class ArgumentTypes {
                     
                     final int numConvPrice2;
                     if (argIsNum && ClassUtil.isNumerical(paramType2)) {
-                        final Class nonPrimParamType2 = paramType2.isPrimitive()
+                        final Class<?> nonPrimParamType2 = paramType2.isPrimitive()
                                 ? ClassUtil.primitiveClassToBoxingClass(paramType2) : paramType2; 
                         numConvPrice2 = OverloadedNumberUtil.getArgumentConversionPrice(argType, nonPrimParamType2);
                     } else {
@@ -357,8 +356,8 @@ final class ArgumentTypes {
                         // index of the varargs parameter, like if we had a single varargs argument. However, this
                         // time we don't have an argument type, so we can only decide based on type specificity:
                         if (argTypesLen == paramTypes1Len - 1) {
-                            Class paramType1 = getParamType(paramTypes1, paramTypes1Len, argTypesLen, true);
-                            Class paramType2 = getParamType(paramTypes2, paramTypes2Len, argTypesLen, true);
+                            Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, argTypesLen, true);
+                            Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, argTypesLen, true);
                             if (ClassUtil.isNumerical(paramType1) && ClassUtil.isNumerical(paramType2)) {
                                 int r = OverloadedNumberUtil.compareNumberTypeSpecificity(paramType1, paramType2);
                                 if (r != 0) return r;
@@ -380,8 +379,8 @@ final class ArgumentTypes {
             boolean paramTypes1HasAMoreSpecific = false;
             boolean paramTypes2HasAMoreSpecific = false;
             for (int i = 0; i < paramTypes1Len; ++i) {
-                Class paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
-                Class paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
+                Class<?> paramType1 = getParamType(paramTypes1, paramTypes1Len, i, varArg);
+                Class<?> paramType2 = getParamType(paramTypes2, paramTypes2Len, i, varArg);
                 if (paramType1 != paramType2) {
                     paramTypes1HasAMoreSpecific = 
                         paramTypes1HasAMoreSpecific
@@ -408,12 +407,13 @@ final class ArgumentTypes {
      * @return Less-than-0, 0, or more-than-0 depending on which side is more specific. The absolute value is 1 if
      *     the difference is only in primitive VS non-primitive, more otherwise.
      */
-    private int compareParameterListPreferability_cmpTypeSpecificty(final Class paramType1, final Class paramType2) {
+    private int compareParameterListPreferability_cmpTypeSpecificty(
+            final Class<?> paramType1, final Class<?> paramType2) {
         // The more specific (smaller) type wins.
         
-        final Class nonPrimParamType1 = paramType1.isPrimitive()
+        final Class<?> nonPrimParamType1 = paramType1.isPrimitive()
                 ? ClassUtil.primitiveClassToBoxingClass(paramType1) : paramType1; 
-        final Class nonPrimParamType2 = paramType2.isPrimitive()
+        final Class<?> nonPrimParamType2 = paramType2.isPrimitive()
                 ? ClassUtil.primitiveClassToBoxingClass(paramType2) : paramType2;
                 
         if (nonPrimParamType1 == nonPrimParamType2) {
@@ -441,7 +441,7 @@ final class ArgumentTypes {
         }
     }
 
-    private static Class getParamType(Class[] paramTypes, int paramTypesLen, int i, boolean varArg) {
+    private static Class<?> getParamType(Class<?>[] paramTypes, int paramTypesLen, int i, boolean varArg) {
         return varArg && i >= paramTypesLen - 1
                 ? paramTypes[paramTypesLen - 1].getComponentType()
                 : paramTypes[i];
@@ -451,11 +451,10 @@ final class ArgumentTypes {
      * Returns all methods that are applicable to actual
      * parameter types represented by this ArgumentTypes object.
      */
-    LinkedList/*<ReflectionCallableMemberDescriptor>*/ getApplicables(
-            List/*<ReflectionCallableMemberDescriptor>*/ memberDescs, boolean varArg) {
-        LinkedList applicables = new LinkedList();
-        for (Iterator it = memberDescs.iterator(); it.hasNext(); ) {
-            ReflectionCallableMemberDescriptor memberDesc = (ReflectionCallableMemberDescriptor) it.next();
+    LinkedList<CallableMemberDescriptor> getApplicables(
+            List<ReflectionCallableMemberDescriptor> memberDescs, boolean varArg) {
+        LinkedList<CallableMemberDescriptor> applicables = new LinkedList<CallableMemberDescriptor>();
+        for (ReflectionCallableMemberDescriptor memberDesc : memberDescs) {
             int difficulty = isApplicable(memberDesc, varArg);
             if (difficulty != CONVERSION_DIFFICULTY_IMPOSSIBLE) {
                 if (difficulty == CONVERSION_DIFFICULTY_REFLECTION) {
@@ -478,7 +477,7 @@ final class ArgumentTypes {
      * @return One of the <tt>CONVERSION_DIFFICULTY_...</tt> constants.
      */
     private int isApplicable(ReflectionCallableMemberDescriptor memberDesc, boolean varArg) {
-        final Class[] paramTypes = memberDesc.getParamTypes(); 
+        final Class<?>[] paramTypes = memberDesc.getParamTypes(); 
         final int cl = types.length;
         final int fl = paramTypes.length - (varArg ? 1 : 0);
         if (varArg) {
@@ -502,7 +501,7 @@ final class ArgumentTypes {
             }
         }
         if (varArg) {
-            Class varArgParamType = paramTypes[fl].getComponentType();
+            Class<?> varArgParamType = paramTypes[fl].getComponentType();
             for (int i = fl; i < cl; ++i) {
                 int difficulty = isMethodInvocationConvertible(varArgParamType, types[i]); 
                 if (difficulty == CONVERSION_DIFFICULTY_IMPOSSIBLE) {
@@ -530,12 +529,12 @@ final class ArgumentTypes {
      * 
      * @return One of the <tt>CONVERSION_DIFFICULTY_...</tt> constants.
      */
-    private int isMethodInvocationConvertible(final Class formal, final Class actual) {
+    private int isMethodInvocationConvertible(final Class<?> formal, final Class<?> actual) {
         // Check for identity or widening reference conversion
         if (formal.isAssignableFrom(actual) && actual != CharacterOrString.class) {
             return CONVERSION_DIFFICULTY_REFLECTION;
         } else if (bugfixed) {
-            final Class formalNP;
+            final Class<?> formalNP;
             if (formal.isPrimitive()) {
                 if (actual == Null.class) {
                     return CONVERSION_DIFFICULTY_IMPOSSIBLE;
@@ -684,7 +683,7 @@ final class ArgumentTypes {
         }
 
         @Override
-        Class[] getParamTypes() {
+        Class<?>[] getParamTypes() {
             return callableMemberDesc.getParamTypes();
         }
         
@@ -694,10 +693,10 @@ final class ArgumentTypes {
         }
 
         private void convertArgsToReflectionCompatible(BeansWrapper bw, Object[] args) throws TemplateModelException {
-            Class[] paramTypes = callableMemberDesc.getParamTypes();
+            Class<?>[] paramTypes = callableMemberDesc.getParamTypes();
             int ln = paramTypes.length;
             for (int i = 0; i < ln; i++) {
-                Class paramType = paramTypes[i];
+                Class<?> paramType = paramTypes[i];
                 final Object arg = args[i];
                 if (arg == null) continue;
                 
@@ -712,7 +711,7 @@ final class ArgumentTypes {
                 // parameter, and that an array argument is applicable to a List parameter, so we end up with this
                 // situation.
                 if (paramType.isArray() && arg instanceof List) {
-                   args[i] = bw.listToArray((List) arg, paramType, null);
+                   args[i] = bw.listToArray((List<?>) arg, paramType, null);
                 }
                 if (arg.getClass().isArray() && paramType.isAssignableFrom(List.class)) {
                     args[i] = bw.arrayToList(arg);

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/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 794a66b..ba3dc62 100644
--- a/src/main/java/freemarker/ext/beans/BeanModel.java
+++ b/src/main/java/freemarker/ext/beans/BeanModel.java
@@ -143,8 +143,8 @@ implements
      */
     public TemplateModel get(String key)
         throws TemplateModelException {
-        Class clazz = object.getClass();
-        Map classInfo = wrapper.getClassIntrospector().get(clazz);
+        Class<?> clazz = object.getClass();
+        Map<Object, Object> classInfo = wrapper.getClassIntrospector().get(clazz);
         TemplateModel retval = null;
         
         try {
@@ -206,7 +206,7 @@ implements
         return wrapper.getClassIntrospector().get(object.getClass()).get(ClassIntrospector.GENERIC_GET_KEY) != null;
     }
     
-    private TemplateModel invokeThroughDescriptor(Object desc, Map classInfo)
+    private TemplateModel invokeThroughDescriptor(Object desc, Map<Object, Object> classInfo)
         throws IllegalAccessException,
         InvocationTargetException,
         TemplateModelException {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/BeansWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeansWrapper.java b/src/main/java/freemarker/ext/beans/BeansWrapper.java
index cf2d0c4..8b51238 100644
--- a/src/main/java/freemarker/ext/beans/BeansWrapper.java
+++ b/src/main/java/freemarker/ext/beans/BeansWrapper.java
@@ -31,6 +31,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
+import java.util.IdentityHashMap;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
@@ -41,7 +42,6 @@ import freemarker.core.BugException;
 import freemarker.core._DelayedFTLTypeDescription;
 import freemarker.core._DelayedShortClassName;
 import freemarker.core._TemplateModelException;
-import freemarker.ext.util.IdentityHashMap;
 import freemarker.ext.util.ModelCache;
 import freemarker.ext.util.ModelFactory;
 import freemarker.ext.util.WrapperTemplateModel;
@@ -94,9 +94,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     @Deprecated
     static final Object CAN_NOT_UNWRAP = ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS;
     
-    private static final Class ITERABLE_CLASS;
+    private static final Class<?> ITERABLE_CLASS;
     static {
-        Class iterable;
+        Class<?> iterable;
         try {
             iterable = Class.forName("java.lang.Iterable");
         } catch (ClassNotFoundException e) {
@@ -106,7 +106,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         ITERABLE_CLASS = iterable;
     }
     
-    private static final Constructor ENUMS_MODEL_CTOR = enumsModelCtor();
+    private static final Constructor<?> ENUMS_MODEL_CTOR = enumsModelCtor();
     
     /**
      * At this level of exposure, all methods and properties of the
@@ -296,7 +296,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     protected BeansWrapper(BeansWrapperConfiguration bwConf, boolean writeProtected, boolean finalizeConstruction) {
         // Backward-compatibility hack for "finetuneMethodAppearance" overrides to work:
         if (bwConf.getMethodAppearanceFineTuner() == null) {
-            Class thisClass = this.getClass();
+            Class<?> thisClass = this.getClass();
             boolean overridden = false;
             boolean testFailed = false;
             try {
@@ -306,7 +306,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                         && thisClass != SimpleObjectWrapper.class) {
                     try {
                         thisClass.getDeclaredMethod("finetuneMethodAppearance",
-                                new Class[] { Class.class, Method.class, MethodAppearanceDecision.class });
+                                new Class<?>[] { Class.class, Method.class, MethodAppearanceDecision.class });
                         overridden = true;
                     } catch (NoSuchMethodException e) {
                         thisClass = thisClass.getSuperclass();
@@ -912,17 +912,17 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
 
     private static final ModelFactory ITERATOR_FACTORY = new ModelFactory() {
         public TemplateModel create(Object object, ObjectWrapper wrapper) {
-            return new IteratorModel((Iterator) object, (BeansWrapper) wrapper); 
+            return new IteratorModel((Iterator<?>) object, (BeansWrapper) wrapper); 
         }
     };
 
     private static final ModelFactory ENUMERATION_FACTORY = new ModelFactory() {
         public TemplateModel create(Object object, ObjectWrapper wrapper) {
-            return new EnumerationModel((Enumeration) object, (BeansWrapper) wrapper); 
+            return new EnumerationModel((Enumeration<?>) object, (BeansWrapper) wrapper); 
         }
     };
 
-    protected ModelFactory getModelFactory(Class clazz) {
+    protected ModelFactory getModelFactory(Class<?> clazz) {
         if (Map.class.isAssignableFrom(clazz)) {
             return simpleMapWrapper ? SimpleMapModel.FACTORY : MapModel.FACTORY;
         }
@@ -983,7 +983,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * 
      * @see #tryUnwrapTo(TemplateModel, Class)
      */
-    public Object unwrap(TemplateModel model, Class targetClass) 
+    public Object unwrap(TemplateModel model, Class<?> targetClass) 
     throws TemplateModelException {
         final Object obj = tryUnwrapTo(model, targetClass);
         if (obj == ObjectWrapperAndUnwrapper.CANT_UNWRAP_TO_TARGET_CLASS) {
@@ -996,7 +996,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * @since 2.3.22
      */
-    public Object tryUnwrapTo(TemplateModel model, Class targetClass) throws TemplateModelException {
+    public Object tryUnwrapTo(TemplateModel model, Class<?> targetClass) throws TemplateModelException {
         return tryUnwrapTo(model, targetClass, 0);
     }
     
@@ -1007,7 +1007,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      *            {@link #is2321Bugfixed()} is {@code false}.
      * @return {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} or the unwrapped object.
      */
-    Object tryUnwrapTo(TemplateModel model, Class targetClass, int typeFlags) 
+    Object tryUnwrapTo(TemplateModel model, Class<?> targetClass, int typeFlags) 
     throws TemplateModelException {
         Object res = tryUnwrapTo(model, targetClass, typeFlags, null);
         if ((typeFlags & TypeFlags.WIDENED_NUMERICAL_UNWRAPPING_HINT) != 0
@@ -1021,7 +1021,8 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * See {@try #tryUnwrap(TemplateModel, Class, int, boolean)}.
      */
-    private Object tryUnwrapTo(final TemplateModel model, Class targetClass, final int typeFlags, final Map recursionStops) 
+    private Object tryUnwrapTo(final TemplateModel model, Class<?> targetClass, final int typeFlags,
+            final Map<Object, Object> recursionStops) 
     throws TemplateModelException {
         if (model == null || model == nullModel) {
             return null;
@@ -1249,7 +1250,8 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      *            {@link ObjectWrapperAndUnwrapper#CANT_UNWRAP_TO_TARGET_CLASS} instead of throwing a
      *            {@link TemplateModelException}.
      */
-    Object unwrapSequenceToArray(TemplateSequenceModel seq, Class arrayClass, boolean tryOnly, Map recursionStops)
+    Object unwrapSequenceToArray(
+            TemplateSequenceModel seq, Class<?> arrayClass, boolean tryOnly, Map<Object, Object> recursionStops)
             throws TemplateModelException {
         if (recursionStops != null) {
             Object retval = recursionStops.get(seq);
@@ -1257,9 +1259,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 return retval;
             }
         } else {
-            recursionStops = new IdentityHashMap();
+            recursionStops = new IdentityHashMap<Object, Object>();
         }
-        Class componentType = arrayClass.getComponentType();
+        Class<?> componentType = arrayClass.getComponentType();
         Object array = Array.newInstance(componentType, seq.size());
         recursionStops.put(seq, array);
         try {
@@ -1287,7 +1289,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         return array;
     }
     
-    Object listToArray(List list, Class arrayClass, Map recursionStops)
+    Object listToArray(List<?> list, Class<?> arrayClass, Map<Object, Object> recursionStops)
             throws TemplateModelException {
         if (list instanceof SequenceAdapter) {
             return unwrapSequenceToArray(
@@ -1302,9 +1304,9 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 return retval;
             }
         } else {
-            recursionStops = new IdentityHashMap();
+            recursionStops = new IdentityHashMap<Object, Object>();
         }
-        Class componentType = arrayClass.getComponentType();
+        Class<?> componentType = arrayClass.getComponentType();
         Object array = Array.newInstance(componentType, list.size());
         recursionStops.put(list, array);
         try {
@@ -1312,7 +1314,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             boolean isComponentTypeNumerical = false;  // will be filled on demand
             boolean isComponentTypeList = false;  // will be filled on demand
             int i = 0;
-            for (Iterator it = list.iterator(); it.hasNext(); ) {
+            for (Iterator<?> it = list.iterator(); it.hasNext(); ) {
                 Object listItem = it.next();
                 if (listItem != null && !componentType.isInstance(listItem)) {
                     // Type conversion is needed. If we can't do it, we just let it fail at Array.set later.
@@ -1333,7 +1335,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                         }
                     } else if (componentType.isArray()) {
                         if (listItem instanceof List) {
-                            listItem = listToArray((List) listItem, componentType, recursionStops);
+                            listItem = listToArray((List<?>) listItem, componentType, recursionStops);
                         } else if (listItem instanceof TemplateSequenceModel) {
                             listItem = unwrapSequenceToArray((TemplateSequenceModel) listItem, componentType, false, recursionStops);
                         }
@@ -1361,7 +1363,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     /**
      * @param array Must be an array (of either a reference or primitive type)
      */
-    List arrayToList(Object array) throws TemplateModelException {
+    List<?> arrayToList(Object array) throws TemplateModelException {
         if (array instanceof Object[]) {
             // Array of any non-primitive type.
             // Note that an array of non-primitive type is always instanceof Object[].
@@ -1378,7 +1380,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * @param n Non-{@code null}
      * @return {@code null} if the conversion has failed.
      */
-    static Number forceUnwrappedNumberToType(final Number n, final Class targetType, final boolean bugfixed) {
+    static Number forceUnwrappedNumberToType(final Number n, final Class<?> targetType, final boolean bugfixed) {
         // We try to order the conditions by decreasing probability.
         if (targetType == n.getClass()) {
             return n;
@@ -1516,7 +1518,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * @param arguments The list of {@link TemplateModel}-s to pass to the constructor after unwrapping them
      * @return The instance created; it's not wrapped into {@link TemplateModel}.
      */
-    public Object newInstance(Class clazz, List/*<TemplateModel>*/ arguments)
+    public Object newInstance(Class<?> clazz, List/*<? extends TemplateModel>*/ arguments)
     throws TemplateModelException {
         try {
             Object ctors = classIntrospector.get(clazz).get(ClassIntrospector.CONSTRUCTORS_KEY);
@@ -1524,11 +1526,11 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                 throw new TemplateModelException("Class " + clazz.getName() + 
                         " has no public constructors.");
             }
-            Constructor ctor = null;
+            Constructor<?> ctor = null;
             Object[] objargs;
             if (ctors instanceof SimpleMethod) {
                 SimpleMethod sm = (SimpleMethod) ctors;
-                ctor = (Constructor) sm.getMember();
+                ctor = (Constructor<?>) sm.getMember();
                 objargs = sm.unwrapArguments(arguments, this);
                 try {
                     return ctor.newInstance(objargs);
@@ -1565,7 +1567,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      * 
      * @since 2.3.20
      */
-    public void removeFromClassIntrospectionCache(Class clazz) {
+    public void removeFromClassIntrospectionCache(Class<?> clazz) {
         classIntrospector.remove(clazz);
     }
     
@@ -1596,7 +1598,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      */
     @Deprecated
     protected void finetuneMethodAppearance(
-            Class clazz, Method m, MethodAppearanceDecision decision) {
+            Class<?> clazz, Method m, MethodAppearanceDecision decision) {
         // left everything on its default; do nothing
     }
     
@@ -1606,7 +1608,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
      */
     // Unused?
     public static void coerceBigDecimals(AccessibleObject callable, Object[] args) {
-        Class[] formalTypes = null;
+        Class<?>[] formalTypes = null;
         for (int i = 0; i < args.length; ++i) {
             Object arg = args[i];
             if (arg instanceof BigDecimal) {
@@ -1614,7 +1616,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
                     if (callable instanceof Method) {
                         formalTypes = ((Method) callable).getParameterTypes();
                     } else if (callable instanceof Constructor) {
-                        formalTypes = ((Constructor) callable).getParameterTypes();
+                        formalTypes = ((Constructor<?>) callable).getParameterTypes();
                     } else {
                         throw new IllegalArgumentException("Expected method or "
                                 + " constructor; callable is " + 
@@ -1627,10 +1629,10 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
     
     /**
-     * Converts any {@link BigDecimal}s in the passed array to the type of
-     * the corresponding formal argument of the method.
+     * Converts any {@link BigDecimal}-s in the passed array to the type of
+     * the corresponding formal argument of the method via {@link #coerceBigDecimal(BigDecimal, Class)}.
      */
-    public static void coerceBigDecimals(Class[] formalTypes, Object[] args) {
+    public static void coerceBigDecimals(Class<?>[] formalTypes, Object[] args) {
         int typeLen = formalTypes.length;
         int argsLen = args.length;
         int min = Math.min(typeLen, argsLen);
@@ -1641,7 +1643,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             }
         }
         if (argsLen > typeLen) {
-            Class varArgType = formalTypes[typeLen - 1];
+            Class<?> varArgType = formalTypes[typeLen - 1];
             for (int i = typeLen; i < argsLen; ++i) {
                 Object arg = args[i];
                 if (arg instanceof BigDecimal) {
@@ -1651,7 +1653,12 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
         }
     }
 
-    public static Object coerceBigDecimal(BigDecimal bd, Class formalType) {
+    /**
+     * Converts {@link BigDecimal} to the class given in the {@code formalType} argument if that's a known numerical
+     * type, returns the {@link BigDecimal} as is otherwise. Overflow and precision loss are possible, similarly as
+     * with casting in Java.
+     */
+    public static Object coerceBigDecimal(BigDecimal bd, Class<?> formalType) {
         // int is expected in most situations, so we check it first
         if (formalType == int.class || formalType == Integer.class) {
             return Integer.valueOf(bd.intValue());
@@ -1774,19 +1781,17 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
     }
     
     /**
-     * Used for
-     * {@link MethodAppearanceFineTuner#process}
-     * as input parameter; see there.
+     * Used for {@link MethodAppearanceFineTuner#process} as input parameter; see there.
      */
     static public final class MethodAppearanceDecisionInput {
         private Method method;
-        private Class containingClass;
+        private Class<?> containingClass;
         
         void setMethod(Method method) {
             this.method = method;
         }
         
-        void setContainingClass(Class containingClass) {
+        void setContainingClass(Class<?> containingClass) {
             this.containingClass = containingClass;
         }
 
@@ -1794,7 +1799,7 @@ public class BeansWrapper implements RichObjectWrapper, WriteProtectable {
             return method;
         }
 
-        public Class getContainingClass() {
+        public Class/*<?>*/ getContainingClass() {
             return containingClass;
         }
         

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java b/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
index 54090b9..f8cb545 100644
--- a/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
+++ b/src/main/java/freemarker/ext/beans/BeansWrapperBuilder.java
@@ -20,6 +20,7 @@
 package freemarker.ext.beans;
 
 import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
 import java.util.Map;
 import java.util.WeakHashMap;
 
@@ -109,11 +110,13 @@ import freemarker.template.Version;
  */
 public class BeansWrapperBuilder extends BeansWrapperConfiguration {
 
-    private final static WeakHashMap/*<ClassLoader, Map<PropertyAssignments, WeakReference<BeansWrapper>>*/
-            INSTANCE_CACHE = new WeakHashMap();
-    private final static ReferenceQueue INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue();
+    private final static Map<ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>>
+            INSTANCE_CACHE = new WeakHashMap<
+                    ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>>();
+    private final static ReferenceQueue<BeansWrapper> INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue<BeansWrapper>();
    
-    private static class BeansWrapperFactory implements _BeansAPI._BeansWrapperSubclassFactory {
+    private static class BeansWrapperFactory
+            implements _BeansAPI._BeansWrapperSubclassFactory<BeansWrapper, BeansWrapperConfiguration> {
         
         private static final BeansWrapperFactory INSTANCE = new BeansWrapperFactory(); 
 
@@ -137,8 +140,10 @@ public class BeansWrapperBuilder extends BeansWrapperConfiguration {
         }
     }
 
-    /** For unit testing only */
-    static Map getInstanceCache() {
+    /**
+     * For unit testing only 
+     */
+    static Map<ClassLoader, Map<BeansWrapperConfiguration, WeakReference<BeansWrapper>>> getInstanceCache() {
         return INSTANCE_CACHE;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/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 6ccd872..c852636 100644
--- a/src/main/java/freemarker/ext/beans/ClassIntrospector.java
+++ b/src/main/java/freemarker/ext/beans/ClassIntrospector.java
@@ -41,6 +41,7 @@ import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Map.Entry;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
@@ -120,8 +121,11 @@ class ClassIntrospector {
     // -----------------------------------------------------------------------------------------------------------------
     // Introspection info Map keys:
 
-    private static final Object ARGTYPES_KEY = new Object();
+    /** Key in the class info Map to the Map that maps method to argument type arrays */
+    private static final Object ARG_TYPES_BY_METHOD_KEY = new Object();
+    /** Key in the class info Map to the object that represents the constructors (one or multiple due to overloading) */
     static final Object CONSTRUCTORS_KEY = new Object();
+    /** Key in the class info Map to the get(String|Object) Method */
     static final Object GENERIC_GET_KEY = new Object();
 
     // -----------------------------------------------------------------------------------------------------------------
@@ -145,12 +149,14 @@ class ClassIntrospector {
     // State fields:
 
     private final Object sharedLock;
-    private final Map/* <Class, Map<String, Object>> */cache = new ConcurrentHashMap(0, 0.75f, 16);
-    private final Set/* <String> */cacheClassNames = new HashSet(0);
-    private final Set/* <Class> */classIntrospectionsInProgress = new HashSet(0);
+    private final Map<Class<?>, Map<Object, Object>> cache
+            = new ConcurrentHashMap<Class<?>, Map<Object, Object>>(0, 0.75f, 16);
+    private final Set<String> cacheClassNames = new HashSet<String>(0);
+    private final Set<Class<?>> classIntrospectionsInProgress = new HashSet<Class<?>>(0);
 
-    private final List/* <WeakReference<ClassBasedModelFactory|ModelCache>> */modelFactories = new LinkedList();
-    private final ReferenceQueue modelFactoriesRefQueue = new ReferenceQueue();
+    private final List<WeakReference<Object/*ClassBasedModelFactory|ModelCache>*/>> modelFactories
+            = new LinkedList<WeakReference<Object>>();
+    private final ReferenceQueue<Object> modelFactoriesRefQueue = new ReferenceQueue<Object>();
 
     private int clearingCounter;
 
@@ -210,15 +216,15 @@ class ClassIntrospector {
      *         {@link #CONSTRUCTORS_KEY}), each value is a {@link PropertyDescriptor} or {@link Method} or
      *         {@link OverloadedMethods} or {@link Field} (but better check the source code...).
      */
-    Map get(Class clazz) {
+    Map<Object, Object> get(Class<?> clazz) {
         {
-            Map introspData = (Map) cache.get(clazz);
+            Map<Object, Object> introspData = cache.get(clazz);
             if (introspData != null) return introspData;
         }
 
         String className;
         synchronized (sharedLock) {
-            Map introspData = (Map) cache.get(clazz);
+            Map<Object, Object> introspData = cache.get(clazz);
             if (introspData != null) return introspData;
 
             className = clazz.getName();
@@ -231,7 +237,7 @@ class ClassIntrospector {
                 // waiting for its result.
                 try {
                     sharedLock.wait();
-                    introspData = (Map) cache.get(clazz);
+                    introspData = cache.get(clazz);
                 } catch (InterruptedException e) {
                     throw new RuntimeException(
                             "Class inrospection data lookup aborded: " + e);
@@ -243,7 +249,7 @@ class ClassIntrospector {
             classIntrospectionsInProgress.add(clazz);
         }
         try {
-            Map introspData = createClassIntrospectionData(clazz);
+            Map<Object, Object> introspData = createClassIntrospectionData(clazz);
             synchronized (sharedLock) {
                 cache.put(clazz, introspData);
                 cacheClassNames.add(className);
@@ -260,14 +266,14 @@ class ClassIntrospector {
     /**
      * Creates a {@link Map} with the content as described for the return value of {@link #get(Class)}.
      */
-    private Map createClassIntrospectionData(Class clazz) {
-        final Map introspData = new HashMap();
+    private Map<Object, Object> createClassIntrospectionData(Class<?> clazz) {
+        final Map<Object, Object> introspData = new HashMap<Object, Object>();
 
         if (exposeFields) {
             addFieldsToClassIntrospectionData(introspData, clazz);
         }
 
-        final Map accessibleMethods = discoverAccessibleMethods(clazz);
+        final Map<MethodSignature, List<Method>> accessibleMethods = discoverAccessibleMethods(clazz);
 
         addGenericGetToClassIntrospectionData(introspData, accessibleMethods);
 
@@ -285,14 +291,14 @@ class ClassIntrospector {
         if (introspData.size() > 1) {
             return introspData;
         } else if (introspData.size() == 0) {
-            return Collections.EMPTY_MAP;
+            return Collections.emptyMap();
         } else { // map.size() == 1
-            Map.Entry e = (Map.Entry) introspData.entrySet().iterator().next();
+            Entry<Object, Object> e = introspData.entrySet().iterator().next();
             return Collections.singletonMap(e.getKey(), e.getValue());
         }
     }
 
-    private void addFieldsToClassIntrospectionData(Map introspData, Class clazz)
+    private void addFieldsToClassIntrospectionData(Map<Object, Object> introspData, Class<?> clazz)
             throws SecurityException {
         Field[] fields = clazz.getFields();
         for (int i = 0; i < fields.length; i++) {
@@ -303,7 +309,8 @@ class ClassIntrospector {
         }
     }
 
-    private void addBeanInfoToClassIntrospectionData(Map introspData, Class clazz, Map accessibleMethods)
+    private void addBeanInfoToClassIntrospectionData(
+            Map<Object, Object> introspData, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods)
             throws IntrospectionException {
         BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
 
@@ -354,7 +361,7 @@ class ClassIntrospector {
                                 overloadedMethods.addMethod(method);
                                 introspData.put(methodKey, overloadedMethods);
                                 // Remove parameter type information
-                                getArgTypes(introspData).remove(previous);
+                                getArgTypesByMethod(introspData).remove(previous);
                             } else if (previous instanceof OverloadedMethods) {
                                 // Already overloaded method - add new overload
                                 ((OverloadedMethods) previous).addMethod(method);
@@ -362,7 +369,7 @@ class ClassIntrospector {
                                     || !(previous instanceof PropertyDescriptor)) {
                                 // Simple method (this far)
                                 introspData.put(methodKey, method);
-                                getArgTypes(introspData).put(method,
+                                getArgTypesByMethod(introspData).put(method,
                                         method.getParameterTypes());
                             }
                         }
@@ -372,8 +379,8 @@ class ClassIntrospector {
         } // end if (exposureLevel < EXPOSE_PROPERTIES_ONLY)
     }
 
-    private void addPropertyDescriptorToClassIntrospectionData(Map introspData,
-            PropertyDescriptor pd, Class clazz, Map accessibleMethods) {
+    private void addPropertyDescriptorToClassIntrospectionData(Map<Object, Object> introspData,
+            PropertyDescriptor pd, Class<?> clazz, Map<MethodSignature, List<Method>> accessibleMethods) {
         if (pd instanceof IndexedPropertyDescriptor) {
             IndexedPropertyDescriptor ipd =
                     (IndexedPropertyDescriptor) pd;
@@ -388,7 +395,7 @@ class ClassIntrospector {
                                 null);
                     }
                     introspData.put(ipd.getName(), ipd);
-                    getArgTypes(introspData).put(publicReadMethod, publicReadMethod.getParameterTypes());
+                    getArgTypesByMethod(introspData).put(publicReadMethod, publicReadMethod.getParameterTypes());
                 } catch (IntrospectionException e) {
                     LOG.warn("Failed creating a publicly-accessible " +
                             "property descriptor for " + clazz.getName() +
@@ -417,8 +424,8 @@ class ClassIntrospector {
         }
     }
 
-    private void addGenericGetToClassIntrospectionData(Map introspData,
-            Map accessibleMethods) {
+    private void addGenericGetToClassIntrospectionData(Map<Object, Object> introspData,
+            Map<MethodSignature, List<Method>> accessibleMethods) {
         Method genericGet = getFirstAccessibleMethod(
                 MethodSignature.GET_STRING_SIGNATURE, accessibleMethods);
         if (genericGet == null) {
@@ -430,19 +437,19 @@ class ClassIntrospector {
         }
     }
 
-    private void addConstructorsToClassIntrospectionData(final Map introspData,
-            Class clazz) {
+    private void addConstructorsToClassIntrospectionData(final Map<Object, Object> introspData,
+            Class<?> clazz) {
         try {
-            Constructor[] ctors = clazz.getConstructors();
+            Constructor<?>[] ctors = clazz.getConstructors();
             if (ctors.length == 1) {
-                Constructor ctor = ctors[0];
+                Constructor<?> ctor = ctors[0];
                 introspData.put(CONSTRUCTORS_KEY, new SimpleMethod(ctor, ctor.getParameterTypes()));
             } else if (ctors.length > 1) {
-                OverloadedMethods ctorMap = new OverloadedMethods(bugfixed);
+                OverloadedMethods overloadedCtors = new OverloadedMethods(bugfixed);
                 for (int i = 0; i < ctors.length; i++) {
-                    ctorMap.addConstructor(ctors[i]);
+                    overloadedCtors.addConstructor(ctors[i]);
                 }
-                introspData.put(CONSTRUCTORS_KEY, ctorMap);
+                introspData.put(CONSTRUCTORS_KEY, overloadedCtors);
             }
         } catch (SecurityException e) {
             LOG.warn("Can't discover constructors for class " + clazz.getName(), e);
@@ -454,13 +461,13 @@ class ClassIntrospector {
      * class is not public, retrieves methods with same signature as its public methods from public superclasses and
      * interfaces. Basically upcasts every method to the nearest accessible method.
      */
-    private static Map discoverAccessibleMethods(Class clazz) {
-        Map accessibles = new HashMap();
+    private static Map<MethodSignature, List<Method>> discoverAccessibleMethods(Class<?> clazz) {
+        Map<MethodSignature, List<Method>> accessibles = new HashMap<MethodSignature, List<Method>>();
         discoverAccessibleMethods(clazz, accessibles);
         return accessibles;
     }
 
-    private static void discoverAccessibleMethods(Class clazz, Map accessibles) {
+    private static void discoverAccessibleMethods(Class<?> clazz, Map<MethodSignature, List<Method>> accessibles) {
         if (Modifier.isPublic(clazz.getModifiers())) {
             try {
                 Method[] methods = clazz.getMethods();
@@ -478,9 +485,10 @@ class ClassIntrospector {
                     // public interface I<T> { T m(); }
                     // public class C implements I<Integer> { Integer m() { return 42; } }
                     // C.class will have both "Object m()" and "Integer m()" methods.
-                    List methodList = (List) accessibles.get(sig);
+                    List<Method> methodList = accessibles.get(sig);
                     if (methodList == null) {
-                        methodList = new LinkedList();
+                     // TODO Collection.singletonList is more efficient, though read only.
+                        methodList = new LinkedList<Method>();
                         accessibles.put(sig, methodList);
                     }
                     methodList.add(method);
@@ -494,27 +502,26 @@ class ClassIntrospector {
             }
         }
 
-        Class[] interfaces = clazz.getInterfaces();
+        Class<?>[] interfaces = clazz.getInterfaces();
         for (int i = 0; i < interfaces.length; i++) {
             discoverAccessibleMethods(interfaces[i], accessibles);
         }
-        Class superclass = clazz.getSuperclass();
+        Class<?> superclass = clazz.getSuperclass();
         if (superclass != null) {
             discoverAccessibleMethods(superclass, accessibles);
         }
     }
 
-    private static Method getMatchingAccessibleMethod(Method m, Map accessibles) {
+    private static Method getMatchingAccessibleMethod(Method m, Map<MethodSignature, List<Method>> accessibles) {
         if (m == null) {
             return null;
         }
         MethodSignature sig = new MethodSignature(m);
-        List l = (List) accessibles.get(sig);
-        if (l == null) {
+        List<Method> ams = accessibles.get(sig);
+        if (ams == null) {
             return null;
         }
-        for (Iterator iterator = l.iterator(); iterator.hasNext(); ) {
-            Method am = (Method) iterator.next();
+        for (Method am : ams) {
             if (am.getReturnType() == m.getReturnType()) {
                 return am;
             }
@@ -522,12 +529,12 @@ class ClassIntrospector {
         return null;
     }
 
-    private static Method getFirstAccessibleMethod(MethodSignature sig, Map accessibles) {
-        List l = (List) accessibles.get(sig);
-        if (l == null || l.isEmpty()) {
+    private static Method getFirstAccessibleMethod(MethodSignature sig, Map<MethodSignature, List<Method>> accessibles) {
+        List<Method> ams = accessibles.get(sig);
+        if (ams == null || ams.isEmpty()) {
             return null;
         }
-        return (Method) l.iterator().next();
+        return ams.get(0);
     }
 
     /**
@@ -541,11 +548,12 @@ class ClassIntrospector {
         return exposureLevel < BeansWrapper.EXPOSE_SAFE || !UnsafeMethods.isUnsafeMethod(method);
     }
 
-    private static Map getArgTypes(Map classMap) {
-        Map argTypes = (Map) classMap.get(ARGTYPES_KEY);
+    private static Map<Method, Class<?>[]> getArgTypesByMethod(Map<Object, Object> classInfo) {
+        @SuppressWarnings("unchecked")
+        Map<Method, Class<?>[]> argTypes = (Map<Method, Class<?>[]>) classInfo.get(ARG_TYPES_BY_METHOD_KEY);
         if (argTypes == null) {
-            argTypes = new HashMap();
-            classMap.put(ARGTYPES_KEY, argTypes);
+            argTypes = new HashMap<Method, Class<?>[]>();
+            classInfo.put(ARG_TYPES_BY_METHOD_KEY, argTypes);
         }
         return argTypes;
     }
@@ -557,9 +565,9 @@ class ClassIntrospector {
                 new MethodSignature("get", new Class[] { Object.class });
 
         private final String name;
-        private final Class[] args;
+        private final Class<?>[] args;
 
-        private MethodSignature(String name, Class[] args) {
+        private MethodSignature(String name, Class<?>[] args) {
             this.name = name;
             this.args = args;
         }
@@ -606,8 +614,8 @@ class ClassIntrospector {
             cacheClassNames.clear();
             clearingCounter++;
 
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((WeakReference) it.next()).get();
+            for (WeakReference<Object> regedMfREf : modelFactories) {
+                Object regedMf = regedMfREf.get();
                 if (regedMf != null) {
                     if (regedMf instanceof ClassBasedModelFactory) {
                         ((ClassBasedModelFactory) regedMf).clearCache();
@@ -628,14 +636,14 @@ class ClassIntrospector {
      * 
      * @since 2.3.20
      */
-    void remove(Class clazz) {
+    void remove(Class<?> clazz) {
         synchronized (sharedLock) {
             cache.remove(clazz);
             cacheClassNames.remove(clazz.getName());
             clearingCounter++;
 
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((WeakReference) it.next()).get();
+            for (WeakReference<Object> regedMfREf : modelFactories) {
+                Object regedMf = regedMfREf.get();
                 if (regedMf != null) {
                     if (regedMf instanceof ClassBasedModelFactory) {
                         ((ClassBasedModelFactory) regedMf).removeFromCache(clazz);
@@ -688,7 +696,7 @@ class ClassIntrospector {
     private void registerModelFactory(Object mf) {
         // Note that this `synchronized (sharedLock)` is also need for the BeansWrapper constructor to work safely.
         synchronized (sharedLock) {
-            modelFactories.add(new WeakReference(mf, modelFactoriesRefQueue));
+            modelFactories.add(new WeakReference<Object>(mf, modelFactoriesRefQueue));
             removeClearedModelFactoryReferences();
         }
     }
@@ -703,8 +711,8 @@ class ClassIntrospector {
 
     void unregisterModelFactory(Object mf) {
         synchronized (sharedLock) {
-            for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
-                Object regedMf = ((Reference) it.next()).get();
+            for (Iterator<WeakReference<Object>> it = modelFactories.iterator(); it.hasNext(); ) {
+                Object regedMf = it.next().get();
                 if (regedMf == mf) {
                     it.remove();
                 }
@@ -714,13 +722,13 @@ class ClassIntrospector {
     }
 
     private void removeClearedModelFactoryReferences() {
-        Reference cleardRef;
+        Reference<?> cleardRef;
         while ((cleardRef = modelFactoriesRefQueue.poll()) != null) {
             synchronized (sharedLock) {
-                findCleardRef: for (Iterator it = modelFactories.iterator(); it.hasNext(); ) {
+                findClearedRef: for (Iterator<WeakReference<Object>> it = modelFactories.iterator(); it.hasNext(); ) {
                     if (it.next() == cleardRef) {
                         it.remove();
-                        break findCleardRef;
+                        break findClearedRef;
                     }
                 }
             }
@@ -730,20 +738,22 @@ class ClassIntrospector {
     // -----------------------------------------------------------------------------------------------------------------
     // Extracting from introspection info:
 
-    static Class[] getArgTypes(Map classMap, AccessibleObject methodOrCtor) {
-        return (Class[]) ((Map) classMap.get(ARGTYPES_KEY)).get(methodOrCtor);
+    static Class<?>[] getArgTypes(Map<Object, Object> classInfo, Method method) {
+        @SuppressWarnings("unchecked")
+        Map<Method, Class<?>[]> argTypesByMethod = (Map<Method, Class<?>[]>) classInfo.get(ARG_TYPES_BY_METHOD_KEY);
+        return argTypesByMethod.get(method);
     }
 
     /**
      * Returns the number of introspected methods/properties that should be available via the TemplateHashModel
      * interface.
      */
-    int keyCount(Class clazz) {
-        Map map = get(clazz);
+    int keyCount(Class<?> clazz) {
+        Map<Object, Object> map = get(clazz);
         int count = map.size();
         if (map.containsKey(CONSTRUCTORS_KEY)) count--;
         if (map.containsKey(GENERIC_GET_KEY)) count--;
-        if (map.containsKey(ARGTYPES_KEY)) count--;
+        if (map.containsKey(ARG_TYPES_BY_METHOD_KEY)) count--;
         return count;
     }
 
@@ -751,11 +761,11 @@ class ClassIntrospector {
      * Returns the Set of names of introspected methods/properties that should be available via the TemplateHashModel
      * interface.
      */
-    Set keySet(Class clazz) {
-        Set set = new HashSet(get(clazz).keySet());
+    Set<Object> keySet(Class<?> clazz) {
+        Set<Object> set = new HashSet<Object>(get(clazz).keySet());
         set.remove(CONSTRUCTORS_KEY);
         set.remove(GENERIC_GET_KEY);
-        set.remove(ARGTYPES_KEY);
+        set.remove(ARG_TYPES_BY_METHOD_KEY);
         return set;
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/beans/_BeansAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/beans/_BeansAPI.java b/src/main/java/freemarker/ext/beans/_BeansAPI.java
index f469508..a2c648d 100644
--- a/src/main/java/freemarker/ext/beans/_BeansAPI.java
+++ b/src/main/java/freemarker/ext/beans/_BeansAPI.java
@@ -49,7 +49,7 @@ public class _BeansAPI {
         return bm.getAsClassicCompatibleString();
     }
     
-    public static Object newInstance(Class pClass, Object[] args, BeansWrapper bw)
+    public static Object newInstance(Class<?> pClass, Object[] args, BeansWrapper bw)
             throws NoSuchMethodException, IllegalArgumentException, InstantiationException,
             IllegalAccessException, InvocationTargetException, TemplateModelException {
         return newInstance(getConstructorDescriptor(pClass, args), args, bw);
@@ -60,15 +60,18 @@ public class _BeansAPI {
      * than what the Java reflection API provides in that it can handle overloaded constructors. This re-uses the
      * overloaded method selection logic of {@link BeansWrapper}.
      */
-    private static CallableMemberDescriptor getConstructorDescriptor(Class pClass, Object[] args) throws NoSuchMethodException {
+    private static CallableMemberDescriptor getConstructorDescriptor(Class<?> pClass, Object[] args)
+            throws NoSuchMethodException {
         if (args == null) args = CollectionUtils.EMPTY_OBJECT_ARRAY;
         
         final ArgumentTypes argTypes = new ArgumentTypes(args, true);
-        final List fixedArgMemberDescs = new ArrayList();
-        final List varArgsMemberDescs = new ArrayList();
-        final Constructor[] constrs = pClass.getConstructors();
+        final List<ReflectionCallableMemberDescriptor> fixedArgMemberDescs
+                = new ArrayList<ReflectionCallableMemberDescriptor>();
+        final List<ReflectionCallableMemberDescriptor> varArgsMemberDescs
+                = new ArrayList<ReflectionCallableMemberDescriptor>();
+        final Constructor<?>[] constrs = pClass.getConstructors();
         for (int i = 0; i < constrs.length; i++) {
-            Constructor constr = constrs[i];
+            Constructor<?> constr = constrs[i];
             ReflectionCallableMemberDescriptor memberDesc = new ReflectionCallableMemberDescriptor(constr, constr.getParameterTypes());
             if (!_MethodUtil.isVarargs(constr)) {
                 fixedArgMemberDescs.add(memberDesc);
@@ -108,7 +111,7 @@ public class _BeansAPI {
         if (constrDesc.isVarargs()) {
             // We have to put all the varargs arguments into a single array argument.
 
-            final Class[] paramTypes = constrDesc.getParamTypes();
+            final Class<?>[] paramTypes = constrDesc.getParamTypes();
             final int fixedArgCnt = paramTypes.length - 1;
             
             packedArgs = new Object[fixedArgCnt + 1]; 
@@ -116,7 +119,7 @@ public class _BeansAPI {
                 packedArgs[i] = args[i];
             }
             
-            final Class compType = paramTypes[fixedArgCnt].getComponentType();
+            final Class<?> compType = paramTypes[fixedArgCnt].getComponentType();
             final int varArgCnt = args.length - fixedArgCnt;
             final Object varArgsArray = Array.newInstance(compType, varArgCnt);
             for (int i = 0; i < varArgCnt; i++) {
@@ -136,47 +139,47 @@ public class _BeansAPI {
      * @param beansWrapperSubclassFactory Creates a <em>new</em> read-only object wrapper of the desired
      *     {@link BeansWrapper} subclass. 
      */
-    public static BeansWrapper getBeansWrapperSubclassSingleton(
-            BeansWrapperConfiguration settings,
-            Map instanceCache,
-            ReferenceQueue instanceCacheRefQue,
-            _BeansWrapperSubclassFactory beansWrapperSubclassFactory) {
+    public static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> BW getBeansWrapperSubclassSingleton(
+            BWC settings,
+            Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
+            ReferenceQueue<BW> instanceCacheRefQue,
+            _BeansWrapperSubclassFactory<BW, BWC> beansWrapperSubclassFactory) {
         // BeansWrapper can't be cached across different Thread Context Class Loaders (TCCL), because the result of
         // a class name (String) to Class mappings depends on it, and the staticModels and enumModels need that.
         // (The ClassIntrospector doesn't have to consider the TCCL, as it only works with Class-es, not class
         // names.)
         ClassLoader tccl = Thread.currentThread().getContextClassLoader();
         
-        Reference instanceRef;
-        Map/*<PropertyAssignments, WeakReference<BeansWrapper>>*/ tcclScopedCache;
+        Reference<BW> instanceRef;
+        Map<BWC, WeakReference<BW>> tcclScopedCache;
         synchronized (instanceCache) {
-            tcclScopedCache = (Map) instanceCache.get(tccl);
+            tcclScopedCache = instanceCache.get(tccl);
             if (tcclScopedCache == null) {
-                tcclScopedCache = new HashMap();
+                tcclScopedCache = new HashMap<BWC, WeakReference<BW>>();
                 instanceCache.put(tccl, tcclScopedCache);
                 instanceRef = null;
             } else {
-                instanceRef = (Reference) tcclScopedCache.get(settings);
+                instanceRef = tcclScopedCache.get(settings);
             }
         }
 
-        BeansWrapper instance = instanceRef != null ? (BeansWrapper) instanceRef.get() : null;
+        BW instance = instanceRef != null ? instanceRef.get() : null;
         if (instance != null) {  // cache hit
             return instance;
         }
         // cache miss
         
-        settings = (BeansWrapperConfiguration) settings.clone(true);  // prevent any aliasing issues 
+        settings = clone(settings);  // prevent any aliasing issues 
         instance = beansWrapperSubclassFactory.create(settings);
         if (!instance.isWriteProtected()) {
             throw new BugException();
         }
         
         synchronized (instanceCache) {
-            instanceRef = (Reference) tcclScopedCache.get(settings);
-            BeansWrapper concurrentInstance = instanceRef != null ? (BeansWrapper) instanceRef.get() : null;
+            instanceRef = tcclScopedCache.get(settings);
+            BW concurrentInstance = instanceRef != null ? instanceRef.get() : null;
             if (concurrentInstance == null) {
-                tcclScopedCache.put(settings, new WeakReference(instance, instanceCacheRefQue));
+                tcclScopedCache.put(settings, new WeakReference<BW>(instance, instanceCacheRefQue));
             } else {
                 instance = concurrentInstance;
             }
@@ -186,14 +189,21 @@ public class _BeansAPI {
         
         return instance;
     }
+
+    @SuppressWarnings("unchecked")
+    private static <BWC extends BeansWrapperConfiguration> BWC clone(BWC settings) {
+        return (BWC) settings.clone(true);
+    }
     
-    private static void removeClearedReferencesFromCache(Map instanceCache, ReferenceQueue instanceCacheRefQue) {
-        Reference clearedRef;
+    private static <BW extends BeansWrapper, BWC extends BeansWrapperConfiguration>
+            void removeClearedReferencesFromCache(
+                    Map<ClassLoader, Map<BWC, WeakReference<BW>>> instanceCache,
+                    ReferenceQueue<BW> instanceCacheRefQue) {
+        Reference<? extends BW> clearedRef;
         while ((clearedRef = instanceCacheRefQue.poll()) != null) {
             synchronized (instanceCache) {
-                findClearedRef: for (Iterator it1 = instanceCache.values().iterator(); it1.hasNext(); ) {
-                    Map tcclScopedCache = (Map) it1.next();
-                    for (Iterator it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
+                findClearedRef: for (Map<BWC, WeakReference<BW>> tcclScopedCache : instanceCache.values()) {
+                    for (Iterator<WeakReference<BW>> it2 = tcclScopedCache.values().iterator(); it2.hasNext(); ) {
                         if (it2.next() == clearedRef) {
                             it2.remove();
                             break findClearedRef;
@@ -207,10 +217,10 @@ public class _BeansAPI {
     /**
      * For internal use only; don't depend on this, there's no backward compatibility guarantee at all!
      */
-    public interface _BeansWrapperSubclassFactory {
+    public interface _BeansWrapperSubclassFactory<BW extends BeansWrapper, BWC extends BeansWrapperConfiguration> {
         
         /** Creates a new read-only {@link BeansWrapper}; used for {@link BeansWrapperBuilder} and such. */
-        BeansWrapper create(BeansWrapperConfiguration sa);
+        BW create(BWC sa);
     }
     
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/util/IdentityHashMap.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/util/IdentityHashMap.java b/src/main/java/freemarker/ext/util/IdentityHashMap.java
index 57bb9db..13e140f 100644
--- a/src/main/java/freemarker/ext/util/IdentityHashMap.java
+++ b/src/main/java/freemarker/ext/util/IdentityHashMap.java
@@ -30,11 +30,12 @@ import java.util.NoSuchElementException;
 import java.util.Set;
 
 /**
- * A variant of {@link java.util.HashMap} that uses
- * {@link System#identityHashCode(Object)} for hashing, and reference comparison
- * instead of {@link Object#equals(Object)}. Note that this applies only to keys,
- * and not to values, i.e. {@link #containsValue(Object)} still uses {@link Object#equals(Object)}.
+ * Was used instead of {@link java.util.IdentityHashMap} before that was added to Java itself in Java 1.4. 
+ * 
+ * @deprecated Use {@link java.util.IdentityHashMap} instead.
  */
+@SuppressWarnings("rawtypes")
+@Deprecated
 public class IdentityHashMap
     extends AbstractMap
     implements Map, Cloneable, java.io.Serializable {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/ext/util/ModelCache.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/ext/util/ModelCache.java b/src/main/java/freemarker/ext/util/ModelCache.java
index 5a4b3ad..52ac7d1 100644
--- a/src/main/java/freemarker/ext/util/ModelCache.java
+++ b/src/main/java/freemarker/ext/util/ModelCache.java
@@ -23,6 +23,8 @@ import java.lang.ref.ReferenceQueue;
 import java.lang.ref.SoftReference;
 import java.util.Map;
 
+import java.util.IdentityHashMap;
+
 import freemarker.template.TemplateModel;
 import freemarker.template.TemplateModelAdapter;
 
@@ -32,8 +34,8 @@ import freemarker.template.TemplateModelAdapter;
  */
 public abstract class ModelCache {
     private boolean useCache = false;
-    private Map modelCache = null;
-    private ReferenceQueue refQueue = null;
+    private Map<Object, ModelReference> modelCache = null;
+    private ReferenceQueue<TemplateModel> refQueue = null;
     
     protected ModelCache() {
     }
@@ -46,8 +48,8 @@ public abstract class ModelCache {
     public synchronized void setUseCache(boolean useCache) {
         this.useCache = useCache;
         if (useCache) {
-            modelCache = new IdentityHashMap();
-            refQueue = new ReferenceQueue();
+            modelCache = new IdentityHashMap<Object, ModelReference>();
+            refQueue = new ReferenceQueue<TemplateModel>();
         } else {
             modelCache = null;
             refQueue = null;
@@ -97,7 +99,7 @@ public abstract class ModelCache {
         // duplicate wrapper creation. However, this has no harmful side-effects and
         // is a lesser performance hit.
         synchronized (modelCache) {
-            ref = (ModelReference) modelCache.get(object);
+            ref = modelCache.get(object);
         }
 
         if (ref != null)
@@ -111,8 +113,9 @@ public abstract class ModelCache {
             // Remove cleared references
             for (; ; ) {
                 ModelReference queuedRef = (ModelReference) refQueue.poll();
-                if (queuedRef == null)
+                if (queuedRef == null) {
                     break;
+                }
                 modelCache.remove(queuedRef.object);
             }
             // Register new reference
@@ -125,10 +128,10 @@ public abstract class ModelCache {
      * When it gets cleared (that is, the model became unreachable)
      * it will remove itself from the model cache.
      */
-    private static final class ModelReference extends SoftReference {
+    private static final class ModelReference extends SoftReference<TemplateModel> {
         Object object;
 
-        ModelReference(TemplateModel ref, Object object, ReferenceQueue refQueue) {
+        ModelReference(TemplateModel ref, Object object, ReferenceQueue<TemplateModel> refQueue) {
             super(ref, refQueue);
             this.object = object;
         }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/DefaultObjectWrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/DefaultObjectWrapper.java b/src/main/java/freemarker/template/DefaultObjectWrapper.java
index b2f5820..323e1dd 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapper.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapper.java
@@ -61,7 +61,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
     @Deprecated
     static final DefaultObjectWrapper instance = new DefaultObjectWrapper();
     
-    static final private Class JYTHON_OBJ_CLASS;
+    static final private Class<?> JYTHON_OBJ_CLASS;
     
     static final private ObjectWrapper JYTHON_WRAPPER;
     
@@ -133,7 +133,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
     }
     
     static {
-        Class cl;
+        Class<?> cl;
         ObjectWrapper ow;
         try {
             cl = Class.forName("org.python.core.PyObject");
@@ -191,7 +191,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
             }
             return new SimpleDate((java.util.Date) obj, getDefaultDateType());
         }
-        final Class objClass = obj.getClass();
+        final Class<?> objClass = obj.getClass();
         if (objClass.isArray()) {
             if (useAdaptersForContainers) {
                 return DefaultArrayAdapter.adapt(obj, this);
@@ -203,28 +203,28 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
         if (obj instanceof Collection) {
             if (useAdaptersForContainers) {
                 if (obj instanceof List) {
-                    return DefaultListAdapter.adapt((List) obj, this);
+                    return DefaultListAdapter.adapt((List<?>) obj, this);
                 } else {
                     return forceLegacyNonListCollections
-                            ? (TemplateModel) new SimpleSequence((Collection) obj, this)
-                            : (TemplateModel) DefaultNonListCollectionAdapter.adapt((Collection) obj, this);
+                            ? (TemplateModel) new SimpleSequence((Collection<?>) obj, this)
+                            : (TemplateModel) DefaultNonListCollectionAdapter.adapt((Collection<?>) obj, this);
                 }
             } else {
-                return new SimpleSequence((Collection) obj, this);
+                return new SimpleSequence((Collection<?>) obj, this);
             }
         }
         if (obj instanceof Map) {
             return useAdaptersForContainers
-                    ? (TemplateModel) DefaultMapAdapter.adapt((Map) obj, this)
-                    : (TemplateModel) new SimpleHash((Map) obj, this);
+                    ? (TemplateModel) DefaultMapAdapter.adapt((Map<?, ?>) obj, this)
+                    : (TemplateModel) new SimpleHash((Map<?, ?>) obj, this);
         }
         if (obj instanceof Boolean) {
             return obj.equals(Boolean.TRUE) ? TemplateBooleanModel.TRUE : TemplateBooleanModel.FALSE;
         }
         if (obj instanceof Iterator) {
             return useAdaptersForContainers
-                    ? (TemplateModel) DefaultIteratorAdapter.adapt((Iterator) obj, this)
-                    : (TemplateModel) new SimpleCollection((Iterator) obj, this);
+                    ? (TemplateModel) DefaultIteratorAdapter.adapt((Iterator<?>) obj, this)
+                    : (TemplateModel) new SimpleCollection((Iterator<?>) obj, this);
         }
         if (iterableSupport && obj instanceof Iterable) {
             return DefaultIterableAdapter.adapt((Iterable<?>) obj, this);
@@ -261,6 +261,7 @@ public class DefaultObjectWrapper extends freemarker.ext.beans.BeansWrapper {
      * Converts an array to a java.util.List.
      */
     protected Object convertArray(Object arr) {
+        // FM 2.4: Use Arrays.asList instead
         final int size = Array.getLength(arr);
         ArrayList list = new ArrayList(size);
         for (int i = 0; i < size; i++) {

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java b/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
index b8f89ba..7a6a027 100644
--- a/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
+++ b/src/main/java/freemarker/template/DefaultObjectWrapperBuilder.java
@@ -20,11 +20,11 @@
 package freemarker.template;
 
 import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.util.Map;
 import java.util.WeakHashMap;
 
-import freemarker.ext.beans.BeansWrapper;
 import freemarker.ext.beans.BeansWrapperBuilder;
-import freemarker.ext.beans.BeansWrapperConfiguration;
 import freemarker.ext.beans._BeansAPI;
 
 /**
@@ -38,9 +38,11 @@ import freemarker.ext.beans._BeansAPI;
  */
 public class DefaultObjectWrapperBuilder extends DefaultObjectWrapperConfiguration {
 
-    private final static WeakHashMap/*<ClassLoader, Map<BeansWrapperSettings, WeakReference<DefaultObjectWrapper>>*/
-            INSTANCE_CACHE = new WeakHashMap();
-    private final static ReferenceQueue INSTANCE_CACHE_REF_QUEUE = new ReferenceQueue();
+    private final static Map<ClassLoader, Map<DefaultObjectWrapperConfiguration, WeakReference<DefaultObjectWrapper>>>
+            INSTANCE_CACHE = new WeakHashMap<
+                    ClassLoader, Map<DefaultObjectWrapperConfiguration, WeakReference<DefaultObjectWrapper>>>();
+    private final static ReferenceQueue<DefaultObjectWrapper> INSTANCE_CACHE_REF_QUEUE
+            = new ReferenceQueue<DefaultObjectWrapper>();
     
     /**
      * Creates a builder that creates a {@link DefaultObjectWrapper} with the given {@code incompatibleImprovements};
@@ -63,16 +65,16 @@ public class DefaultObjectWrapperBuilder extends DefaultObjectWrapperConfigurati
      * a singleton that is also in use elsewhere. 
      */
     public DefaultObjectWrapper build() {
-        return (DefaultObjectWrapper) _BeansAPI.getBeansWrapperSubclassSingleton(
+        return _BeansAPI.getBeansWrapperSubclassSingleton(
                 this, INSTANCE_CACHE, INSTANCE_CACHE_REF_QUEUE, DefaultObjectWrapperFactory.INSTANCE);
     }
     
     private static class DefaultObjectWrapperFactory
-        implements _BeansAPI._BeansWrapperSubclassFactory {
+        implements _BeansAPI._BeansWrapperSubclassFactory<DefaultObjectWrapper, DefaultObjectWrapperConfiguration> {
     
         private static final DefaultObjectWrapperFactory INSTANCE = new DefaultObjectWrapperFactory(); 
         
-        public BeansWrapper create(BeansWrapperConfiguration bwConf) {
+        public DefaultObjectWrapper create(DefaultObjectWrapperConfiguration bwConf) {
             return new DefaultObjectWrapper(bwConf, true);
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java b/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
index b48fa5f..7ec4461 100644
--- a/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
+++ b/src/main/java/freemarker/template/ObjectWrapperAndUnwrapper.java
@@ -87,6 +87,6 @@ public interface ObjectWrapperAndUnwrapper extends ObjectWrapper {
      * 
      * @since 2.3.22
      */
-    Object tryUnwrapTo(TemplateModel tm, Class targetClass) throws TemplateModelException;
+    Object tryUnwrapTo(TemplateModel tm, Class<?> targetClass) throws TemplateModelException;
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-freemarker/blob/277956d9/src/main/java/freemarker/template/_TemplateAPI.java
----------------------------------------------------------------------
diff --git a/src/main/java/freemarker/template/_TemplateAPI.java b/src/main/java/freemarker/template/_TemplateAPI.java
index 0fc702a..c55a113 100644
--- a/src/main/java/freemarker/template/_TemplateAPI.java
+++ b/src/main/java/freemarker/template/_TemplateAPI.java
@@ -19,8 +19,6 @@
 
 package freemarker.template;
 
-import java.util.List;
-import java.util.Map;
 import java.util.Set;
 
 import freemarker.cache.CacheStorage;