From 8f2ed66b4af93df15ef09681efd40a31b75d976d Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Tue, 27 May 2014 17:43:31 +0200 Subject: [PATCH] ServletRequestAttributes considers standard Number subclasses (as defined in NumberUtils) as immutable Issue: SPR-11738 --- .../org/springframework/util/NumberUtils.java | 22 +++++++++++++++++++ .../request/ServletRequestAttributes.java | 17 +++++++++++--- 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/spring-core/src/main/java/org/springframework/util/NumberUtils.java b/spring-core/src/main/java/org/springframework/util/NumberUtils.java index 8236c9edb4..c43ebaaf55 100644 --- a/spring-core/src/main/java/org/springframework/util/NumberUtils.java +++ b/spring-core/src/main/java/org/springframework/util/NumberUtils.java @@ -21,6 +21,9 @@ import java.math.BigInteger; import java.text.DecimalFormat; import java.text.NumberFormat; import java.text.ParseException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; /** * Miscellaneous utility methods for number conversion and parsing. @@ -37,6 +40,25 @@ public abstract class NumberUtils { private static final BigInteger LONG_MAX = BigInteger.valueOf(Long.MAX_VALUE); + /** + * Standard number types (all immutable): + * Byte, Short, Integer, Long, BigInteger, Float, Double, BigDecimal. + */ + public static final Set> STANDARD_NUMBER_TYPES; + + static { + Set> numberTypes = new HashSet>(8); + numberTypes.add(Byte.class); + numberTypes.add(Short.class); + numberTypes.add(Integer.class); + numberTypes.add(Long.class); + numberTypes.add(BigInteger.class); + numberTypes.add(Float.class); + numberTypes.add(Double.class); + numberTypes.add(BigDecimal.class); + STANDARD_NUMBER_TYPES = Collections.unmodifiableSet(numberTypes); + } + /** * Convert the given number into an instance of the given target class. diff --git a/spring-web/src/main/java/org/springframework/web/context/request/ServletRequestAttributes.java b/spring-web/src/main/java/org/springframework/web/context/request/ServletRequestAttributes.java index 20a17c3fce..4182342a26 100644 --- a/spring-web/src/main/java/org/springframework/web/context/request/ServletRequestAttributes.java +++ b/spring-web/src/main/java/org/springframework/web/context/request/ServletRequestAttributes.java @@ -16,13 +16,16 @@ package org.springframework.web.context.request; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpSession; import org.springframework.util.Assert; +import org.springframework.util.NumberUtils; import org.springframework.util.StringUtils; import org.springframework.web.util.WebUtils; @@ -46,6 +49,15 @@ public class ServletRequestAttributes extends AbstractRequestAttributes { public static final String DESTRUCTION_CALLBACK_NAME_PREFIX = ServletRequestAttributes.class.getName() + ".DESTRUCTION_CALLBACK."; + protected static final Set> immutableValueTypes = new HashSet>(16); + + static { + immutableValueTypes.addAll(NumberUtils.STANDARD_NUMBER_TYPES); + immutableValueTypes.add(Boolean.class); + immutableValueTypes.add(Character.class); + immutableValueTypes.add(String.class); + } + private final HttpServletRequest request; @@ -265,7 +277,7 @@ public class ServletRequestAttributes extends AbstractRequestAttributes { * attribute, that is, doesn't have to be re-set via {@code session.setAttribute} * since its value cannot meaningfully change internally. *

The default implementation returns {@code true} for {@code String}, - * {@code Character}, {@code Boolean} and {@code Number} values. + * {@code Character}, {@code Boolean} and standard {@code Number} values. * @param name the name of the attribute * @param value the corresponding value to check * @return {@code true} if the value is to be considered as immutable for the @@ -273,8 +285,7 @@ public class ServletRequestAttributes extends AbstractRequestAttributes { * @see #updateAccessedSessionAttributes() */ protected boolean isImmutableSessionAttribute(String name, Object value) { - return (value instanceof String || value instanceof Character || - value instanceof Boolean || value instanceof Number); + return (value == null || immutableValueTypes.contains(value.getClass())); } /**