Author: henrib
Date: Sat May 1 09:48:56 2010
New Revision: 939962
URL: http://svn.apache.org/viewvc?rev=939962&view=rev
Log:
JEXL-101: fixed varargs handling in MethodExecutor and MethodKey; added test
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/MethodExecutor.java
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/MethodKey.java
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/MethodTest.java
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/MethodExecutor.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/MethodExecutor.java?rev=939962&r1=939961&r2=939962&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/MethodExecutor.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/MethodExecutor.java
Sat May 1 09:48:56 2010
@@ -67,13 +67,13 @@ public final class MethodExecutor extend
/** {...@inheritdoc} */
@Override
- public Object tryExecute(String name, Object o, Object[] args) {
+ public Object tryExecute(String name, Object obj, Object[] args) {
MethodKey tkey = new MethodKey(name, args);
// let's assume that invocation will fly if the declaring class is the
// same and arguments have the same type
- if (objectClass.equals(o.getClass()) && tkey.equals(key)) {
+ if (objectClass.equals(obj.getClass()) && tkey.equals(key)) {
try {
- return execute(o, args);
+ return execute(obj, args);
} catch (InvocationTargetException xinvoke) {
return TRY_FAILED; // fail
} catch (IllegalAccessException xill) {
@@ -127,35 +127,28 @@ public final class MethodExecutor extend
* to fit the method declaration.
*/
protected Object[] handleVarArg(Class<?> type, int index, Object[] actual)
{
- // if no values are being passed into the vararg
- if (actual.length == index) {
- // create an empty array of the expected type
- actual = new Object[]{Array.newInstance(type, 0)};
- } else if (actual.length == index + 1) {
- // if one value is being passed into the vararg
- // make sure the last arg is an array of the expected type
- if (MethodKey.isInvocationConvertible(type,
- actual[index].getClass(),
- false)) {
- // create a 1-length array to hold and replace the last param
+ final int size = actual.length - index;
+ // if no values are being passed into the vararg, size == 0
+ if (size == 1) {
+ // if one non-null value is being passed into the vararg,
+ // make the last arg an array of the expected type
+ if (actual[index] != null) {
+ // create a 1-length array to hold and replace the last
argument
Object lastActual = Array.newInstance(type, 1);
Array.set(lastActual, 0, actual[index]);
actual[index] = lastActual;
}
- } else if (actual.length > index + 1) {
- // if multiple values are being passed into the vararg
- // put the last and extra actual in an array of the expected type
- int size = actual.length - index;
+ } else {
+ // if no or multiple values are being passed into the vararg,
+ // put them in an array of the expected type
Object lastActual = Array.newInstance(type, size);
for (int i = 0; i < size; i++) {
Array.set(lastActual, i, actual[index + i]);
}
- // put all into a new actual array of the appropriate size
+ // put all arguments into a new actual array of the appropriate
size
Object[] newActual = new Object[index + 1];
- for (int i = 0; i < index; i++) {
- newActual[i] = actual[i];
- }
+ System.arraycopy(actual, 0, newActual, 0, index);
newActual[index] = lastActual;
// replace the old actual array
Modified:
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/MethodKey.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/MethodKey.java?rev=939962&r1=939961&r2=939962&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/MethodKey.java
(original)
+++
commons/proper/jexl/trunk/src/main/java/org/apache/commons/jexl2/internal/introspection/MethodKey.java
Sat May 1 09:48:56 2010
@@ -542,13 +542,11 @@ public final class MethodKey {
*/
private boolean isApplicable(T method, Class<?>[] classes) {
Class<?>[] methodArgs = getParameterTypes(method);
-
- if (methodArgs.length > classes.length) {
- // if there's just one more methodArg than class arg
- // and the last methodArg is an array, then treat it as a
vararg
- return methodArgs.length == classes.length + 1 &&
methodArgs[methodArgs.length - 1].isArray();
- }
- if (methodArgs.length == classes.length) {
+ // if samee number or args or
+ // there's just one more methodArg than class arg
+ // and the last methodArg is an array, then treat it as a vararg
+ if (methodArgs.length == classes.length
+ || methodArgs.length == classes.length + 1 &&
methodArgs[methodArgs.length - 1].isArray()) {
// this will properly match when the last methodArg
// is an array/varargs and the last class is the type of array
// (e.g. String when the method is expecting String...)
Modified:
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/MethodTest.java
URL:
http://svn.apache.org/viewvc/commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/MethodTest.java?rev=939962&r1=939961&r2=939962&view=diff
==============================================================================
---
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/MethodTest.java
(original)
+++
commons/proper/jexl/trunk/src/test/java/org/apache/commons/jexl2/MethodTest.java
Sat May 1 09:48:56 2010
@@ -29,9 +29,33 @@ public class MethodTest extends JexlTest
private static final String METHOD_STRING = "Method string";
- public static class TestClass {
- public String testVarArgs(Integer[] args) {
- return "Test";
+ public static class VarArgs {
+ public String callInts(Integer... args) {
+ int result = 0;
+ for (int i = 0; i < args.length; i++) {
+ result += args[i].intValue();
+ }
+ return "Varargs:"+result;
+ }
+
+ public String callMixed(Integer fixed, Integer... args) {
+ int result = fixed.intValue();
+ if (args != null) {
+ for (int i = 0; i < args.length; i++) {
+ result += args[i].intValue();
+ }
+ }
+ return "Mixed:"+result;
+ }
+
+ public String callMixed(String mixed, Integer... args) {
+ int result = 0;
+ if (args != null) {
+ for (int arg : args) {
+ result += arg;
+ }
+ }
+ return mixed+":"+result;
}
}
@@ -74,8 +98,26 @@ public class MethodTest extends JexlTest
}
public void testCallVarArgMethod() throws Exception {
- asserter.setVariable("test", new TestClass());
- asserter.assertExpression("test.testVarArgs(1,2,3,4,5)", "Test");
+ asserter.setVariable("test", new VarArgs());
+ asserter.assertExpression("test.callInts()", "Varargs:0");
+ asserter.assertExpression("test.callInts(1)", "Varargs:1");
+ asserter.assertExpression("test.callInts(1,2,3,4,5)", "Varargs:15");
+ }
+
+ public void testCallMixedVarArgMethod() throws Exception {
+ asserter.setVariable("test", new VarArgs());
+ asserter.assertExpression("test.callMixed(1)", "Mixed:1");
+ asserter.assertExpression("test.callMixed(1, null)", "Mixed:1");
+ asserter.assertExpression("test.callMixed(1,2)", "Mixed:3");
+ asserter.assertExpression("test.callMixed(1,2,3,4,5)", "Mixed:15");
+ }
+
+ public void testCallJexlVarArgMethod() throws Exception {
+ asserter.setVariable("test", new VarArgs());
+ asserter.assertExpression("test.callMixed('jexl')", "jexl:0");
+ asserter.assertExpression("test.callMixed('jexl', null)", "jexl:0");
+ asserter.assertExpression("test.callMixed('jexl', 2)", "jexl:2");
+ asserter.assertExpression("test.callMixed('jexl',2,3,4,5)", "jexl:14");
}
public void testInvoke() throws Exception {