From 2e98a8a2a4d905c8d53de8d6fc02ea67e084cfad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20Deleuze?= Date: Wed, 20 Mar 2024 09:56:53 +0100 Subject: [PATCH] Refine null-safety in spring-expression See gh-32475 --- .../springframework/core/convert/TypeDescriptor.java | 2 +- .../expression/EvaluationException.java | 6 ++++-- .../expression/ExpressionException.java | 7 +++++-- .../ExpressionInvocationTargetException.java | 6 ++++-- .../expression/spel/InternalParseException.java | 5 ++++- .../expression/spel/SpelEvaluationException.java | 11 +++++++---- .../springframework/expression/spel/SpelMessage.java | 4 +++- .../expression/spel/ast/SpelNodeImpl.java | 2 +- 8 files changed, 29 insertions(+), 14 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java b/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java index e5202fc472a3..a61e62322147 100644 --- a/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java +++ b/spring-core/src/main/java/org/springframework/core/convert/TypeDescriptor.java @@ -463,7 +463,7 @@ public TypeDescriptor getMapValueTypeDescriptor() { * @see #narrow(Object) */ @Nullable - public TypeDescriptor getMapValueTypeDescriptor(Object mapValue) { + public TypeDescriptor getMapValueTypeDescriptor(@Nullable Object mapValue) { return narrow(mapValue, getMapValueTypeDescriptor()); } diff --git a/spring-expression/src/main/java/org/springframework/expression/EvaluationException.java b/spring-expression/src/main/java/org/springframework/expression/EvaluationException.java index 400f561c0e84..ec66a5268294 100644 --- a/spring-expression/src/main/java/org/springframework/expression/EvaluationException.java +++ b/spring-expression/src/main/java/org/springframework/expression/EvaluationException.java @@ -16,6 +16,8 @@ package org.springframework.expression; +import org.springframework.lang.Nullable; + /** * Represent an exception that occurs during expression evaluation. * @@ -38,7 +40,7 @@ public EvaluationException(String message) { * @param message description of the problem that occurred * @param cause the underlying cause of this exception */ - public EvaluationException(String message, Throwable cause) { + public EvaluationException(String message, @Nullable Throwable cause) { super(message,cause); } @@ -66,7 +68,7 @@ public EvaluationException(String expressionString, String message) { * @param message description of the problem that occurred * @param cause the underlying cause of this exception */ - public EvaluationException(int position, String message, Throwable cause) { + public EvaluationException(int position, String message, @Nullable Throwable cause) { super(position, message, cause); } diff --git a/spring-expression/src/main/java/org/springframework/expression/ExpressionException.java b/spring-expression/src/main/java/org/springframework/expression/ExpressionException.java index 4fb1fe8b4225..42f8ffa47146 100644 --- a/spring-expression/src/main/java/org/springframework/expression/ExpressionException.java +++ b/spring-expression/src/main/java/org/springframework/expression/ExpressionException.java @@ -49,7 +49,7 @@ public ExpressionException(String message) { * @param message a descriptive message * @param cause the underlying cause of this exception */ - public ExpressionException(String message, Throwable cause) { + public ExpressionException(String message, @Nullable Throwable cause) { super(message, cause); this.expressionString = null; this.position = 0; @@ -95,7 +95,7 @@ public ExpressionException(int position, String message) { * @param message a descriptive message * @param cause the underlying cause of this exception */ - public ExpressionException(int position, String message, Throwable cause) { + public ExpressionException(int position, String message, @Nullable Throwable cause) { super(message, cause); this.expressionString = null; this.position = position; @@ -124,6 +124,7 @@ public final int getPosition() { * @see java.lang.Throwable#getMessage() */ @Override + @Nullable public String getMessage() { return toDetailedString(); } @@ -132,6 +133,7 @@ public String getMessage() { * Return a detailed description of this exception, including the expression * String and position (if available) as well as the actual exception message. */ + @Nullable public String toDetailedString() { if (this.expressionString != null) { StringBuilder output = new StringBuilder(); @@ -156,6 +158,7 @@ public String toDetailedString() { * that caused the failure. * @since 4.0 */ + @Nullable public String getSimpleMessage() { return super.getMessage(); } diff --git a/spring-expression/src/main/java/org/springframework/expression/ExpressionInvocationTargetException.java b/spring-expression/src/main/java/org/springframework/expression/ExpressionInvocationTargetException.java index 9753ef898578..1cb24e5d1672 100644 --- a/spring-expression/src/main/java/org/springframework/expression/ExpressionInvocationTargetException.java +++ b/spring-expression/src/main/java/org/springframework/expression/ExpressionInvocationTargetException.java @@ -16,6 +16,8 @@ package org.springframework.expression; +import org.springframework.lang.Nullable; + /** * This exception wraps (as cause) a checked exception thrown by some method that SpEL * invokes. It differs from a SpelEvaluationException because this indicates the @@ -28,7 +30,7 @@ @SuppressWarnings("serial") public class ExpressionInvocationTargetException extends EvaluationException { - public ExpressionInvocationTargetException(int position, String message, Throwable cause) { + public ExpressionInvocationTargetException(int position, String message, @Nullable Throwable cause) { super(position, message, cause); } @@ -40,7 +42,7 @@ public ExpressionInvocationTargetException(String expressionString, String messa super(expressionString, message); } - public ExpressionInvocationTargetException(String message, Throwable cause) { + public ExpressionInvocationTargetException(String message, @Nullable Throwable cause) { super(message, cause); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/InternalParseException.java b/spring-expression/src/main/java/org/springframework/expression/spel/InternalParseException.java index 3debd82a46d0..d6e173c5f140 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/InternalParseException.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/InternalParseException.java @@ -16,6 +16,8 @@ package org.springframework.expression.spel; +import org.springframework.lang.Nullable; + /** * Wraps a real parse exception. This exception flows to the top parse method and then * the wrapped exception is thrown as the real problem. @@ -26,11 +28,12 @@ @SuppressWarnings("serial") public class InternalParseException extends RuntimeException { - public InternalParseException(SpelParseException cause) { + public InternalParseException(@Nullable SpelParseException cause) { super(cause); } @Override + @Nullable public SpelParseException getCause() { return (SpelParseException) super.getCause(); } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/SpelEvaluationException.java b/spring-expression/src/main/java/org/springframework/expression/spel/SpelEvaluationException.java index c6b49c6fae86..9817ba413490 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/SpelEvaluationException.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/SpelEvaluationException.java @@ -17,6 +17,7 @@ package org.springframework.expression.spel; import org.springframework.expression.EvaluationException; +import org.springframework.lang.Nullable; /** * Root exception for Spring EL related exceptions. @@ -35,28 +36,29 @@ public class SpelEvaluationException extends EvaluationException { private final SpelMessage message; + @Nullable private final Object[] inserts; - public SpelEvaluationException(SpelMessage message, Object... inserts) { + public SpelEvaluationException(SpelMessage message, @Nullable Object... inserts) { super(message.formatMessage(inserts)); this.message = message; this.inserts = inserts; } - public SpelEvaluationException(int position, SpelMessage message, Object... inserts) { + public SpelEvaluationException(int position, SpelMessage message, @Nullable Object... inserts) { super(position, message.formatMessage(inserts)); this.message = message; this.inserts = inserts; } - public SpelEvaluationException(int position, Throwable cause, SpelMessage message, Object... inserts) { + public SpelEvaluationException(int position, @Nullable Throwable cause, SpelMessage message, @Nullable Object... inserts) { super(position, message.formatMessage(inserts), cause); this.message = message; this.inserts = inserts; } - public SpelEvaluationException(Throwable cause, SpelMessage message, Object... inserts) { + public SpelEvaluationException(@Nullable Throwable cause, SpelMessage message, @Nullable Object... inserts) { super(message.formatMessage(inserts), cause); this.message = message; this.inserts = inserts; @@ -80,6 +82,7 @@ public SpelMessage getMessageCode() { /** * Return the message inserts. */ + @Nullable public Object[] getInserts() { return this.inserts; } diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java b/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java index 0c0747011cf1..2356b6011c59 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/SpelMessage.java @@ -18,6 +18,8 @@ import java.text.MessageFormat; +import org.springframework.lang.Nullable; + /** * Contains all the messages that can be produced by the Spring Expression Language. * @@ -313,7 +315,7 @@ public enum SpelMessage { * @return a formatted message * @since 4.3.5 */ - public String formatMessage(Object... inserts) { + public String formatMessage(@Nullable Object... inserts) { StringBuilder formattedMessage = new StringBuilder(); formattedMessage.append("EL").append(this.code); if (this.kind == Kind.ERROR) { diff --git a/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java b/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java index 8dbc4c13a9a6..f6cbaa6c97c7 100644 --- a/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java +++ b/spring-expression/src/main/java/org/springframework/expression/spel/ast/SpelNodeImpl.java @@ -71,7 +71,7 @@ public abstract class SpelNodeImpl implements SpelNode, Opcodes { protected volatile String exitTypeDescriptor; - public SpelNodeImpl(int startPos, int endPos, SpelNodeImpl... operands) { + public SpelNodeImpl(int startPos, int endPos, @Nullable SpelNodeImpl... operands) { this.startPos = startPos; this.endPos = endPos; if (!ObjectUtils.isEmpty(operands)) {