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 e5202fc472a..a61e6232214 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 class TypeDescriptor implements Serializable { * @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 400f561c0e8..ec66a526829 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 class EvaluationException extends ExpressionException { * @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 class EvaluationException extends ExpressionException { * @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 4fb1fe8b422..42f8ffa4714 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 class ExpressionException extends RuntimeException { * @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 class ExpressionException extends RuntimeException { * @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 class ExpressionException extends RuntimeException { * @see java.lang.Throwable#getMessage() */ @Override + @Nullable public String getMessage() { return toDetailedString(); } @@ -132,6 +133,7 @@ public class ExpressionException extends RuntimeException { * 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 class ExpressionException extends RuntimeException { * 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 9753ef89857..1cb24e5d167 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 @@ package org.springframework.expression; @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 class ExpressionInvocationTargetException extends EvaluationException { 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 3debd82a46d..d6e173c5f14 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 @@ package org.springframework.expression.spel; @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 c6b49c6fae8..9817ba41349 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 class SpelEvaluationException extends EvaluationException { /** * 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 0c0747011cf..2356b6011c5 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 @@ package org.springframework.expression.spel; 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 8dbc4c13a9a..f6cbaa6c97c 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)) {