Convert primitive array to Object[] when invoking varargs method in SpEL

Prior to this commit, SpEL incorrectly wrapped a primitive array in an
Object[] array when invoking Object[] varargs methods and constructors.

This commit addresses this by updating the convertArguments(...) method
in ReflectionHelper as follows when the user supplies the varargs
already packaged in a primitive array.

- When deciding whether to convert a single element passed as varargs,
  we now check if the argument is an array that is assignable to the
  varargs array type.

- When converting an array supplied as the varargs, we convert that
  array to the varargs array type.

Closes gh-33317
This commit is contained in:
Sam Brannen 2024-08-05 11:56:42 +03:00
parent 444e7eeb74
commit 8badae9d72
3 changed files with 9 additions and 9 deletions

View File

@ -311,11 +311,15 @@ public abstract class ReflectionHelper {
}
}
// If the argument type is assignable to the varargs component type, there is no need to
// convert it or wrap it in an array. For example, using StringToArrayConverter to
// convert a String containing a comma would result in the String being split and
// repackaged in an array when it should be used as-is.
else if (!sourceType.isAssignableTo(componentTypeDesc)) {
arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetType);
// convert it or wrap it in an array. For example, using StringToArrayConverter to convert
// a String containing a comma would result in the String being split and repackaged in an
// array when it should be used as-is. Similarly, if the argument is an array that is
// assignable to the varargs array type, there is no need to convert it.
else if (!sourceType.isAssignableTo(componentTypeDesc) ||
(sourceType.isArray() && !sourceType.isAssignableTo(targetType))) {
TypeDescriptor targetTypeToUse = (sourceType.isArray() ? targetType : componentTypeDesc);
arguments[varargsPosition] = converter.convertValue(argument, sourceType, targetTypeToUse);
}
// Possible outcomes of the above if-else block:
// 1) the input argument was null, and nothing was done.

View File

@ -23,7 +23,6 @@ import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.expression.Expression;
@ -357,7 +356,6 @@ class MethodInvocationTests extends AbstractExpressionTests {
evaluate("formatPrimitiveVarargs('x -> %s %s', '2', 3.0d)", "x -> 2 3", String.class);
}
@Disabled("Primitive array to Object[] conversion is not currently supported")
@Test
void testVarargsWithPrimitiveArrayToObjectArrayConversion() {
evaluate("formatObjectVarargs('x -> %s %s %s', new short[]{1, 2, 3})", "x -> 1 2 3", String.class); // short[] to Object[]

View File

@ -16,7 +16,6 @@
package org.springframework.expression.spel;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.springframework.expression.spel.standard.SpelExpressionParser;
@ -199,7 +198,6 @@ class VariableAndFunctionTests extends AbstractExpressionTests {
evaluate("#formatPrimitiveVarargs('x -> %s %s %s', new String[]{'1', '2', '3'})", "x -> 1 2 3", String.class); // String[] to int[]
}
@Disabled("Primitive array to Object[] conversion is not currently supported")
@Test
void functionFromMethodWithVarargsAndPrimitiveArrayToObjectArrayConversion() {
evaluate("#varargsObjectFunction(new short[]{1, 2, 3})", "[1, 2, 3]", String.class); // short[] to Object[]