NativeWebRequest detects native MultipartRequest even when decorated (SPR-6594)

This commit is contained in:
Juergen Hoeller
2010-03-30 10:24:39 +00:00
parent 81e81ce77c
commit 2c9753ad25
12 changed files with 321 additions and 108 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -23,6 +23,8 @@ import java.util.Map;
import javax.portlet.PortletRequest;
import javax.portlet.PortletResponse;
import javax.portlet.PortletSession;
import javax.portlet.filter.PortletRequestWrapper;
import javax.portlet.filter.PortletResponseWrapper;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
@@ -75,6 +77,44 @@ public class PortletWebRequest extends PortletRequestAttributes implements Nativ
return getResponse();
}
@SuppressWarnings("unchecked")
public <T> T getNativeRequest(Class<T> requiredType) {
if (requiredType != null) {
PortletRequest request = getRequest();
while (request != null) {
if (requiredType.isInstance(request)) {
return (T) request;
}
else if (request instanceof PortletRequestWrapper) {
request = ((PortletRequestWrapper) request).getRequest();
}
else {
request = null;
}
}
}
return null;
}
@SuppressWarnings("unchecked")
public <T> T getNativeResponse(Class<T> requiredType) {
if (requiredType != null) {
PortletResponse response = getResponse();
while (response != null) {
if (requiredType.isInstance(response)) {
return (T) response;
}
else if (response instanceof PortletResponseWrapper) {
response = ((PortletResponseWrapper) response).getResponse();
}
else {
response = null;
}
}
}
return null;
}
public String getHeader(String headerName) {
return getRequest().getProperty(headerName);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -534,13 +534,13 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
throws Exception {
return AnnotationMethodHandlerAdapter.this.createBinder(
(PortletRequest) webRequest.getNativeRequest(), target, objectName);
webRequest.getNativeRequest(PortletRequest.class), target, objectName);
}
@Override
protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
PortletRequestDataBinder portletBinder = (PortletRequestDataBinder) binder;
portletBinder.bind((PortletRequest) webRequest.getNativeRequest());
portletBinder.bind(webRequest.getNativeRequest(PortletRequest.class));
}
@Override
@@ -560,7 +560,7 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest)
throws Exception {
PortletRequest portletRequest = (PortletRequest) webRequest.getNativeRequest();
PortletRequest portletRequest = webRequest.getNativeRequest(PortletRequest.class);
Cookie cookieValue = PortletUtils.getCookie(portletRequest, cookieName);
if (Cookie.class.isAssignableFrom(paramType)) {
return cookieValue;
@@ -577,8 +577,8 @@ public class AnnotationMethodHandlerAdapter extends PortletContentGenerator
protected Object resolveStandardArgument(Class parameterType, NativeWebRequest webRequest)
throws Exception {
PortletRequest request = (PortletRequest) webRequest.getNativeRequest();
PortletResponse response = (PortletResponse) webRequest.getNativeResponse();
PortletRequest request = webRequest.getNativeRequest(PortletRequest.class);
PortletResponse response = webRequest.getNativeResponse(PortletResponse.class);
if (PortletRequest.class.isAssignableFrom(parameterType)) {
return request;

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2009 the original author or authors.
* Copyright 2002-2010 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.
@@ -61,6 +61,7 @@ import org.springframework.web.servlet.View;
/**
* Implementation of the {@link org.springframework.web.portlet.HandlerExceptionResolver} interface that handles
* exceptions through the {@link ExceptionHandler} annotation.
*
* <p>This exception resolver is enabled by default in the {@link org.springframework.web.portlet.DispatcherPortlet}.
*
* @author Arjen Poutsma
@@ -70,6 +71,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
private WebArgumentResolver[] customArgumentResolvers;
/**
* Set a custom ArgumentResolvers to use for special method parameter types. Such a custom ArgumentResolver will kick
* in first, having a chance to resolve an argument value before the standard argument handling kicks in.
@@ -86,11 +88,11 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
this.customArgumentResolvers = argumentResolvers;
}
@Override
protected ModelAndView doResolveException(PortletRequest request,
MimeResponse response,
Object handler,
Exception ex) {
protected ModelAndView doResolveException(PortletRequest request, MimeResponse response,
Object handler, Exception ex) {
if (handler != null) {
Method handlerMethod = findBestExceptionHandlerMethod(handler, ex);
if (handlerMethod != null) {
@@ -113,15 +115,13 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
/**
* Finds the handler method that matches the thrown exception best.
*
* @param handler the handler object
* @param handler the handler object
* @param thrownException the exception to be handled
* @return the best matching method; or <code>null</code> if none is found
*/
private Method findBestExceptionHandlerMethod(Object handler, final Exception thrownException) {
final Class<?> handlerType = handler.getClass();
final Class<? extends Throwable> thrownExceptionType = thrownException.getClass();
final Map<Class<? extends Throwable>, Method> resolverMethods =
new LinkedHashMap<Class<? extends Throwable>, Method>();
@@ -145,16 +145,15 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
}
});
return getBestMatchingMethod(thrownException, resolverMethods);
}
/**
* Returns all the exception classes handled by the given method.
*
* <p>Default implementation looks for exceptions in the {@linkplain ExceptionHandler#value() annotation}, or -
* if that annotation element is empty - any exceptions listed in the method parameters if the method is annotated
* with {@code @ExceptionHandler}.
*
* <p>Default implementation looks for exceptions in the {@linkplain ExceptionHandler#value() annotation},
* or - if that annotation element is empty - any exceptions listed in the method parameters if the
* method is annotated with {@code @ExceptionHandler}.
* @param method the method
* @return the handled exceptions
*/
@@ -182,6 +181,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
*/
private Method getBestMatchingMethod(Exception thrownException,
Map<Class<? extends Throwable>, Method> resolverMethods) {
if (!resolverMethods.isEmpty()) {
List<Class<? extends Throwable>> handledExceptions =
new ArrayList<Class<? extends Throwable>>(resolverMethods.keySet());
@@ -197,47 +197,40 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
/**
* Resolves the arguments for the given method. Delegates to {@link #resolveCommonArgument}.
*/
private Object[] resolveHandlerArguments(Method handlerMethod,
Object handler,
NativeWebRequest webRequest,
Exception thrownException) throws Exception {
private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
NativeWebRequest webRequest, Exception thrownException) throws Exception {
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();
Object argValue = resolveCommonArgument(methodParam, webRequest, thrownException);
if (argValue != WebArgumentResolver.UNRESOLVED) {
args[i] = argValue;
}
else {
throw new IllegalStateException(
"Unsupported argument [" + paramType.getName() + "] for @ExceptionHandler method: " +
handlerMethod);
throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
"] for @ExceptionHandler method: " + handlerMethod);
}
}
return args;
}
/**
* Resolves common method arguments. Delegates to registered {@link #setCustomArgumentResolver(org.springframework.web.bind.support.WebArgumentResolver) argumentResolvers} first,
* Resolves common method arguments. Delegates to registered
* {@link #setCustomArgumentResolver argumentResolvers} first,
* then checking {@link #resolveStandardArgument}.
*
* @param methodParameter the method parameter
* @param webRequest the request
* @param webRequest the request
* @param thrownException the exception thrown
* @return the argument value, or {@link org.springframework.web.bind.support.WebArgumentResolver#UNRESOLVED}
*/
protected Object resolveCommonArgument(MethodParameter methodParameter,
NativeWebRequest webRequest,
protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest,
Exception thrownException) throws Exception {
// Invoke custom argument resolvers if present...
if (this.customArgumentResolvers != null) {
for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
@@ -261,25 +254,24 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
/**
* Resolves standard method arguments. Default implementation handles {@link org.springframework.web.context.request.NativeWebRequest},
* {@link javax.servlet.ServletRequest}, {@link javax.servlet.ServletResponse}, {@link javax.servlet.http.HttpSession}, {@link java.security.Principal}, {@link java.util.Locale},
* request {@link java.io.InputStream}, request {@link java.io.Reader}, response {@link java.io.OutputStream}, response {@link java.io.Writer},
* and the given {@code thrownException}.
*
* @param parameterType the method parameter type
* @param webRequest the request
* Resolves standard method arguments. The default implementation handles {@link NativeWebRequest},
* {@link ServletRequest}, {@link ServletResponse}, {@link HttpSession}, {@link Principal},
* {@link Locale}, request {@link InputStream}, request {@link Reader}, response {@link OutputStream},
* response {@link Writer}, and the given {@code thrownException}.
* @param parameterType the method parameter type
* @param webRequest the request
* @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 (WebRequest.class.isAssignableFrom(parameterType)) {
return webRequest;
}
PortletRequest request = (PortletRequest) webRequest.getNativeRequest();
PortletResponse response = (PortletResponse) webRequest.getNativeResponse();
PortletRequest request = webRequest.getNativeRequest(PortletRequest.class);
PortletResponse response = webRequest.getNativeResponse(PortletResponse.class);
if (PortletRequest.class.isAssignableFrom(parameterType)) {
return request;
@@ -382,6 +374,7 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
}
/**
* Comparator capable of sorting exceptions based on their depth from the thrown exception type.
*/
@@ -413,4 +406,5 @@ public class AnnotationMethodHandlerExceptionResolver extends AbstractHandlerExc
}
}
}
}