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);