Skip to content

Commit fa138d2

Browse files
committed
ReflectionHelper's isFirstEntryInArray properly handles empty arrays
Issue: SPR-12522
1 parent d40be6c commit fa138d2

File tree

2 files changed

+24
-52
lines changed

2 files changed

+24
-52
lines changed

spring-expression/src/main/java/org/springframework/expression/spel/support/ReflectionHelper.java

Lines changed: 14 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -281,8 +281,8 @@ static boolean convertArguments(TypeConverter converter, Object[] arguments, Obj
281281
// 1) the input argument was already compatible (ie. array of valid type) and nothing was done
282282
// 2) the input argument was correct type but not in an array so it was made into an array
283283
// 3) the input argument was the wrong type and got converted and put into an array
284-
if (argument != arguments[varargsPosition] &&
285-
!isFirstEntryInArray(argument, arguments[varargsPosition])) {
284+
if (argument != arguments[varargsPosition] &&
285+
!isFirstEntryInArray(argument, arguments[varargsPosition])) {
286286
conversionOccurred = true; // case 3
287287
}
288288
}
@@ -310,54 +310,19 @@ private static boolean isFirstEntryInArray(Object value, Object possibleArray) {
310310
return false;
311311
}
312312
Class<?> type = possibleArray.getClass();
313-
if (type.isArray()) {
314-
Class<?> componentType = type.getComponentType();
315-
if (componentType.isPrimitive()) {
316-
if (componentType == Boolean.TYPE) {
317-
return value instanceof Boolean &&
318-
((boolean[])possibleArray)[0] == (Boolean)value;
319-
}
320-
else if (componentType == Double.TYPE) {
321-
return value instanceof Double &&
322-
((double[])possibleArray)[0] == (Double)value;
323-
}
324-
else if (componentType == Float.TYPE) {
325-
return value instanceof Float &&
326-
((float[])possibleArray)[0] == (Float)value;
327-
}
328-
else if (componentType == Integer.TYPE) {
329-
return value instanceof Integer &&
330-
((int[])possibleArray)[0] == (Integer)value;
331-
}
332-
else if (componentType == Long.TYPE) {
333-
return value instanceof Long &&
334-
((long[])possibleArray)[0] == (Long)value;
335-
}
336-
else if (componentType == Short.TYPE) {
337-
return value instanceof Short &&
338-
((short[])possibleArray)[0] == (Short)value;
339-
}
340-
else if (componentType == Character.TYPE) {
341-
return value instanceof Character &&
342-
((char[])possibleArray)[0] == (Character)value;
343-
}
344-
else if (componentType == Byte.TYPE) {
345-
return value instanceof Byte &&
346-
((byte[])possibleArray)[0] == (Byte)value;
347-
}
348-
}
349-
else {
350-
return ((Object[])possibleArray)[0] == value;
351-
}
313+
if (!type.isArray() || Array.getLength(possibleArray) == 0 ||
314+
!ClassUtils.isAssignableValue(type.getComponentType(), value)) {
315+
return false;
352316
}
353-
return false;
317+
Object arrayValue = Array.get(possibleArray, 0);
318+
return (type.getComponentType().isPrimitive() ? arrayValue.equals(value) : arrayValue == value);
354319
}
355320

356321
/**
357-
* Package up the arguments so that they correctly match what is expected in parameterTypes. For example, if
358-
* parameterTypes is (int, String[]) because the second parameter was declared String... then if arguments is
359-
* [1,"a","b"] then it must be repackaged as [1,new String[]{"a","b"}] in order to match the expected
360-
* parameterTypes.
322+
* Package up the arguments so that they correctly match what is expected in parameterTypes.
323+
* For example, if parameterTypes is (int, String[]) because the second parameter was declared String...
324+
* then if arguments is [1,"a","b"] then it must be repackaged as [1,new String[]{"a","b"}] in order to
325+
* match the expected parameterTypes.
361326
* @param requiredParameterTypes the types of the parameters for the invocation
362327
* @param args the arguments to be setup ready for the invocation
363328
* @return a repackaged array of arguments where any varargs setup has been done
@@ -366,11 +331,9 @@ public static Object[] setupArgumentsForVarargsInvocation(Class<?>[] requiredPar
366331
// Check if array already built for final argument
367332
int parameterCount = requiredParameterTypes.length;
368333
int argumentCount = args.length;
369-
370-
if (parameterCount == args.length) {
371-
372-
}
373-
else if (parameterCount != args.length ||
334+
335+
// Check if repackaging is needed...
336+
if (parameterCount != args.length ||
374337
requiredParameterTypes[parameterCount - 1] !=
375338
(args[argumentCount - 1] != null ? args[argumentCount - 1].getClass() : null)) {
376339

spring-expression/src/test/java/org/springframework/expression/spel/SpelReproTests.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1879,13 +1879,22 @@ public void SPR9735() {
18791879
}
18801880

18811881
@Test
1882-
public void SPR12502() throws Exception {
1882+
public void SPR12502() {
18831883
SpelExpressionParser parser = new SpelExpressionParser();
18841884
Expression expression = parser.parseExpression("#root.getClass().getName()");
18851885
assertEquals(UnnamedUser.class.getName(), expression.getValue(new UnnamedUser()));
18861886
assertEquals(NamedUser.class.getName(), expression.getValue(new NamedUser()));
18871887
}
18881888

1889+
@Test
1890+
public void SPR12522() {
1891+
SpelExpressionParser parser = new SpelExpressionParser();
1892+
Expression expression = parser.parseExpression("T(java.util.Arrays).asList('')");
1893+
Object value = expression.getValue();
1894+
assertTrue(value instanceof List);
1895+
assertTrue(((List) value).isEmpty());
1896+
}
1897+
18891898

18901899
private static enum ABC { A, B, C }
18911900

0 commit comments

Comments
 (0)