Fix SpEL vararg method invocation for strings containing commas
Prior to this commit, if a SpEL expression invoked a method or registered function that declares a String varargs argument, there were sometimes issues with converting the input arguments into the varargs array argument. Specifically, if the expression supplied a single String argument containing a comma for the varargs (such as "a,b"), SpEL's ReflectionHelper.convertArguments() method incorrectly converted that single String to an array via the ConversionService, which indirectly converted that String using the StringToArrayConverter, which converts a comma-delimited String to an array. Thus, "a,b" effectively got converted to a two-dimensional array ["a", "b"] instead of simply ["a,b"]. This commit fixes this bug by avoiding use of the TypeConverter and ConversionService for single arguments supplied as varargs when the single argument's type matches the varargs array component type. Closes gh-27582
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -46,6 +46,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
|
||||
*
|
||||
* @author Andy Clement
|
||||
* @author Phillip Webb
|
||||
* @author Sam Brannen
|
||||
*/
|
||||
public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
@@ -233,26 +234,54 @@ public class MethodInvocationTests extends AbstractExpressionTests {
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation01() {
|
||||
// Calling 'public int aVarargsMethod(String... strings)'
|
||||
//evaluate("aVarargsMethod('a','b','c')", 3, Integer.class);
|
||||
//evaluate("aVarargsMethod('a')", 1, Integer.class);
|
||||
// Calling 'public int aVarargsMethod(String... strings)' - returns number of arguments
|
||||
evaluate("aVarargsMethod('a','b','c')", 3, Integer.class);
|
||||
evaluate("aVarargsMethod('a')", 1, Integer.class);
|
||||
evaluate("aVarargsMethod()", 0, Integer.class);
|
||||
evaluate("aVarargsMethod(1,2,3)", 3, Integer.class); // all need converting to strings
|
||||
evaluate("aVarargsMethod(1)", 1, Integer.class); // needs string conversion
|
||||
evaluate("aVarargsMethod(1,'a',3.0d)", 3, Integer.class); // first and last need conversion
|
||||
// evaluate("aVarargsMethod(new String[]{'a','b','c'})", 3, Integer.class);
|
||||
evaluate("aVarargsMethod(new String[]{'a','b','c'})", 3, Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation02() {
|
||||
// Calling 'public int aVarargsMethod2(int i, String... strings)' - returns int+length_of_strings
|
||||
// Calling 'public int aVarargsMethod2(int i, String... strings)' - returns int + length_of_strings
|
||||
evaluate("aVarargsMethod2(5,'a','b','c')", 8, Integer.class);
|
||||
evaluate("aVarargsMethod2(2,'a')", 3, Integer.class);
|
||||
evaluate("aVarargsMethod2(4)", 4, Integer.class);
|
||||
evaluate("aVarargsMethod2(8,2,3)", 10, Integer.class);
|
||||
evaluate("aVarargsMethod2(9)", 9, Integer.class);
|
||||
evaluate("aVarargsMethod2(2,'a',3.0d)", 4, Integer.class);
|
||||
// evaluate("aVarargsMethod2(8,new String[]{'a','b','c'})", 11, Integer.class);
|
||||
evaluate("aVarargsMethod2(8,new String[]{'a','b','c'})", 11, Integer.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testVarargsInvocation03() {
|
||||
// Calling 'public int aVarargsMethod3(String str1, String... strings)' - returns all strings concatenated with "-"
|
||||
|
||||
// No conversion necessary
|
||||
evaluate("aVarargsMethod3('x')", "x", String.class);
|
||||
evaluate("aVarargsMethod3('x', 'a')", "x-a", String.class);
|
||||
evaluate("aVarargsMethod3('x', 'a', 'b', 'c')", "x-a-b-c", String.class);
|
||||
|
||||
// Conversion necessary
|
||||
evaluate("aVarargsMethod3(9)", "9", String.class);
|
||||
evaluate("aVarargsMethod3(8,2,3)", "8-2-3", String.class);
|
||||
evaluate("aVarargsMethod3('2','a',3.0d)", "2-a-3.0", String.class);
|
||||
evaluate("aVarargsMethod3('8',new String[]{'a','b','c'})", "8-a-b-c", String.class);
|
||||
|
||||
// Individual string contains a comma with multiple varargs arguments
|
||||
evaluate("aVarargsMethod3('foo', ',', 'baz')", "foo-,-baz", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar', ',baz')", "foo-bar-,baz", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,', 'baz')", "foo-bar,-baz", String.class);
|
||||
|
||||
// Individual string contains a comma with single varargs argument.
|
||||
// Reproduces https://github.com/spring-projects/spring-framework/issues/27582
|
||||
evaluate("aVarargsMethod3('foo', ',')", "foo-,", String.class);
|
||||
evaluate("aVarargsMethod3('foo', ',bar')", "foo-,bar", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,')", "foo-bar,", String.class);
|
||||
evaluate("aVarargsMethod3('foo', 'bar,baz')", "foo-bar,baz", String.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2016 the original author or authors.
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@@ -28,6 +28,7 @@ import org.springframework.util.ObjectUtils;
|
||||
///CLOVER:OFF
|
||||
@SuppressWarnings("unused")
|
||||
public class Inventor {
|
||||
|
||||
private String name;
|
||||
public String _name;
|
||||
public String _name_;
|
||||
@@ -202,8 +203,14 @@ public class Inventor {
|
||||
return strings.length + i;
|
||||
}
|
||||
|
||||
public Inventor(String... strings) {
|
||||
public String aVarargsMethod3(String str1, String... strings) {
|
||||
if (ObjectUtils.isEmpty(strings)) {
|
||||
return str1;
|
||||
}
|
||||
return str1 + "-" + String.join("-", strings);
|
||||
}
|
||||
|
||||
public Inventor(String... strings) {
|
||||
}
|
||||
|
||||
public boolean getSomeProperty() {
|
||||
|
||||
Reference in New Issue
Block a user