diff --git a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java index 35ac1ca121..e6c561392a 100644 --- a/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java +++ b/org.springframework.expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java @@ -316,18 +316,73 @@ public class ReflectionHelper { if (argumentCount >= parameterCount) { arraySize = argumentCount - (parameterCount - 1); } - Object[] repackagedArguments = (Object[]) Array.newInstance(requiredParameterTypes[parameterCount - 1].getComponentType(), - arraySize); - // Copy all but the varargs arguments - for (int i = 0; i < arraySize; i++) { - repackagedArguments[i] = args[parameterCount + i - 1]; - } + // Create an array for the varargs arguments Object[] newArgs = new Object[parameterCount]; for (int i = 0; i < newArgs.length - 1; i++) { newArgs[i] = args[i]; } - newArgs[newArgs.length - 1] = repackagedArguments; + // Now sort out the final argument, which is the varargs one. Before entering this + // method the arguments should have been converted to the box form of the required type. + Class componentType = requiredParameterTypes[parameterCount-1].getComponentType(); + if (componentType.isPrimitive()) { + if (componentType==Integer.TYPE) { + int[] repackagedArguments = (int[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Integer)args[parameterCount + i - 1]).intValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Float.TYPE) { + float[] repackagedArguments = (float[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Float)args[parameterCount + i - 1]).floatValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Double.TYPE) { + double[] repackagedArguments = (double[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Double)args[parameterCount + i - 1]).doubleValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Short.TYPE) { + short[] repackagedArguments = (short[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Short)args[parameterCount + i - 1]).shortValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Character.TYPE) { + char[] repackagedArguments = (char[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Character)args[parameterCount + i - 1]).charValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Byte.TYPE) { + byte[] repackagedArguments = (byte[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Byte)args[parameterCount + i - 1]).byteValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Boolean.TYPE) { + boolean[] repackagedArguments = (boolean[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Boolean)args[parameterCount + i - 1]).booleanValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } else if(componentType==Long.TYPE) { + long[] repackagedArguments = (long[]) Array.newInstance(componentType, arraySize); + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = ((Long)args[parameterCount + i - 1]).longValue(); + } + newArgs[newArgs.length - 1] = repackagedArguments; + } + } else { + Object[] repackagedArguments = (Object[]) Array.newInstance(componentType, arraySize); + // Copy all but the varargs arguments + for (int i = 0; i < arraySize; i++) { + repackagedArguments[i] = args[parameterCount + i - 1]; + } + newArgs[newArgs.length - 1] = repackagedArguments; + } return newArgs; } return args; diff --git a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java index f98ca94dd9..a87dc65547 100644 --- a/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java +++ b/org.springframework.expression/src/test/java/org/springframework/expression/spel/SpringEL300Tests.java @@ -36,11 +36,13 @@ import org.springframework.expression.EvaluationContext; import org.springframework.expression.EvaluationException; import org.springframework.expression.Expression; import org.springframework.expression.ExpressionParser; +import org.springframework.expression.MethodExecutor; import org.springframework.expression.ParserContext; import org.springframework.expression.PropertyAccessor; import org.springframework.expression.TypedValue; import org.springframework.expression.spel.standard.SpelExpression; import org.springframework.expression.spel.standard.SpelExpressionParser; +import org.springframework.expression.spel.support.ReflectiveMethodResolver; import org.springframework.expression.spel.support.ReflectivePropertyAccessor; import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.expression.spel.support.StandardTypeLocator; @@ -811,5 +813,109 @@ public class SpringEL300Tests extends ExpressionTestCase { assertEquals("[D(aaa), D(bbb), D(ccc)]",value3.toString()); } + @Test + public void varargsAndPrimitives_SPR8174() throws Exception { + EvaluationContext emptyEvalContext = new StandardEvaluationContext(); + List args = new ArrayList(); + + args.add(TypeDescriptor.forObject(34L)); + ReflectionUtil ru = new ReflectionUtil(); + MethodExecutor me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"methodToCall",args); + + args.set(0,TypeDescriptor.forObject(23)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, 45); + + args.set(0,TypeDescriptor.forObject(23f)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, 45f); + + args.set(0,TypeDescriptor.forObject(23d)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, 23d); + + args.set(0,TypeDescriptor.forObject((short)23)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, (short)23); + + args.set(0,TypeDescriptor.forObject(23L)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, 23L); + + args.set(0,TypeDescriptor.forObject((char)65)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, (char)65); + + args.set(0,TypeDescriptor.forObject((byte)23)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, (byte)23); + + args.set(0,TypeDescriptor.forObject(true)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"foo",args); + me.execute(emptyEvalContext, ru, true); + + // trickier: + args.set(0,TypeDescriptor.forObject(12)); + args.add(TypeDescriptor.forObject(23f)); + me = new ReflectiveMethodResolver().resolve(emptyEvalContext,ru,"bar",args); + me.execute(emptyEvalContext, ru, 12,23f); + + } + + + + public class ReflectionUtil { + public Object methodToCall(T param) { + System.out.println(param+" "+param.getClass()); + return "Object methodToCall(T param)"; + } + + public void foo(int... array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(float...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(double...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(short...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(long...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(boolean...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(char...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + public void foo(byte...array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + + public void bar(int... array) { + if (array.length==0) { + throw new RuntimeException(); + } + } + } }