This commit ensures that methods declared in java.lang.Object (such as
toString() can be invoked on a JDK proxy instance in a SpEL expression.
Closes gh-25316
Prior to this commit, SpEL's ConstructorReference did not provide
support for arrays when generating a string representation of the
internal AST. For example, 'new String[3]' was represented as 'new
String()' instead of 'new String[3]'.
This commit introduces support for standard array construction and array
construction with initializers in ConstructorReference's toStringAST()
implementation.
Closes gh-29665
Prior to this commit, there were two bugs in the support for quotes
within String literals in SpEL expressions.
- Two double quotes ("") or two single quotes ('') were always replaced
with one double quote or one single quote, respectively, regardless
of which quote character was used to enclose the original String
literal. This resulted in the loss of one of the double quotes when
the String literal was enclosed in single quotes, and vice versa. For
example, 'x "" y' became 'x " y'.
- A single quote which was properly escaped in a String literal
enclosed within single quotes was not escaped in the AST string
representation of the expression. For example, 'x '' y' became 'x ' y'.
This commit fixes both of these related issues in StringLiteral and
overhauls the structure of ParsingTests.
Closes gh-29604, gh-28356
Prior to this commit, ternary and Elvis expressions enclosed in
parentheses (to account for operator precedence) were properly parsed
and evaluated; however, the corresponding toStringAST() implementations
did not enclose the results in parentheses. Consequently, the string
representation of the ASTs did not reflect the original semantics of
such expressions.
For example, given "(4 % 2 == 0 ? 1 : 0) * 10" as the expression to
parse and evaluate, the result of toStringAST() was previously
"(((4 % 2) == 0) ? 1 : 0 * 10)" instead of
"((((4 % 2) == 0) ? 1 : 0) * 10)", implying that 0 should be multiplied
by 10 instead of multiplying the result of the ternary expression by 10.
This commit addresses this by ensuring that SpEL ternary and Elvis
expressions are enclosed in parentheses in toStringAST().
Closes gh-29463
The antlr-based SpEL expression grammar file (SpringExpressions.g) was
introduced during initial development and prototyping of the Spring
Expression language; however, it was quickly abandoned in favor of a
handcrafted implementation. Consequently, it has become obsolete over
time and has never been actively maintained.
This commit therefore removes the obsolete SpEL expression grammar file.
Closes gh-28425
Attempting to create a large array in a SpEL expression can result in
an OutOfMemoryError. Although the JVM recovers from that, the error
message is not very helpful to the user.
This commit improves the diagnostics in SpEL for large array creation
by throwing a SpelEvaluationException with a meaningful error message
in order to improve diagnostics for the user.
Closes gh-28145
Prior to this commit, SpEL was able to recover from an error that
occurred while running a CompiledExpression; however, SpEL was not able
to recover from an error that occurred while compiling the expression
(such as a java.lang.VerifyError). The latter can occur when multiple
threads concurrently change types involved in the expression, such as
the concrete type of a custom variable registered via
EvaluationContext.setVariable(...), which can result in SpEL generating
invalid bytecode.
This commit addresses this issue by catching exceptions thrown while
compiling an expression and updating the `failedAttempts` and
`interpretedCount` counters accordingly. If an exception is caught
while operating in SpelCompilerMode.IMMEDIATE mode, the exception will
be propagated via a SpelEvaluationException with a new
SpelMessage.EXCEPTION_COMPILING_EXPRESSION error category.
Closes gh-28043
The test case is intended to be for the method 'withRootObject()', but
actually it's copied from the previous test method that does not use
'withRootObject()'.
This commit fixes the propertyReadWriteWithRootObject() test method in
PropertyAccessTests.
Closes gh-27905
This commit replaces the use of Collections.unmodifiableList/Set/Map
with the corresponding 'of(...)' factory methods introduced in Java 9.
Closes gh-27824
Prior to this commit, if a single null value was passed to a method with
a varargs array of type java.util.Optional, that null value was passed
unmodified. On the contrary, a null passed with additional values to
such a method resulted in the null being converted to Optional.empty().
This commit ensures that a single null value is also converted to
Optional.empty() for such SpEL expressions.
Closes gh-27795
A regression was introduced in gh-27582. Specifically, when null is
supplied as the single argument for a varargs parameter in a method or
function in a SpEL expression, ReflectionHelper currently throws a
NullPointerException instead of leaving the null value unchanged.
This commit fixes this regression.
Closes gh-27719
Prior to this commit, the SpEL relational operators for comparison
would have the following problem:
* their implementation would claim that incompatible types
could be compared and later fail during comparison
* not delegate the comparison to the actual `TypeComparator`
implementation but rely on operator specifics
This commit ensures that the `TypeComparator` implementation is used for
both `canCompare` and `compare` calls in the operators.
See gh-1581
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 also applies additional clean-up tasks such as the following.
- final fields
This commit also makes use of java.lang.String.repeat(int) in OptMultiply.
This has only been applied to `src/main/java`.
In order to be able to use text blocks and other new Java language
features, we are upgrading to a recent version of Checkstyle.
The latest version of spring-javaformat-checkstyle (0.0.28) is built
against Checkstyle 8.32 which does not include support for language
features such as text blocks. Support for text blocks was added in
Checkstyle 8.36.
In addition, there is a binary compatibility issue between
spring-javaformat-checkstyle 0.0.28 and Checkstyle 8.42. Thus we cannot
use Checkstyle 8.42 or higher.
In this commit, we therefore upgrade to spring-javaformat-checkstyle
0.0.28 and downgrade to Checkstyle 8.41.
This change is being applied to `5.3.x` as well as `main` in order to
benefit from the enhanced checking provided in more recent versions of
Checkstyle.
Closes gh-27481
To slightly improve performance, this commit switches to
StringBuilder.append(char) instead of StringBuilder.append(String)
whenever we append a single character to a StringBuilder.
Closes gh-27098
This commit allows the spring-expression module to be more easily repackaged
for embedding in third-party JARs -- for example, via the Shadow Gradle plugin.
Closes gh-26779
The migration from JUnit 4 assertions to AssertJ assertions resulted in
several unnecessary casts from int to long that actually cause
assertions to pass when they should otherwise fail.
This commit fixes all such bugs for the pattern `.isNotEqualTo((long)`.
Prior to this commit, The "auto grow" feature in SpEL expressions only
worked for element types with a default constructor. For example, auto
grow did not work for a list of BigDecimal elements.
This commit inserts a null value in the list when no default
constructor can be found for the element type.
Closes gh-25367
Spring Framework 5.1.8 introduced a regression for the compilation of
SpEL expressions referencing a method declared in an interface. An
attempt to compile such an expression resulted in a
SpelEvaluationException caused by an IncompatibleClassChangeError.
This commit fixes this regression by adding explicit support in
ReflectivePropertyAccessor.OptimalPropertyAccessor.generateCode() for
methods declared in interfaces.
Closes gh-24357
When index == arrayLength, the array index is also out of bounds.
For this scenario, a SpelEvaluationException should be thrown instead
of ArrayIndexOutOfBoundsException.
Closes gh-23658
Prior to this commit, a lot of work had been done to prevent improper
use of testing Framework APIs throughout the codebase; however, there
were still some loopholes.
This commit addresses these loopholes by introducing additional
Checkstyle rules (and modifying existing rules) to prevent improper use
of testing framework APIs in production code as well as in test code.
- Checkstyle rules for banned imports have been refactored into
multiple rules specific to JUnit 3, JUnit 4, JUnit Jupiter, and
TestNG.
- Accidental usage of org.junit.Assume has been switched to
org.junit.jupiter.api.Assumptions.
- All test classes now reside under org.springframework packages.
- All test classes (including abstract test classes) now conform to the
`*Tests` naming convention.
- As an added bonus, tests in the renamed
ScenariosForSpringSecurityExpressionTests are now included in the
build.
- Dead JUnit 4 parameterized code has been removed from
DefaultServerWebExchangeCheckNotModifiedTests.
Closes gh-22962