From 0b0293393876934e24a5215bdb7bc2e1bf75c233 Mon Sep 17 00:00:00 2001 From: Rossen Stoyanchev Date: Mon, 2 Apr 2012 15:46:31 -0400 Subject: [PATCH] Fix race condition in AnntationMethodHER Issues: SPR-9138 --- ...otationMethodHandlerExceptionResolver.java | 34 +++++++++--------- ...otationMethodHandlerExceptionResolver.java | 36 +++++++++---------- 2 files changed, 35 insertions(+), 35 deletions(-) diff --git a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index 9095a3bc04..13955c415d 100644 --- a/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/spring-webmvc-portlet/src/main/java/org/springframework/web/portlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -75,8 +75,7 @@ import org.springframework.web.servlet.View; public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { // dummy method placeholder - private static final Method NO_METHOD_FOUND = ClassUtils - .getMethodIfAvailable(System.class, "currentTimeMillis", null); + private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", (Class[]) null); private WebArgumentResolver[] customArgumentResolvers; @@ -134,10 +133,9 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) { final Class handlerType = handler.getClass(); final Class thrownExceptionType = thrownException.getClass(); - Method handlerMethod = null; - Map, Method> handlers = exceptionHandlerCache - .get(handlerType); + + Map, Method> handlers = exceptionHandlerCache.get(handlerType); if (handlers != null) { handlerMethod = handlers.get(thrownExceptionType); @@ -173,7 +171,9 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } }); - return getBestMatchingMethod(resolverMethods, thrownException); + handlerMethod = getBestMatchingMethod(resolverMethods, thrownException); + handlers.put(thrownExceptionType, (handlerMethod == null ? NO_METHOD_FOUND : handlerMethod)); + return handlerMethod; } /** @@ -204,19 +204,19 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } /** - * Returns the best matching method. Uses the {@link DepthComparator}. + * Uses the {@link DepthComparator} to find the best matching method + * @return the best matching method or {@code null}. */ private Method getBestMatchingMethod( Map, Method> resolverMethods, Exception thrownException) { - if (!resolverMethods.isEmpty()) { - Class closestMatch = - ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); - return resolverMethods.get(closestMatch); - } - else { + if (resolverMethods.isEmpty()) { return null; } + Class closestMatch = + ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); + Method method = resolverMethods.get(closestMatch); + return ((method == null) || (NO_METHOD_FOUND == method)) ? null : method; } /** @@ -225,13 +225,13 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, Exception thrownException) throws Exception { - Class[] paramTypes = handlerMethod.getParameterTypes(); + Class[] paramTypes = handlerMethod.getParameterTypes(); Object[] args = new Object[paramTypes.length]; Class handlerType = handler.getClass(); for (int i = 0; i < args.length; i++) { MethodParameter methodParam = new MethodParameter(handlerMethod, i); GenericTypeResolver.resolveParameterType(methodParam, handlerType); - Class paramType = methodParam.getParameterType(); + Class paramType = methodParam.getParameterType(); Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); if (argValue != WebArgumentResolver.UNRESOLVED) { args[i] = argValue; @@ -267,7 +267,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } // Resolution of standard parameter types... - Class paramType = methodParameter.getParameterType(); + Class paramType = methodParameter.getParameterType(); Object value = resolveStandardArgument(paramType, webRequest, thrownException); if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { throw new IllegalStateException("Standard argument type [" + paramType.getName() + @@ -287,7 +287,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc * @param thrownException the exception thrown * @return the argument value, or {@link org.springframework.web.bind.support.WebArgumentResolver#UNRESOLVED} */ - protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest, + protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest, Exception thrownException) throws Exception { if (parameterType.isInstance(thrownException)) { diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java index 713fe66f1e..2ff7987c9f 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/annotation/AnnotationMethodHandlerExceptionResolver.java @@ -84,10 +84,10 @@ import org.springframework.web.servlet.support.RequestContextUtils; public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExceptionResolver { // dummy method placeholder - private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", null); - - private final Map, Map, Method>> exceptionHandlerCache = - new ConcurrentHashMap, Map, Method>>(); + private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis", (Class[]) null); + + private final Map, Map, Method>> exceptionHandlerCache = + new ConcurrentHashMap, Map, Method>>(); private WebArgumentResolver[] customArgumentResolvers; @@ -157,7 +157,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc final Class handlerType = ClassUtils.getUserClass(handler); final Class thrownExceptionType = thrownException.getClass(); Method handlerMethod = null; - + Map, Method> handlers = exceptionHandlerCache.get(handlerType); if (handlers != null) { @@ -170,7 +170,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc handlers = new ConcurrentHashMap, Method>(); exceptionHandlerCache.put(handlerType, handlers); } - + final Map, Method> resolverMethods = handlers; ReflectionUtils.doWithMethods(handlerType, new ReflectionUtils.MethodCallback() { @@ -228,19 +228,19 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } /** - * Returns the best matching method. Uses the {@link DepthComparator}. + * Uses the {@link DepthComparator} to find the best matching method + * @return the best matching method or {@code null}. */ private Method getBestMatchingMethod( Map, Method> resolverMethods, Exception thrownException) { - if (!resolverMethods.isEmpty()) { - Class closestMatch = - ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); - return resolverMethods.get(closestMatch); - } - else { + if (resolverMethods.isEmpty()) { return null; } + Class closestMatch = + ExceptionDepthComparator.findClosestMatch(resolverMethods.keySet(), thrownException); + Method method = resolverMethods.get(closestMatch); + return ((method == null) || (NO_METHOD_FOUND == method)) ? null : method; } /** @@ -249,13 +249,13 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc private Object[] resolveHandlerArguments(Method handlerMethod, Object handler, NativeWebRequest webRequest, Exception thrownException) throws Exception { - Class[] paramTypes = handlerMethod.getParameterTypes(); + Class[] paramTypes = handlerMethod.getParameterTypes(); Object[] args = new Object[paramTypes.length]; Class handlerType = handler.getClass(); for (int i = 0; i < args.length; i++) { MethodParameter methodParam = new MethodParameter(handlerMethod, i); GenericTypeResolver.resolveParameterType(methodParam, handlerType); - Class paramType = methodParam.getParameterType(); + Class paramType = methodParam.getParameterType(); Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException); if (argValue != WebArgumentResolver.UNRESOLVED) { args[i] = argValue; @@ -290,7 +290,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc } // Resolution of standard parameter types... - Class paramType = methodParameter.getParameterType(); + Class paramType = methodParameter.getParameterType(); Object value = resolveStandardArgument(paramType, webRequest, thrownException); if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) { throw new IllegalStateException( @@ -311,7 +311,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc * @param thrownException the exception thrown * @return the argument value, or {@link WebArgumentResolver#UNRESOLVED} */ - protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest, + protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest, Exception thrownException) throws Exception { if (parameterType.isInstance(thrownException)) { @@ -395,7 +395,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc return new ModelAndView().addAllObjects(((Model) returnValue).asMap()); } else if (returnValue instanceof Map) { - return new ModelAndView().addAllObjects((Map) returnValue); + return new ModelAndView().addAllObjects((Map) returnValue); } else if (returnValue instanceof View) { return new ModelAndView((View) returnValue);