On 05/17/2012 12:23 PM, Jacopo Cappellato wrote:
> file are attached; that bug tracker is really awful.

I've got another one to attach, a more proper fix, that makes the
change configurable.

ps: Have I said how much I hate that tracker?
diff --git a/freemarker/src/freemarker/ext/beans/BeansWrapper.java b/freemarker/src/freemarker/ext/beans/BeansWrapper.java
index 7103a42..cd4d59d 100644
--- a/freemarker/src/freemarker/ext/beans/BeansWrapper.java
+++ b/freemarker/src/freemarker/ext/beans/BeansWrapper.java
@@ -223,6 +223,7 @@ public class BeansWrapper implements ObjectWrapper
     private ObjectWrapper outerIdentity = this;
     private boolean simpleMapWrapper;
     private boolean strict = false;
+    private boolean nullWildcards = false;
     
     /**
      * Creates a new instance of BeansWrapper. The newly created instance
@@ -237,6 +238,27 @@ public class BeansWrapper implements ObjectWrapper
     }
     
     /**
+     * @see #setNullWildcards(boolean)
+     */
+    public boolean useNullWildcards() {
+    	return nullWildcards;
+    }
+    
+    /**
+     * Specifies whether to use a wildcard class when resolving method objects.
+     * 
+     * <p>If this property is <tt>false</tt> (the default) then null parameter passed
+     * to a method will be given an Object.class, for method resolution.
+     *
+     * <p>If this property is <tt>true</tt> then null parameters will have wildcard
+     * class processing done when finding the most correct overloaded method to call.
+     * A formal method type will match when the type is not a primitive type.  This
+     */
+    public void setNullWildcards(boolean nullWildcards) {
+    	this.nullWildcards = nullWildcards;
+    }
+    
+    /**
      * @see #setStrict(boolean)
      */
     public boolean isStrict() {
diff --git a/freemarker/src/freemarker/ext/beans/ClassString.java b/freemarker/src/freemarker/ext/beans/ClassString.java
index 2cdee9b..67d10ea 100644
--- a/freemarker/src/freemarker/ext/beans/ClassString.java
+++ b/freemarker/src/freemarker/ext/beans/ClassString.java
@@ -70,12 +70,20 @@ final class ClassString
 
     private final Class[] classes;
     
-    ClassString(Object[] objects) {
+    ClassString(Object[] objects, boolean nullWildcards) {
         int l = objects.length;
         classes = new Class[l];
         for(int i = 0; i < l; ++i) {
             Object obj = objects[i];
-            classes[i] = obj == null ? MethodUtilities.OBJECT_CLASS : obj.getClass();
+            if (obj == null) {
+                if (nullWildcards) {
+                    classes[i] = MethodUtilities.WILDCARD_CLASS;
+                } else {
+                    classes[i] = MethodUtilities.OBJECT_CLASS;
+                }
+            } else {
+                classes[i] = obj.getClass();
+            }
         }
     }
     
@@ -293,13 +301,16 @@ final class ClassString
             // conversion, not widening. 
             return isBigDecimalConvertible(formal, actual);
         }
+        if (actual == MethodUtilities.WILDCARD_CLASS) {
+            return true;
+        }
         return false;
     }
     
     private static boolean isBigDecimalConvertible(Class formal, Class actual)
     {
         // BigDecimal 
-        if(BIGDECIMAL_CLASS.isAssignableFrom(actual))
+        if(BIGDECIMAL_CLASS.isAssignableFrom(actual) || actual == MethodUtilities.WILDCARD_CLASS)
         {
             if(NUMBER_CLASS.isAssignableFrom(formal))
             {
diff --git a/freemarker/src/freemarker/ext/beans/MethodUtilities.java b/freemarker/src/freemarker/ext/beans/MethodUtilities.java
index d80efc1..97e810f 100644
--- a/freemarker/src/freemarker/ext/beans/MethodUtilities.java
+++ b/freemarker/src/freemarker/ext/beans/MethodUtilities.java
@@ -64,6 +64,11 @@ import freemarker.template.utility.UndeclaredThrowableException;
 
 class MethodUtilities
 {
+    static final Class WILDCARD_CLASS = new Object() {
+        public String toString() {
+            return "<fm-wildcard>";
+        }
+    }.getClass();
     static final Class OBJECT_CLASS = Object.class;
     private static final Method METHOD_IS_VARARGS = getIsVarArgsMethod(Method.class);
     private static final Method CONSTRUCTOR_IS_VARARGS = getIsVarArgsMethod(Constructor.class);
diff --git a/freemarker/src/freemarker/ext/beans/OverloadedFixArgMethod.java b/freemarker/src/freemarker/ext/beans/OverloadedFixArgMethod.java
index aacf89b..4fc29f9 100644
--- a/freemarker/src/freemarker/ext/beans/OverloadedFixArgMethod.java
+++ b/freemarker/src/freemarker/ext/beans/OverloadedFixArgMethod.java
@@ -101,7 +101,7 @@ class OverloadedFixArgMethod extends OverloadedMethod
             args[i] = obj;
         }
         
-        Object objMember = getMemberForArgs(args, false);
+        Object objMember = getMemberForArgs(args, false, w.useNullWildcards());
         if(objMember instanceof Member) {
             Member member = (Member)objMember;
             BeansWrapper.coerceBigDecimals(getSignature(member), args);
diff --git a/freemarker/src/freemarker/ext/beans/OverloadedMethod.java b/freemarker/src/freemarker/ext/beans/OverloadedMethod.java
index 1473afc..9168fd9 100644
--- a/freemarker/src/freemarker/ext/beans/OverloadedMethod.java
+++ b/freemarker/src/freemarker/ext/beans/OverloadedMethod.java
@@ -117,8 +117,8 @@ abstract class OverloadedMethod {
 	return marshalTypes;
     }
     
-    Object getMemberForArgs(Object[] args, boolean varArg) {
-	ClassString argTypes = new ClassString(args);
+    Object getMemberForArgs(Object[] args, boolean varArg, boolean nullWildcards) {
+	ClassString argTypes = new ClassString(args, nullWildcards);
         Object objMember;
         synchronized(selectorCache) {
             objMember = selectorCache.get(argTypes);
diff --git a/freemarker/src/freemarker/ext/beans/OverloadedVarArgMethod.java b/freemarker/src/freemarker/ext/beans/OverloadedVarArgMethod.java
index 9ca2af3..319516a 100644
--- a/freemarker/src/freemarker/ext/beans/OverloadedVarArgMethod.java
+++ b/freemarker/src/freemarker/ext/beans/OverloadedVarArgMethod.java
@@ -242,7 +242,7 @@ outer:  for(int j = Math.min(l + 1, marshalTypes.length - 1); j >= 0; --j) {
             break;
         }
         
-        Object objMember = getMemberForArgs(args, true);
+        Object objMember = getMemberForArgs(args, true, w.useNullWildcards());
         if(objMember instanceof Member) {
             Member member = (Member)objMember;
             args = ((ArgumentPacker)argPackers.get(member)).packArgs(args, arguments, w);

Reply via email to