Author: markt
Date: Sat Mar 24 21:30:46 2012
New Revision: 1304931
URL: http://svn.apache.org/viewvc?rev=1304931&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=52970
Take account of coercion rules when invoking methods
Modified:
tomcat/trunk/java/org/apache/el/parser/AstValue.java
tomcat/trunk/java/org/apache/el/util/ReflectionUtil.java
Modified: tomcat/trunk/java/org/apache/el/parser/AstValue.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/parser/AstValue.java?rev=1304931&r1=1304930&r2=1304931&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/parser/AstValue.java (original)
+++ tomcat/trunk/java/org/apache/el/parser/AstValue.java Sat Mar 24 21:30:46
2012
@@ -230,7 +230,8 @@ public final class AstValue extends Simp
@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 @@ public final class AstValue extends Simp
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 @@ public final class AstValue extends Simp
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: tomcat/trunk/java/org/apache/el/util/ReflectionUtil.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/el/util/ReflectionUtil.java?rev=1304931&r1=1304930&r2=1304931&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/el/util/ReflectionUtil.java (original)
+++ tomcat/trunk/java/org/apache/el/util/ReflectionUtil.java Sat Mar 24
21:30:46 2012
@@ -23,8 +23,11 @@ import java.util.HashMap;
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 @@ public class ReflectionUtil {
* @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,
@@ -163,15 +168,30 @@ public class ReflectionUtil {
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) {
@@ -299,6 +319,17 @@ public class ReflectionUtil {
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();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]