Browse Source

Merge branch '6.0.x'

pull/31113/head
Juergen Hoeller 2 years ago
parent
commit
ecc0a6d2db
  1. 2
      spring-core/src/main/java/org/springframework/util/ClassUtils.java
  2. 84
      spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java
  3. 16
      spring-expression/src/main/java/org/springframework/expression/spel/standard/Token.java
  4. 21
      spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java

2
spring-core/src/main/java/org/springframework/util/ClassUtils.java

@ -1479,7 +1479,7 @@ public abstract class ClassUtils { @@ -1479,7 +1479,7 @@ public abstract class ClassUtils {
Assert.notNull(methodName, "Method name must not be null");
try {
Method method = clazz.getMethod(methodName, args);
return Modifier.isStatic(method.getModifiers()) ? method : null;
return (Modifier.isStatic(method.getModifiers()) ? method : null);
}
catch (NoSuchMethodException ex) {
return null;

84
spring-expression/src/main/java/org/springframework/expression/spel/standard/InternalSpelExpressionParser.java

@ -77,7 +77,6 @@ import org.springframework.expression.spel.ast.Ternary; @@ -77,7 +77,6 @@ import org.springframework.expression.spel.ast.Ternary;
import org.springframework.expression.spel.ast.TypeReference;
import org.springframework.expression.spel.ast.VariableReference;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@ -137,12 +136,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -137,12 +136,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
this.tokenStreamPointer = 0;
this.constructedNodes.clear();
SpelNodeImpl ast = eatExpression();
Assert.state(ast != null, "No node");
if (ast == null) {
throw new SpelParseException(this.expressionString, 0, SpelMessage.OOD);
}
Token t = peekToken();
if (t != null) {
throw new SpelParseException(t.startPos, SpelMessage.MORE_INPUT, toString(nextToken()));
throw new SpelParseException(this.expressionString, t.startPos, SpelMessage.MORE_INPUT, toString(nextToken()));
}
Assert.isTrue(this.constructedNodes.isEmpty(), "At least one node expected");
return new SpelExpression(expressionString, ast, this.configuration);
}
catch (InternalParseException ex) {
@ -254,20 +254,20 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -254,20 +254,20 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (tk == TokenKind.EQ) {
return new OpEQ(t.startPos, t.endPos, expr, rhExpr);
}
Assert.isTrue(tk == TokenKind.NE, "Not-equals token expected");
return new OpNE(t.startPos, t.endPos, expr, rhExpr);
if (tk == TokenKind.NE) {
return new OpNE(t.startPos, t.endPos, expr, rhExpr);
}
}
if (tk == TokenKind.INSTANCEOF) {
return new OperatorInstanceof(t.startPos, t.endPos, expr, rhExpr);
}
if (tk == TokenKind.MATCHES) {
return new OperatorMatches(this.patternCache, t.startPos, t.endPos, expr, rhExpr);
}
Assert.isTrue(tk == TokenKind.BETWEEN, "Between token expected");
return new OperatorBetween(t.startPos, t.endPos, expr, rhExpr);
if (tk == TokenKind.BETWEEN) {
return new OperatorBetween(t.startPos, t.endPos, expr, rhExpr);
}
}
return expr;
}
@ -304,8 +304,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -304,8 +304,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
else if (t.kind == TokenKind.DIV) {
expr = new OpDivide(t.startPos, t.endPos, expr, rhExpr);
}
else {
Assert.isTrue(t.kind == TokenKind.MOD, "Mod token expected");
else if (t.kind == TokenKind.MOD) {
expr = new OpModulus(t.startPos, t.endPos, expr, rhExpr);
}
}
@ -335,18 +334,21 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -335,18 +334,21 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// unaryExpression: (PLUS^ | MINUS^ | BANG^ | INC^ | DEC^) unaryExpression | primaryExpression ;
@Nullable
private SpelNodeImpl eatUnaryExpression() {
if (peekToken(TokenKind.PLUS, TokenKind.MINUS, TokenKind.NOT)) {
if (peekToken(TokenKind.NOT, TokenKind.PLUS, TokenKind.MINUS)) {
Token t = takeToken();
SpelNodeImpl expr = eatUnaryExpression();
Assert.state(expr != null, "No node");
if (expr == null) {
throw internalException(t.startPos, SpelMessage.OOD);
}
if (t.kind == TokenKind.NOT) {
return new OperatorNot(t.startPos, t.endPos, expr);
}
if (t.kind == TokenKind.PLUS) {
return new OpPlus(t.startPos, t.endPos, expr);
}
Assert.isTrue(t.kind == TokenKind.MINUS, "Minus token expected");
return new OpMinus(t.startPos, t.endPos, expr);
if (t.kind == TokenKind.MINUS) {
return new OpMinus(t.startPos, t.endPos, expr);
}
}
if (peekToken(TokenKind.INC, TokenKind.DEC)) {
Token t = takeToken();
@ -354,7 +356,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -354,7 +356,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
if (t.getKind() == TokenKind.INC) {
return new OpInc(t.startPos, t.endPos, false, expr);
}
return new OpDec(t.startPos, t.endPos, false, expr);
if (t.kind == TokenKind.DEC) {
return new OpDec(t.startPos, t.endPos, false, expr);
}
}
return eatPrimaryExpression();
}
@ -414,7 +418,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -414,7 +418,6 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
return pop();
}
if (peekToken() == null) {
// unexpectedly ran out of data
throw internalException(t.startPos, SpelMessage.OOD);
}
else {
@ -460,8 +463,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -460,8 +463,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private void eatConstructorArgs(List<SpelNodeImpl> accumulatedArguments) {
if (!peekToken(TokenKind.LPAREN)) {
throw new InternalParseException(new SpelParseException(this.expressionString,
positionOf(peekToken()), SpelMessage.MISSING_CONSTRUCTOR_ARGS));
throw internalException(positionOf(peekToken()), SpelMessage.MISSING_CONSTRUCTOR_ARGS);
}
consumeArguments(accumulatedArguments);
eatToken(TokenKind.RPAREN);
@ -472,7 +474,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -472,7 +474,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
*/
private void consumeArguments(List<SpelNodeImpl> accumulatedArguments) {
Token t = peekToken();
Assert.state(t != null, "Expected token");
if (t == null) {
return;
}
int pos = t.startPos;
Token next;
do {
@ -575,8 +579,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -575,8 +579,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatTypeReference() {
if (peekToken(TokenKind.IDENTIFIER)) {
Token typeName = peekToken();
Assert.state(typeName != null, "Expected token");
if (!"T".equals(typeName.stringValue())) {
if (typeName == null || !"T".equals(typeName.stringValue())) {
return false;
}
// It looks like a type reference but is T being used as a map key?
@ -605,8 +608,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -605,8 +608,7 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatNullReference() {
if (peekToken(TokenKind.IDENTIFIER)) {
Token nullToken = peekToken();
Assert.state(nullToken != null, "Expected token");
if (!"null".equalsIgnoreCase(nullToken.stringValue())) {
if (nullToken == null || !"null".equalsIgnoreCase(nullToken.stringValue())) {
return false;
}
nextToken();
@ -619,12 +621,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -619,12 +621,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
//projection: PROJECT^ expression RCURLY!;
private boolean maybeEatProjection(boolean nullSafeNavigation) {
Token t = peekToken();
if (!peekToken(TokenKind.PROJECT, true)) {
if (t == null || !peekToken(TokenKind.PROJECT, true)) {
return false;
}
Assert.state(t != null, "No token");
SpelNodeImpl expr = eatExpression();
Assert.state(expr != null, "No node");
if (expr == null) {
throw internalException(t.startPos, SpelMessage.OOD);
}
eatToken(TokenKind.RSQUARE);
this.constructedNodes.push(new Projection(nullSafeNavigation, t.startPos, t.endPos, expr));
return true;
@ -634,15 +637,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -634,15 +637,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
// map = LCURLY (key ':' value (COMMA key ':' value)*) RCURLY
private boolean maybeEatInlineListOrMap() {
Token t = peekToken();
if (!peekToken(TokenKind.LCURLY, true)) {
if (t == null || !peekToken(TokenKind.LCURLY, true)) {
return false;
}
Assert.state(t != null, "No token");
SpelNodeImpl expr = null;
Token closingCurly = peekToken();
if (peekToken(TokenKind.RCURLY, true)) {
if (closingCurly != null && peekToken(TokenKind.RCURLY, true)) {
// empty list '{}'
Assert.state(closingCurly != null, "No token");
expr = new InlineList(t.startPos, closingCurly.endPos);
}
else if (peekToken(TokenKind.COLON, true)) {
@ -695,12 +696,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -695,12 +696,13 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatIndexer() {
Token t = peekToken();
if (!peekToken(TokenKind.LSQUARE, true)) {
if (t == null || !peekToken(TokenKind.LSQUARE, true)) {
return false;
}
Assert.state(t != null, "No token");
SpelNodeImpl expr = eatExpression();
Assert.state(expr != null, "No node");
if (expr == null) {
throw internalException(t.startPos, SpelMessage.MISSING_SELECTION_EXPRESSION);
}
eatToken(TokenKind.RSQUARE);
this.constructedNodes.push(new Indexer(t.startPos, t.endPos, expr));
return true;
@ -708,10 +710,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -708,10 +710,9 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
private boolean maybeEatSelection(boolean nullSafeNavigation) {
Token t = peekToken();
if (!peekSelectToken()) {
if (t == null || !peekSelectToken()) {
return false;
}
Assert.state(t != null, "No token");
nextToken();
SpelNodeImpl expr = eatExpression();
if (expr == null) {
@ -889,9 +890,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser { @@ -889,9 +890,14 @@ class InternalSpelExpressionParser extends TemplateAwareExpressionParser {
//parenExpr : LPAREN! expression RPAREN!;
private boolean maybeEatParenExpression() {
if (peekToken(TokenKind.LPAREN)) {
nextToken();
Token t = nextToken();
if (t == null) {
return false;
}
SpelNodeImpl expr = eatExpression();
Assert.state(expr != null, "No node");
if (expr == null) {
throw internalException(t.startPos, SpelMessage.OOD);
}
eatToken(TokenKind.RPAREN);
push(expr);
return true;

16
spring-expression/src/main/java/org/springframework/expression/spel/standard/Token.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2021 the original author or authors.
* Copyright 2002-2023 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.
@ -65,7 +65,7 @@ class Token { @@ -65,7 +65,7 @@ class Token {
public boolean isNumericRelationalOperator() {
return (this.kind == TokenKind.GT || this.kind == TokenKind.GE || this.kind == TokenKind.LT ||
this.kind == TokenKind.LE || this.kind==TokenKind.EQ || this.kind==TokenKind.NE);
this.kind == TokenKind.LE || this.kind == TokenKind.EQ || this.kind == TokenKind.NE);
}
public String stringValue() {
@ -87,14 +87,14 @@ class Token { @@ -87,14 +87,14 @@ class Token {
@Override
public String toString() {
StringBuilder s = new StringBuilder();
s.append('[').append(this.kind.toString());
StringBuilder sb = new StringBuilder();
sb.append('[').append(this.kind);
if (this.kind.hasPayload()) {
s.append(':').append(this.data);
sb.append(':').append(this.data);
}
s.append(']');
s.append('(').append(this.startPos).append(',').append(this.endPos).append(')');
return s.toString();
sb.append(']');
sb.append('(').append(this.startPos).append(',').append(this.endPos).append(')');
return sb.toString();
}
}

21
spring-expression/src/test/java/org/springframework/expression/spel/standard/SpelParserTests.java

@ -39,7 +39,9 @@ import static org.springframework.expression.spel.SpelMessage.NON_TERMINATING_DO @@ -39,7 +39,9 @@ import static org.springframework.expression.spel.SpelMessage.NON_TERMINATING_DO
import static org.springframework.expression.spel.SpelMessage.NON_TERMINATING_QUOTED_STRING;
import static org.springframework.expression.spel.SpelMessage.NOT_AN_INTEGER;
import static org.springframework.expression.spel.SpelMessage.NOT_A_LONG;
import static org.springframework.expression.spel.SpelMessage.OOD;
import static org.springframework.expression.spel.SpelMessage.REAL_CANNOT_BE_LONG;
import static org.springframework.expression.spel.SpelMessage.RIGHT_OPERAND_PROBLEM;
import static org.springframework.expression.spel.SpelMessage.RUN_OUT_OF_ARGUMENTS;
import static org.springframework.expression.spel.SpelMessage.UNEXPECTED_DATA_AFTER_DOT;
import static org.springframework.expression.spel.SpelMessage.UNEXPECTED_ESCAPE_CHAR;
@ -76,8 +78,8 @@ class SpelParserTests { @@ -76,8 +78,8 @@ class SpelParserTests {
private static void assertNullOrEmptyExpressionIsRejected(ThrowingCallable throwingCallable) {
assertThatIllegalArgumentException()
.isThrownBy(throwingCallable)
.withMessage("'expressionString' must not be null or blank");
.isThrownBy(throwingCallable)
.withMessage("'expressionString' must not be null or blank");
}
@Test
@ -152,7 +154,13 @@ class SpelParserTests { @@ -152,7 +154,13 @@ class SpelParserTests {
assertParseException(() -> parser.parseRaw("new String(3"), RUN_OUT_OF_ARGUMENTS, 10);
assertParseException(() -> parser.parseRaw("new String("), RUN_OUT_OF_ARGUMENTS, 10);
assertParseException(() -> parser.parseRaw("\"abc"), NON_TERMINATING_DOUBLE_QUOTED_STRING, 0);
assertParseException(() -> parser.parseRaw("abc\""), NON_TERMINATING_DOUBLE_QUOTED_STRING, 3);
assertParseException(() -> parser.parseRaw("'abc"), NON_TERMINATING_QUOTED_STRING, 0);
assertParseException(() -> parser.parseRaw("abc'"), NON_TERMINATING_QUOTED_STRING, 3);
assertParseException(() -> parser.parseRaw("("), OOD, 0);
assertParseException(() -> parser.parseRaw(")"), OOD, 0);
assertParseException(() -> parser.parseRaw("+"), OOD, 0);
assertParseException(() -> parser.parseRaw("1+"), RIGHT_OPERAND_PROBLEM, 1);
}
@Test
@ -377,7 +385,7 @@ class SpelParserTests { @@ -377,7 +385,7 @@ class SpelParserTests {
private void checkNumberError(String expression, SpelMessage expectedMessage) {
assertParseExceptionThrownBy(() -> parser.parseRaw(expression))
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(expectedMessage));
.satisfies(ex -> assertThat(ex.getMessageCode()).isEqualTo(expectedMessage));
}
private static ThrowableAssertAlternative<SpelParseException> assertParseExceptionThrownBy(ThrowingCallable throwingCallable) {
@ -386,15 +394,18 @@ class SpelParserTests { @@ -386,15 +394,18 @@ class SpelParserTests {
private static void assertParseException(ThrowingCallable throwingCallable, SpelMessage expectedMessage, int expectedPosition) {
assertParseExceptionThrownBy(throwingCallable)
.satisfies(parseExceptionRequirements(expectedMessage, expectedPosition));
.satisfies(parseExceptionRequirements(expectedMessage, expectedPosition));
}
private static <E extends SpelParseException> Consumer<E> parseExceptionRequirements(
SpelMessage expectedMessage, int expectedPosition) {
return ex -> {
assertThat(ex.getMessageCode()).isEqualTo(expectedMessage);
assertThat(ex.getPosition()).isEqualTo(expectedPosition);
assertThat(ex.getMessage()).contains(ex.getExpressionString());
if (ex.getExpressionString() != null) {
assertThat(ex.getMessage()).contains(ex.getExpressionString());
}
};
}

Loading…
Cancel
Save