Author: remy.maucherat(a)jboss.com
Date: 2012-03-26 10:37:14 -0400 (Mon, 26 Mar 2012)
New Revision: 2004
Modified:
trunk/java/org/apache/el/parser/AstValue.java
trunk/java/org/apache/el/util/ReflectionUtil.java
trunk/webapps/docs/changelog.xml
Log:
52970: Fix enum as method invocation argument in EL
Modified: trunk/java/org/apache/el/parser/AstValue.java
===================================================================
--- trunk/java/org/apache/el/parser/AstValue.java 2012-03-16 16:54:57 UTC (rev 2003)
+++ trunk/java/org/apache/el/parser/AstValue.java 2012-03-26 14:37:14 UTC (rev 2004)
@@ -230,7 +230,8 @@
@SuppressWarnings("rawtypes") Class[] paramTypes)
throws ELException {
Target t = getTarget(ctx);
- Method m = ReflectionUtil.getMethod(t.base, t.property, paramTypes);
+ Method m = ReflectionUtil.getMethod(
+ t.base, t.property, paramTypes, null);
return new MethodInfo(m.getName(), m.getReturnType(), m
.getParameterTypes());
}
@@ -244,19 +245,20 @@
Target t = getTarget(ctx);
Method m = null;
Object[] values = null;
+ Class<?>[] types = null;
if (isParametersProvided()) {
values = ((AstMethodParameters) this.jjtGetChild(
this.jjtGetNumChildren() - 1)).getParameters(ctx);
- Class<?>[] types = getTypesFromValues(values);
- m = ReflectionUtil.getMethod(t.base, t.property, types);
+ types = getTypesFromValues(values);
} else {
- m = ReflectionUtil.getMethod(t.base, t.property, paramTypes);
values = paramValues;
+ types = paramTypes;
}
- if (m.isVarArgs()) {
- // May need to convert values
- values = toVarArgs(values, m);
- }
+ m = ReflectionUtil.getMethod(t.base, t.property, types, values);
+
+ // Handle varArgs and any co-ercion required
+ values = convertArgs(values, m);
+
Object result = null;
try {
result = m.invoke(t.base, values);
@@ -277,17 +279,34 @@
return result;
}
- private Object[] toVarArgs(Object[] src, Method m) {
- int paramCount = m.getParameterTypes().length;
+ private Object[] convertArgs(Object[] src, Method m) {
+ Class<?>[] types = m.getParameterTypes();
+ if (types.length == 0) {
+ return new Object[0];
+ }
+ int paramCount = types.length;
+
Object[] dest = new Object[paramCount];
- Object[] varArgs = (Object[]) Array.newInstance(
- m.getParameterTypes()[paramCount - 1].getComponentType(),
- src.length - (paramCount - 1));
- System.arraycopy(src, 0, dest, 0, paramCount - 1);
- System.arraycopy(src, paramCount - 1, varArgs, 0,
- src.length - (paramCount - 1));
- dest[paramCount - 1] = varArgs;
+
+ for (int i = 0; i < paramCount - 1; i++) {
+ dest[i] = ELSupport.coerceToType(src[i], types[i]);
+ }
+
+ if (m.isVarArgs()) {
+ Object[] varArgs = (Object[]) Array.newInstance(
+ m.getParameterTypes()[paramCount - 1].getComponentType(),
+ src.length - (paramCount - 1));
+ for (int i = 0; i < src.length - (paramCount - 1); i ++) {
+ varArgs[i] = ELSupport.coerceToType(src[paramCount - 1 + i],
+ types[paramCount - 1].getComponentType());
+ }
+ dest[paramCount - 1] = varArgs;
+ } else {
+ dest[paramCount - 1] = ELSupport.coerceToType(
+ src[paramCount - 1], types[paramCount - 1]);
+ }
+
return dest;
}
Modified: trunk/java/org/apache/el/util/ReflectionUtil.java
===================================================================
--- trunk/java/org/apache/el/util/ReflectionUtil.java 2012-03-16 16:54:57 UTC (rev 2003)
+++ trunk/java/org/apache/el/util/ReflectionUtil.java 2012-03-26 14:37:14 UTC (rev 2004)
@@ -23,9 +23,12 @@
import java.util.Map;
import java.util.Set;
+import javax.el.ELException;
import javax.el.MethodNotFoundException;
+import org.apache.el.lang.ELSupport;
+
/**
* Utilities for Managing Serialization and Reflection
*
@@ -106,12 +109,14 @@
* @param base the object that owns the method
* @param property the name of the method
* @param paramTypes the parameter types to use
+ * @param paramValues the parameter values
* @return the method specified
* @throws MethodNotFoundException
*/
@SuppressWarnings("null")
public static Method getMethod(Object base, Object property,
- Class<?>[] paramTypes) throws MethodNotFoundException {
+ Class<?>[] paramTypes, Object[] paramValues)
+ throws MethodNotFoundException {
if (base == null || property == null) {
throw new MethodNotFoundException(MessageFactory.get(
"error.method.notfound", base, property,
@@ -156,21 +161,37 @@
int exactMatch = 0;
boolean noMatch = false;
for (int i = 0; i < mParamCount; i++) {
- if (paramTypes[i] == null || mParamTypes[i].equals(paramTypes[i])) {
+ // Can't be null
+ if (mParamTypes[i].equals(paramTypes[i])) {
exactMatch++;
} else if (i == (mParamCount - 1) && m.isVarArgs()) {
Class<?> varType = mParamTypes[i].getComponentType();
for (int j = i; j < paramCount; j++) {
if (!isAssignableFrom(paramTypes[j], varType)) {
- break;
+ if (paramValues == null) {
+ noMatch = true;
+ break;
+ } else {
+ if (!isCoercibleFrom(paramValues[j], varType)) {
+ noMatch = true;
+ break;
+ }
+ }
}
// Don't treat a varArgs match as an exact match, it can
// lead to a varArgs method matching when the result
// should be ambiguous
}
} else if (!isAssignableFrom(paramTypes[i], mParamTypes[i])) {
- noMatch = true;
- break;
+ if (paramValues == null) {
+ noMatch = true;
+ break;
+ } else {
+ if (!isCoercibleFrom(paramValues[i], mParamTypes[i])) {
+ noMatch = true;
+ break;
+ }
+ }
}
}
if (noMatch) {
@@ -298,6 +319,17 @@
return targetClass.isAssignableFrom(src);
}
+ private static boolean isCoercibleFrom(Object src, Class<?> target) {
+ // TODO: This isn't pretty but it works. Significant refactoring would
+ // be required to avoid the exception.
+ try {
+ ELSupport.coerceToType(src, target);
+ } catch (ELException e) {
+ return false;
+ }
+ return true;
+ }
+
protected static final String paramString(Class<?>[] types) {
if (types != null) {
StringBuilder sb = new StringBuilder();
Modified: trunk/webapps/docs/changelog.xml
===================================================================
--- trunk/webapps/docs/changelog.xml 2012-03-16 16:54:57 UTC (rev 2003)
+++ trunk/webapps/docs/changelog.xml 2012-03-26 14:37:14 UTC (rev 2004)
@@ -35,6 +35,9 @@
<fix>
<bug>52776</bug>: Fix cleanup after JspFragment.invoke. Sumitted by
Karl von Randow. (markt)
</fix>
+ <fix>
+ <bug>52970</bug>: Fix enum as method invocation argument in EL.
(markt)
+ </fix>
</changelog>
</subsection>
</section>