diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/bind/annotation/support/HandlerMethodInvoker.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/bind/annotation/support/HandlerMethodInvoker.java
deleted file mode 100644
index 0e6e4119a..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/bind/annotation/support/HandlerMethodInvoker.java
+++ /dev/null
@@ -1,821 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-
-package org.springframework.data.document.web.bind.annotation.support;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.*;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.http.*;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.ui.ExtendedModelMap;
-import org.springframework.ui.Model;
-import org.springframework.util.*;
-import org.springframework.validation.BindException;
-import org.springframework.validation.BindingResult;
-import org.springframework.validation.Errors;
-import org.springframework.web.HttpMediaTypeNotSupportedException;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.bind.annotation.support.HandlerMethodInvocationException;
-import org.springframework.web.bind.annotation.support.HandlerMethodResolver;
-import org.springframework.web.bind.support.*;
-import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartRequest;
-
-/**
- * Support class for invoking an annotated handler method. Operates on the introspection results of a {@link
- * HandlerMethodResolver} for a specific handler type.
- *
- * Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} and {@link
- * org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
- *
- * @author Juergen Hoeller
- * @author Arjen Poutsma
- * @see #invokeHandlerMethod
- * @since 2.5.2
- */
-public class HandlerMethodInvoker {
-
- private static final String MODEL_KEY_PREFIX_STALE = SessionAttributeStore.class.getName() + ".STALE.";
-
- /**
- * We'll create a lot of these objects, so we don't want a new logger every time.
- */
- private static final Log logger = LogFactory.getLog(HandlerMethodInvoker.class);
-
- private final HandlerMethodResolver methodResolver;
-
- private final WebBindingInitializer bindingInitializer;
-
- private final SessionAttributeStore sessionAttributeStore;
-
- private final ParameterNameDiscoverer parameterNameDiscoverer;
-
- private final WebArgumentResolver[] customArgumentResolvers;
-
- private final HttpMessageConverter[] messageConverters;
-
- private final SimpleSessionStatus sessionStatus = new SimpleSessionStatus();
-
-
- public HandlerMethodInvoker(HandlerMethodResolver methodResolver) {
- this(methodResolver, null);
- }
-
- public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer) {
- this(methodResolver, bindingInitializer, new DefaultSessionAttributeStore(), null, null, null);
- }
-
- public HandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer,
- SessionAttributeStore sessionAttributeStore, ParameterNameDiscoverer parameterNameDiscoverer,
- WebArgumentResolver[] customArgumentResolvers, HttpMessageConverter[] messageConverters) {
-
- this.methodResolver = methodResolver;
- this.bindingInitializer = bindingInitializer;
- this.sessionAttributeStore = sessionAttributeStore;
- this.parameterNameDiscoverer = parameterNameDiscoverer;
- this.customArgumentResolvers = customArgumentResolvers;
- this.messageConverters = messageConverters;
- }
-
-
- public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
- NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
-
- Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
- try {
- boolean debug = logger.isDebugEnabled();
- for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
- Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
- if (attrValue != null) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
- Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
- Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
- }
- String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
- if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
- continue;
- }
- ReflectionUtils.makeAccessible(attributeMethodToInvoke);
- Object attrValue = attributeMethodToInvoke.invoke(handler, args);
- if ("".equals(attrName)) {
- Class resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
- attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
- }
- if (!implicitModel.containsAttribute(attrName)) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
- }
- ReflectionUtils.makeAccessible(handlerMethodToInvoke);
- return handlerMethodToInvoke.invoke(handler, args);
- } catch (IllegalStateException ex) {
- // Internal assertion failed (e.g. invalid signature):
- // throw exception with full handler method context...
- throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
- } catch (InvocationTargetException ex) {
- // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
- ReflectionUtils.rethrowException(ex.getTargetException());
- return null;
- }
- }
-
- public final void updateModelAttributes(Object handler, Map mavModel,
- ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {
-
- if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
- for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
- this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
- }
- }
-
- // Expose model attributes as session attributes, if required.
- // Expose BindingResults for all attributes, making custom editors available.
- Map model = (mavModel != null ? mavModel : implicitModel);
- if (model != null) {
- try {
- String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
- for (String attrName : originalAttrNames) {
- Object attrValue = model.get(attrName);
- boolean isSessionAttr = this.methodResolver.isSessionAttribute(
- attrName, (attrValue != null ? attrValue.getClass() : null));
- if (isSessionAttr) {
- if (this.sessionStatus.isComplete()) {
- implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
- } else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
- this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
- }
- }
- if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX) &&
- (isSessionAttr || isBindingCandidate(attrValue))) {
- String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
- if (mavModel != null && !model.containsKey(bindingResultKey)) {
- WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
- initBinder(handler, attrName, binder, webRequest);
- mavModel.put(bindingResultKey, binder.getBindingResult());
- }
- }
- }
- } catch (InvocationTargetException ex) {
- // User-defined @InitBinder method threw an exception...
- ReflectionUtils.rethrowException(ex.getTargetException());
- }
- }
- }
-
-
- private Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
- NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
-
- Class[] paramTypes = handlerMethod.getParameterTypes();
- Object[] args = new Object[paramTypes.length];
-
- for (int i = 0; i < args.length; i++) {
- MethodParameter methodParam = new MethodParameter(handlerMethod, i);
- methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
- GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
- String paramName = null;
- String headerName = null;
- boolean requestBodyFound = false;
- String cookieName = null;
- String pathVarName = null;
- String attrName = null;
- boolean required = false;
- String defaultValue = null;
- boolean validate = false;
- int annotationsFound = 0;
- Annotation[] paramAnns = methodParam.getParameterAnnotations();
-
- for (Annotation paramAnn : paramAnns) {
- if (RequestParam.class.isInstance(paramAnn)) {
- RequestParam requestParam = (RequestParam) paramAnn;
- paramName = requestParam.value();
- required = requestParam.required();
- defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
- annotationsFound++;
- } else if (RequestHeader.class.isInstance(paramAnn)) {
- RequestHeader requestHeader = (RequestHeader) paramAnn;
- headerName = requestHeader.value();
- required = requestHeader.required();
- defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
- annotationsFound++;
- } else if (RequestBody.class.isInstance(paramAnn)) {
- requestBodyFound = true;
- annotationsFound++;
- } else if (CookieValue.class.isInstance(paramAnn)) {
- CookieValue cookieValue = (CookieValue) paramAnn;
- cookieName = cookieValue.value();
- required = cookieValue.required();
- defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
- annotationsFound++;
- } else if (PathVariable.class.isInstance(paramAnn)) {
- PathVariable pathVar = (PathVariable) paramAnn;
- pathVarName = pathVar.value();
- annotationsFound++;
- } else if (ModelAttribute.class.isInstance(paramAnn)) {
- ModelAttribute attr = (ModelAttribute) paramAnn;
- attrName = attr.value();
- annotationsFound++;
- } else if (Value.class.isInstance(paramAnn)) {
- defaultValue = ((Value) paramAnn).value();
- } else if ("Valid".equals(paramAnn.annotationType().getSimpleName())) {
- validate = true;
- }
- }
-
- if (annotationsFound > 1) {
- throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
- "do not specify more than one such annotation on the same parameter: " + handlerMethod);
- }
-
- if (annotationsFound == 0) {
- Object argValue = resolveCommonArgument(methodParam, webRequest);
- if (argValue != WebArgumentResolver.UNRESOLVED) {
- args[i] = argValue;
- } else if (defaultValue != null) {
- args[i] = resolveDefaultValue(defaultValue);
- } else {
- Class paramType = methodParam.getParameterType();
- if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
- args[i] = implicitModel;
- } else if (SessionStatus.class.isAssignableFrom(paramType)) {
- args[i] = this.sessionStatus;
- } else if (HttpEntity.class.isAssignableFrom(paramType)) {
- args[i] = resolveHttpEntityRequest(methodParam, webRequest);
- } else if (Errors.class.isAssignableFrom(paramType)) {
- throw new IllegalStateException("Errors/BindingResult argument declared " +
- "without preceding model attribute. Check your handler method signature!");
- } else if (BeanUtils.isSimpleProperty(paramType)) {
- paramName = "";
- } else {
- attrName = "";
- }
- }
- }
-
- if (paramName != null) {
- args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
- } else if (headerName != null) {
- args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
- } else if (requestBodyFound) {
- args[i] = resolveRequestBody(methodParam, webRequest, handler);
- } else if (cookieName != null) {
- args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
- } else if (pathVarName != null) {
- args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
- } else if (attrName != null) {
- WebDataBinder binder =
- resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
- boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
- if (binder.getTarget() != null) {
- doBind(binder, webRequest, validate, !assignBindingResult);
- }
- args[i] = binder.getTarget();
- if (assignBindingResult) {
- args[i + 1] = binder.getBindingResult();
- i++;
- }
- implicitModel.putAll(binder.getBindingResult().getModel());
- }
- }
-
- return args;
- }
-
- protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest)
- throws Exception {
-
- if (this.bindingInitializer != null) {
- this.bindingInitializer.initBinder(binder, webRequest);
- }
- if (handler != null) {
- Set initBinderMethods = this.methodResolver.getInitBinderMethods();
- if (!initBinderMethods.isEmpty()) {
- boolean debug = logger.isDebugEnabled();
- for (Method initBinderMethod : initBinderMethods) {
- Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
- String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
- if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
- Object[] initBinderArgs =
- resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
- if (debug) {
- logger.debug("Invoking init-binder method: " + methodToInvoke);
- }
- ReflectionUtils.makeAccessible(methodToInvoke);
- Object returnValue = methodToInvoke.invoke(handler, initBinderArgs);
- if (returnValue != null) {
- throw new IllegalStateException(
- "InitBinder methods must not have a return value: " + methodToInvoke);
- }
- }
- }
- }
- }
- }
-
- private Object[] resolveInitBinderArguments(Object handler, Method initBinderMethod,
- WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
-
- Class[] initBinderParams = initBinderMethod.getParameterTypes();
- Object[] initBinderArgs = new Object[initBinderParams.length];
-
- for (int i = 0; i < initBinderArgs.length; i++) {
- MethodParameter methodParam = new MethodParameter(initBinderMethod, i);
- methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
- GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
- String paramName = null;
- boolean paramRequired = false;
- String paramDefaultValue = null;
- String pathVarName = null;
- Annotation[] paramAnns = methodParam.getParameterAnnotations();
-
- for (Annotation paramAnn : paramAnns) {
- if (RequestParam.class.isInstance(paramAnn)) {
- RequestParam requestParam = (RequestParam) paramAnn;
- paramName = requestParam.value();
- paramRequired = requestParam.required();
- paramDefaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
- break;
- } else if (ModelAttribute.class.isInstance(paramAnn)) {
- throw new IllegalStateException(
- "@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod);
- } else if (PathVariable.class.isInstance(paramAnn)) {
- PathVariable pathVar = (PathVariable) paramAnn;
- pathVarName = pathVar.value();
- }
- }
-
- if (paramName == null && pathVarName == null) {
- Object argValue = resolveCommonArgument(methodParam, webRequest);
- if (argValue != WebArgumentResolver.UNRESOLVED) {
- initBinderArgs[i] = argValue;
- } else {
- Class paramType = initBinderParams[i];
- if (paramType.isInstance(binder)) {
- initBinderArgs[i] = binder;
- } else if (BeanUtils.isSimpleProperty(paramType)) {
- paramName = "";
- } else {
- throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
- "] for @InitBinder method: " + initBinderMethod);
- }
- }
- }
-
- if (paramName != null) {
- initBinderArgs[i] =
- resolveRequestParam(paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null);
- } else if (pathVarName != null) {
- initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null);
- }
- }
-
- return initBinderArgs;
- }
-
- @SuppressWarnings("unchecked")
- private Object resolveRequestParam(String paramName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {
- return resolveRequestParamMap((Class extends Map>) paramType, webRequest);
- }
- if (paramName.length() == 0) {
- paramName = getRequiredParameterName(methodParam);
- }
- Object paramValue = null;
- MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
- if (multipartRequest != null) {
- List files = multipartRequest.getFiles(paramName);
- if (!files.isEmpty()) {
- if (files.size() == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
- paramValue = files.get(0);
- } else {
- paramValue = files;
- }
- }
- }
- if (paramValue == null) {
- String[] paramValues = webRequest.getParameterValues(paramName);
- if (paramValues != null) {
- if (paramValues.length == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
- paramValue = paramValues[0];
- } else {
- paramValue = paramValues;
- }
- }
- }
- if (paramValue == null) {
- if (defaultValue != null) {
- paramValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingParameterException(paramName, paramType);
- }
- paramValue = checkValue(paramName, paramValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, paramName);
- initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
- return binder.convertIfNecessary(paramValue, paramType, methodParam);
- }
-
- private Map resolveRequestParamMap(Class extends Map> mapType, NativeWebRequest webRequest) {
- Map parameterMap = webRequest.getParameterMap();
- if (MultiValueMap.class.isAssignableFrom(mapType)) {
- MultiValueMap result = new LinkedMultiValueMap(parameterMap.size());
- for (Map.Entry entry : parameterMap.entrySet()) {
- for (String value : entry.getValue()) {
- result.add(entry.getKey(), value);
- }
- }
- return result;
- } else {
- Map result = new LinkedHashMap(parameterMap.size());
- for (Map.Entry entry : parameterMap.entrySet()) {
- if (entry.getValue().length > 0) {
- result.put(entry.getKey(), entry.getValue()[0]);
- }
- }
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (Map.class.isAssignableFrom(paramType)) {
- return resolveRequestHeaderMap((Class extends Map>) paramType, webRequest);
- }
- if (headerName.length() == 0) {
- headerName = getRequiredParameterName(methodParam);
- }
- Object headerValue = null;
- String[] headerValues = webRequest.getHeaderValues(headerName);
- if (headerValues != null) {
- headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues);
- }
- if (headerValue == null) {
- if (defaultValue != null) {
- headerValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingHeaderException(headerName, paramType);
- }
- headerValue = checkValue(headerName, headerValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, headerName);
- initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
- return binder.convertIfNecessary(headerValue, paramType, methodParam);
- }
-
- private Map resolveRequestHeaderMap(Class extends Map> mapType, NativeWebRequest webRequest) {
- if (MultiValueMap.class.isAssignableFrom(mapType)) {
- MultiValueMap result;
- if (HttpHeaders.class.isAssignableFrom(mapType)) {
- result = new HttpHeaders();
- } else {
- result = new LinkedMultiValueMap();
- }
- for (Iterator iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
- String headerName = iterator.next();
- for (String headerValue : webRequest.getHeaderValues(headerName)) {
- result.add(headerName, headerValue);
- }
- }
- return result;
- } else {
- Map result = new LinkedHashMap();
- for (Iterator iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
- String headerName = iterator.next();
- String headerValue = webRequest.getHeader(headerName);
- result.put(headerName, headerValue);
- }
- return result;
- }
- }
-
- /**
- * Resolves the given {@link RequestBody @RequestBody} annotation.
- */
- protected Object resolveRequestBody(MethodParameter methodParam, NativeWebRequest webRequest, Object handler)
- throws Exception {
-
- return readWithMessageConverters(methodParam, createHttpInputMessage(webRequest), methodParam.getParameterType());
- }
-
- private HttpEntity resolveHttpEntityRequest(MethodParameter methodParam, NativeWebRequest webRequest)
- throws Exception {
-
- HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
- Class> paramType = getHttpEntityType(methodParam);
- Object body = readWithMessageConverters(methodParam, inputMessage, paramType);
- return new HttpEntity(body, inputMessage.getHeaders());
- }
-
- private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType)
- throws Exception {
-
- MediaType contentType = inputMessage.getHeaders().getContentType();
- if (contentType == null) {
- StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
- String paramName = methodParam.getParameterName();
- if (paramName != null) {
- builder.append(' ');
- builder.append(paramName);
- }
- throw new HttpMediaTypeNotSupportedException(
- "Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
- }
-
- List allSupportedMediaTypes = new ArrayList();
- if (this.messageConverters != null) {
- for (HttpMessageConverter> messageConverter : this.messageConverters) {
- allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
- if (messageConverter.canRead(paramType, contentType)) {
- if (logger.isDebugEnabled()) {
- logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
- + "\" using [" + messageConverter + "]");
- }
- return messageConverter.read(paramType, inputMessage);
- }
- }
- }
- throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
- }
-
- private Class> getHttpEntityType(MethodParameter methodParam) {
- Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
- ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
- if (type.getActualTypeArguments().length == 1) {
- Type typeArgument = type.getActualTypeArguments()[0];
- if (typeArgument instanceof Class) {
- return (Class>) typeArgument;
- } else if (typeArgument instanceof GenericArrayType) {
- Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
- if (componentType instanceof Class) {
- // Surely, there should be a nicer way to do this
- Object array = Array.newInstance((Class>) componentType, 0);
- return array.getClass();
- }
- }
- }
- throw new IllegalArgumentException(
- "HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
-
- }
-
- private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (cookieName.length() == 0) {
- cookieName = getRequiredParameterName(methodParam);
- }
- Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest);
- if (cookieValue == null) {
- if (defaultValue != null) {
- cookieValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingCookieException(cookieName, paramType);
- }
- cookieValue = checkValue(cookieName, cookieValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, cookieName);
- initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
- return binder.convertIfNecessary(cookieValue, paramType, methodParam);
- }
-
- /**
- * Resolves the given {@link CookieValue @CookieValue} annotation.
- * Throws an UnsupportedOperationException by default.
- */
- protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- throw new UnsupportedOperationException("@CookieValue not supported");
- }
-
- private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
- NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (pathVarName.length() == 0) {
- pathVarName = getRequiredParameterName(methodParam);
- }
- String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
- WebDataBinder binder = createBinder(webRequest, null, pathVarName);
- initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
- return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
- }
-
- /**
- * Resolves the given {@link PathVariable @PathVariable} annotation.
- *
Throws an UnsupportedOperationException by default.
- */
- protected String resolvePathVariable(String pathVarName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- throw new UnsupportedOperationException("@PathVariable not supported");
- }
-
- private String getRequiredParameterName(MethodParameter methodParam) {
- String name = methodParam.getParameterName();
- if (name == null) {
- throw new IllegalStateException(
- "No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
- "], and no parameter name information found in class file either.");
- }
- return name;
- }
-
- private Object checkValue(String name, Object value, Class paramType) {
- if (value == null) {
- if (boolean.class.equals(paramType)) {
- return Boolean.FALSE;
- } else if (paramType.isPrimitive()) {
- throw new IllegalStateException("Optional " + paramType + " parameter '" + name +
- "' is not present but cannot be translated into a null value due to being declared as a " +
- "primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
- }
- }
- return value;
- }
-
- private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
- ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
-
- // Bind request parameter onto object...
- String name = attrName;
- if ("".equals(name)) {
- name = Conventions.getVariableNameForParameter(methodParam);
- }
- Class> paramType = methodParam.getParameterType();
- Object bindObject;
- if (implicitModel.containsKey(name)) {
- bindObject = implicitModel.get(name);
- } else if (this.methodResolver.isSessionAttribute(name, paramType)) {
- bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
- if (bindObject == null) {
- raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
- }
- } else {
- bindObject = BeanUtils.instantiateClass(paramType);
- }
- WebDataBinder binder = createBinder(webRequest, bindObject, name);
- initBinder(handler, name, binder, webRequest);
- return binder;
- }
-
-
- /**
- * Determine whether the given value qualifies as a "binding candidate", i.e. might potentially be subject to
- * bean-style data binding later on.
- */
- protected boolean isBindingCandidate(Object value) {
- return (value != null && !value.getClass().isArray() && !(value instanceof Collection) &&
- !(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass()));
- }
-
- protected void raiseMissingParameterException(String paramName, Class paramType) throws Exception {
- throw new IllegalStateException("Missing parameter '" + paramName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseMissingHeaderException(String headerName, Class paramType) throws Exception {
- throw new IllegalStateException("Missing header '" + headerName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseMissingCookieException(String cookieName, Class paramType) throws Exception {
- throw new IllegalStateException(
- "Missing cookie value '" + cookieName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseSessionRequiredException(String message) throws Exception {
- throw new IllegalStateException(message);
- }
-
- protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
- throws Exception {
-
- return new WebRequestDataBinder(target, objectName);
- }
-
- private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate, boolean failOnErrors)
- throws Exception {
-
- doBind(binder, webRequest);
- if (validate) {
- binder.validate();
- }
- if (failOnErrors && binder.getBindingResult().hasErrors()) {
- throw new BindException(binder.getBindingResult());
- }
- }
-
- protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
- ((WebRequestDataBinder) binder).bind(webRequest);
- }
-
- /**
- * Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
- *
Throws an UnsupportedOperation1Exception by default.
- */
- protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
- throw new UnsupportedOperationException("@RequestBody not supported");
- }
-
- /**
- * Return a {@link HttpOutputMessage} for the given {@link NativeWebRequest}.
- *
Throws an UnsupportedOperationException by default.
- */
- protected HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) throws Exception {
- throw new UnsupportedOperationException("@ResponseBody not supported");
- }
-
- protected String parseDefaultValueAttribute(String value) {
- return (ValueConstants.DEFAULT_NONE.equals(value) ? null : value);
- }
-
- protected Object resolveDefaultValue(String value) {
- return value;
- }
-
- protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest)
- throws Exception {
-
- // Invoke custom argument resolvers if present...
- if (this.customArgumentResolvers != null) {
- for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
- Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
- if (value != WebArgumentResolver.UNRESOLVED) {
- return value;
- }
- }
- }
-
- // Resolution of standard parameter types...
- Class paramType = methodParameter.getParameterType();
- Object value = resolveStandardArgument(paramType, webRequest);
- if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
- throw new IllegalStateException("Standard argument type [" + paramType.getName() +
- "] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) +
- "]. Consider declaring the argument type in a less specific fashion.");
- }
- return value;
- }
-
- protected Object resolveStandardArgument(Class> parameterType, NativeWebRequest webRequest) throws Exception {
- if (WebRequest.class.isAssignableFrom(parameterType)) {
- return webRequest;
- }
- return WebArgumentResolver.UNRESOLVED;
- }
-
- protected final void addReturnValueAsModelAttribute(Method handlerMethod, Class handlerType,
- Object returnValue, ExtendedModelMap implicitModel) {
-
- ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
- String attrName = (attr != null ? attr.value() : "");
- if ("".equals(attrName)) {
- Class resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
- attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
- }
- implicitModel.addAttribute(attrName, returnValue);
- }
-
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutedContext.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutedContext.java
deleted file mode 100644
index 97123fdbe..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutedContext.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.data.document.web.servlet;
-
-import java.util.Arrays;
-
-import org.springframework.web.servlet.ModelAndView;
-
-public class ActionExecutedContext extends ActionExecutingContext {
-
-
- private ModelAndView modelAndView;
-
- private Exception exception;
-
- public ActionExecutedContext(ActionExecutingContext actionExecutingContext, ModelAndView modelAndView, Exception exception) {
- super(actionExecutingContext.getServletWebRequest(), actionExecutingContext.getHandler(),
- actionExecutingContext.getHandlerMethod(), actionExecutingContext.getHandlerParameters(),
- actionExecutingContext.getImplicitModel());
- this.modelAndView = modelAndView;
- this.exception = exception;
- }
-
- @Override
- public String toString() {
- return "ActionExecutedContext [handler=" + getHandler()
- + ", servletWebRequest=" + getServletWebRequest()
- + ", implicitModel=" + getImplicitModel() + ", handlerMethod="
- + getHandlerMethod() + ", handlerParameters="
- + Arrays.toString(getHandlerParameters()) + ",modelAndView=" + modelAndView
- + ", exception=" + exception + "]";
- }
-
-
- public ModelAndView getModelAndView() {
- return modelAndView;
- }
-
-
- public Exception getException() {
- return exception;
- }
-
-
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutingContext.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutingContext.java
deleted file mode 100644
index f87c63884..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionExecutingContext.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.data.document.web.servlet;
-
-import java.lang.reflect.Method;
-import java.util.Arrays;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.springframework.ui.ExtendedModelMap;
-import org.springframework.web.context.request.ServletWebRequest;
-
-public class ActionExecutingContext {
-
-
- private Object handler;
-
- private ServletWebRequest servletWebRequest;
-
- private ExtendedModelMap implicitModel;
-
- private Method handlerMethod;
-
- private Object[] handlerParameters;
-
-
- public ActionExecutingContext(ServletWebRequest servletWebRequest,
- Object handler, Method handlerMethod, Object[] handlerParameters,
- ExtendedModelMap implicitModel) {
- super();
- this.servletWebRequest = servletWebRequest;
- this.handler = handler;
- this.handlerMethod = handlerMethod;
- this.handlerParameters = handlerParameters;
- this.implicitModel = implicitModel;
- }
-
- public HttpServletRequest getHttpServletRequest() {
- return servletWebRequest.getRequest();
- }
-
- public HttpServletResponse getHttpServletResponse() {
- return servletWebRequest.getResponse();
- }
-
- public Object getHandler() {
- return handler;
- }
-
- public ServletWebRequest getServletWebRequest() {
- return servletWebRequest;
- }
-
- public ExtendedModelMap getImplicitModel() {
- return implicitModel;
- }
-
- public Method getHandlerMethod() {
- return handlerMethod;
- }
-
- public Object[] getHandlerParameters() {
- return handlerParameters;
- }
-
- @Override
- public String toString() {
- return "ActionExecutingContext [handler=" + handler
- + ", servletWebRequest=" + servletWebRequest
- + ", implicitModel=" + implicitModel + ", handlerMethod="
- + handlerMethod + ", handlerParameters="
- + Arrays.toString(handlerParameters) + "]";
- }
-
-
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionInterceptor.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionInterceptor.java
deleted file mode 100644
index 6327c2605..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/ActionInterceptor.java
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.springframework.data.document.web.servlet;
-
-public interface ActionInterceptor {
-
- boolean preHandle(ActionExecutingContext actionExecutingContext);
-
- void postHandle(ActionExecutedContext actionExecutedContext);
-
- void afterCompletion(ActionExecutedContext actionExecutedContext);
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java
deleted file mode 100644
index 8761e5101..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/AnnotationMethodHandlerAdapter.java
+++ /dev/null
@@ -1,1245 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.document.web.servlet.mvc.annotation;
-
-import java.io.*;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.security.Principal;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.Cookie;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import javax.servlet.http.HttpSession;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.BeanFactory;
-import org.springframework.beans.factory.BeanFactoryAware;
-import org.springframework.beans.factory.config.BeanExpressionContext;
-import org.springframework.beans.factory.config.BeanExpressionResolver;
-import org.springframework.beans.factory.config.ConfigurableBeanFactory;
-import org.springframework.core.*;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.data.document.web.servlet.ActionExecutedContext;
-import org.springframework.data.document.web.servlet.ActionExecutingContext;
-import org.springframework.data.document.web.servlet.ActionInterceptor;
-import org.springframework.data.document.web.servlet.mvc.annotation.support.InterceptingHandlerMethodInvoker;
-import org.springframework.http.*;
-import org.springframework.http.converter.ByteArrayHttpMessageConverter;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.http.converter.StringHttpMessageConverter;
-import org.springframework.http.converter.xml.SourceHttpMessageConverter;
-import org.springframework.http.converter.xml.XmlAwareFormHttpMessageConverter;
-import org.springframework.http.server.ServerHttpRequest;
-import org.springframework.http.server.ServerHttpResponse;
-import org.springframework.http.server.ServletServerHttpRequest;
-import org.springframework.http.server.ServletServerHttpResponse;
-import org.springframework.ui.ExtendedModelMap;
-import org.springframework.ui.Model;
-import org.springframework.util.*;
-import org.springframework.validation.support.BindingAwareModelMap;
-import org.springframework.web.HttpMediaTypeNotAcceptableException;
-import org.springframework.web.HttpRequestMethodNotSupportedException;
-import org.springframework.web.HttpSessionRequiredException;
-import org.springframework.web.bind.MissingServletRequestParameterException;
-import org.springframework.web.bind.ServletRequestDataBinder;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.bind.annotation.support.HandlerMethodInvocationException;
-import org.springframework.web.bind.annotation.support.HandlerMethodInvoker;
-import org.springframework.web.bind.annotation.support.HandlerMethodResolver;
-import org.springframework.web.bind.support.DefaultSessionAttributeStore;
-import org.springframework.web.bind.support.SessionAttributeStore;
-import org.springframework.web.bind.support.WebArgumentResolver;
-import org.springframework.web.bind.support.WebBindingInitializer;
-import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.RequestScope;
-import org.springframework.web.context.request.ServletWebRequest;
-import org.springframework.web.multipart.MultipartRequest;
-import org.springframework.web.servlet.HandlerAdapter;
-import org.springframework.web.servlet.HandlerMapping;
-import org.springframework.web.servlet.ModelAndView;
-import org.springframework.web.servlet.View;
-import org.springframework.web.servlet.mvc.annotation.ModelAndViewResolver;
-import org.springframework.web.servlet.mvc.multiaction.InternalPathMethodNameResolver;
-import org.springframework.web.servlet.mvc.multiaction.MethodNameResolver;
-import org.springframework.web.servlet.mvc.multiaction.NoSuchRequestHandlingMethodException;
-import org.springframework.web.servlet.support.RequestContextUtils;
-import org.springframework.web.servlet.support.WebContentGenerator;
-import org.springframework.web.util.UrlPathHelper;
-import org.springframework.web.util.WebUtils;
-
-/**
- * Implementation of the {@link org.springframework.web.servlet.HandlerAdapter} interface
- * that maps handler methods based on HTTP paths, HTTP methods and request parameters
- * expressed through the {@link RequestMapping} annotation.
- *
- * Supports request parameter binding through the {@link RequestParam} annotation.
- * Also supports the {@link ModelAttribute} annotation for exposing model attribute
- * values to the view, as well as {@link InitBinder} for binder initialization methods
- * and {@link SessionAttributes} for automatic session management of specific attributes.
- *
- * This adapter can be customized through various bean properties.
- * A common use case is to apply shared binder initialization logic through
- * a custom {@link #setWebBindingInitializer WebBindingInitializer}.
- *
- * @author Juergen Hoeller
- * @author Arjen Poutsma
- * @see #setPathMatcher
- * @see #setMethodNameResolver
- * @see #setWebBindingInitializer
- * @see #setSessionAttributeStore
- * @since 2.5
- */
-public class AnnotationMethodHandlerAdapter extends WebContentGenerator
- implements HandlerAdapter, Ordered, BeanFactoryAware {
-
-
- private ActionInterceptor[] actionInterceptors;
-
- /**
- * Log category to use when no mapped handler is found for a request.
- *
- * @see #pageNotFoundLogger
- */
- public static final String PAGE_NOT_FOUND_LOG_CATEGORY = "org.springframework.web.servlet.PageNotFound";
-
- /**
- * Additional logger to use when no mapped handler is found for a request.
- *
- * @see #PAGE_NOT_FOUND_LOG_CATEGORY
- */
- protected static final Log pageNotFoundLogger = LogFactory.getLog(PAGE_NOT_FOUND_LOG_CATEGORY);
-
-
- private UrlPathHelper urlPathHelper = new UrlPathHelper();
-
- private PathMatcher pathMatcher = new AntPathMatcher();
-
- private MethodNameResolver methodNameResolver = new InternalPathMethodNameResolver();
-
- private WebBindingInitializer webBindingInitializer;
-
- private SessionAttributeStore amhaSessionAttributeStore = new DefaultSessionAttributeStore();
-
- private int cacheSecondsForSessionAttributeHandlers = 0;
-
- private boolean synchronizeOnSession = false;
-
- private ParameterNameDiscoverer parameterNameDiscoverer = new LocalVariableTableParameterNameDiscoverer();
-
- private WebArgumentResolver[] customArgumentResolvers;
-
- private ModelAndViewResolver[] customModelAndViewResolvers;
-
- private HttpMessageConverter>[] messageConverters;
-
- private int order = Ordered.LOWEST_PRECEDENCE;
-
- private ConfigurableBeanFactory beanFactory;
-
- private BeanExpressionContext expressionContext;
-
- private final Map, ServletHandlerMethodResolver> methodResolverCache =
- new ConcurrentHashMap, ServletHandlerMethodResolver>();
-
-
- public AnnotationMethodHandlerAdapter() {
- // no restriction of HTTP methods by default
- // MLP
- super(false);
-
- // See SPR-7316
- StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
- stringHttpMessageConverter.setWriteAcceptCharset(false);
- messageConverters = new HttpMessageConverter[]{new ByteArrayHttpMessageConverter(), stringHttpMessageConverter,
- new SourceHttpMessageConverter(), new XmlAwareFormHttpMessageConverter()};
- }
-
-
- /**
- * Set if URL lookup should always use the full path within the current servlet
- * context. Else, the path within the current servlet mapping is used if applicable
- * (that is, in the case of a ".../*" servlet mapping in web.xml).
- * Default is "false".
- *
- * @see org.springframework.web.util.UrlPathHelper#setAlwaysUseFullPath
- */
- public void setAlwaysUseFullPath(boolean alwaysUseFullPath) {
- this.urlPathHelper.setAlwaysUseFullPath(alwaysUseFullPath);
- }
-
- /**
- * Set if context path and request URI should be URL-decoded. Both are returned
- * undecoded by the Servlet API, in contrast to the servlet path.
- *
Uses either the request encoding or the default encoding according
- * to the Servlet spec (ISO-8859-1).
- *
- * @see org.springframework.web.util.UrlPathHelper#setUrlDecode
- */
- public void setUrlDecode(boolean urlDecode) {
- this.urlPathHelper.setUrlDecode(urlDecode);
- }
-
- /**
- * Set the UrlPathHelper to use for resolution of lookup paths.
- *
Use this to override the default UrlPathHelper with a custom subclass,
- * or to share common UrlPathHelper settings across multiple HandlerMappings and HandlerAdapters.
- */
- public void setUrlPathHelper(UrlPathHelper urlPathHelper) {
- Assert.notNull(urlPathHelper, "UrlPathHelper must not be null");
- this.urlPathHelper = urlPathHelper;
- }
-
- /**
- * Set the PathMatcher implementation to use for matching URL paths against registered URL patterns.
- *
Default is {@link org.springframework.util.AntPathMatcher}.
- */
- public void setPathMatcher(PathMatcher pathMatcher) {
- Assert.notNull(pathMatcher, "PathMatcher must not be null");
- this.pathMatcher = pathMatcher;
- }
-
- /**
- * Set the MethodNameResolver to use for resolving default handler methods
- * (carrying an empty @RequestMapping annotation).
- *
Will only kick in when the handler method cannot be resolved uniquely
- * through the annotation metadata already.
- */
- public void setMethodNameResolver(MethodNameResolver methodNameResolver) {
- this.methodNameResolver = methodNameResolver;
- }
-
- /**
- * Specify a WebBindingInitializer which will apply pre-configured
- * configuration to every DataBinder that this controller uses.
- */
- public void setWebBindingInitializer(WebBindingInitializer webBindingInitializer) {
- this.webBindingInitializer = webBindingInitializer;
- }
-
- /**
- * Specify the strategy to store session attributes with.
- *
Default is {@link org.springframework.web.bind.support.DefaultSessionAttributeStore},
- * storing session attributes in the HttpSession, using the same attribute name as in the model.
- */
- public void setSessionAttributeStore(SessionAttributeStore sessionAttributeStore) {
- Assert.notNull(sessionAttributeStore, "SessionAttributeStore must not be null");
- this.amhaSessionAttributeStore = sessionAttributeStore;
- }
-
- /**
- * Cache content produced by @SessionAttributes annotated handlers
- * for the given number of seconds. Default is 0, preventing caching completely.
- *
In contrast to the "cacheSeconds" property which will apply to all general handlers
- * (but not to @SessionAttributes annotated handlers), this setting will
- * apply to @SessionAttributes annotated handlers only.
- *
- * @see #setCacheSeconds
- * @see org.springframework.web.bind.annotation.SessionAttributes
- */
- public void setCacheSecondsForSessionAttributeHandlers(int cacheSecondsForSessionAttributeHandlers) {
- this.cacheSecondsForSessionAttributeHandlers = cacheSecondsForSessionAttributeHandlers;
- }
-
- /**
- * Set if controller execution should be synchronized on the session,
- * to serialize parallel invocations from the same client.
- *
More specifically, the execution of the handleRequestInternal
- * method will get synchronized if this flag is "true". The best available
- * session mutex will be used for the synchronization; ideally, this will
- * be a mutex exposed by HttpSessionMutexListener.
- *
The session mutex is guaranteed to be the same object during
- * the entire lifetime of the session, available under the key defined
- * by the SESSION_MUTEX_ATTRIBUTE constant. It serves as a
- * safe reference to synchronize on for locking on the current session.
- *
In many cases, the HttpSession reference itself is a safe mutex
- * as well, since it will always be the same object reference for the
- * same active logical session. However, this is not guaranteed across
- * different servlet containers; the only 100% safe way is a session mutex.
- *
- * @see org.springframework.web.util.HttpSessionMutexListener
- * @see org.springframework.web.util.WebUtils#getSessionMutex(javax.servlet.http.HttpSession)
- */
- public void setSynchronizeOnSession(boolean synchronizeOnSession) {
- this.synchronizeOnSession = synchronizeOnSession;
- }
-
- /**
- * Set the ParameterNameDiscoverer to use for resolving method parameter names if needed
- * (e.g. for default attribute names).
- *
Default is a {@link org.springframework.core.LocalVariableTableParameterNameDiscoverer}.
- */
- public void setParameterNameDiscoverer(ParameterNameDiscoverer parameterNameDiscoverer) {
- this.parameterNameDiscoverer = parameterNameDiscoverer;
- }
-
- /**
- * Set a custom WebArgumentResolvers to use for special method parameter types.
- *
Such a custom WebArgumentResolver will kick in first, having a chance to resolve
- * an argument value before the standard argument handling kicks in.
- */
- public void setCustomArgumentResolver(WebArgumentResolver argumentResolver) {
- this.customArgumentResolvers = new WebArgumentResolver[]{argumentResolver};
- }
-
- /**
- * Set one or more custom WebArgumentResolvers to use for special method parameter types.
- *
Any such custom WebArgumentResolver will kick in first, having a chance to resolve
- * an argument value before the standard argument handling kicks in.
- */
- public void setCustomArgumentResolvers(WebArgumentResolver[] argumentResolvers) {
- this.customArgumentResolvers = argumentResolvers;
- }
-
- /**
- * Set a custom ModelAndViewResolvers to use for special method return types.
- *
Such a custom ModelAndViewResolver will kick in first, having a chance to resolve
- * a return value before the standard ModelAndView handling kicks in.
- */
- public void setCustomModelAndViewResolver(ModelAndViewResolver customModelAndViewResolver) {
- this.customModelAndViewResolvers = new ModelAndViewResolver[]{customModelAndViewResolver};
- }
-
- /**
- * Set one or more custom ModelAndViewResolvers to use for special method return types.
- *
Any such custom ModelAndViewResolver will kick in first, having a chance to resolve
- * a return value before the standard ModelAndView handling kicks in.
- */
- public void setCustomModelAndViewResolvers(ModelAndViewResolver[] customModelAndViewResolvers) {
- this.customModelAndViewResolvers = customModelAndViewResolvers;
- }
-
- /**
- * Set the message body converters to use.
- *
These converters are used to convert from and to HTTP requests and responses.
- */
- public void setMessageConverters(HttpMessageConverter>[] messageConverters) {
- this.messageConverters = messageConverters;
- }
-
- /**
- * Return the message body converters that this adapter has been configured with.
- */
- public HttpMessageConverter>[] getMessageConverters() {
- return messageConverters;
- }
-
- public void setActionInterceptors(ActionInterceptor[] actionInterceptors) {
- this.actionInterceptors = actionInterceptors;
- }
-
- /**
- * Specify the order value for this HandlerAdapter bean.
- *
Default value is Integer.MAX_VALUE, meaning that it's non-ordered.
- *
- * @see org.springframework.core.Ordered#getOrder()
- */
- public void setOrder(int order) {
- this.order = order;
- }
-
- public int getOrder() {
- return this.order;
- }
-
- public void setBeanFactory(BeanFactory beanFactory) {
- if (beanFactory instanceof ConfigurableBeanFactory) {
- this.beanFactory = (ConfigurableBeanFactory) beanFactory;
- this.expressionContext = new BeanExpressionContext(this.beanFactory, new RequestScope());
- }
- }
-
-
- public boolean supports(Object handler) {
- return getMethodResolver(handler).hasHandlerMethods();
- }
-
- public ModelAndView handle(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- if (AnnotationUtils.findAnnotation(handler.getClass(), SessionAttributes.class) != null) {
- // Always prevent caching in case of session attribute management.
- checkAndPrepare(request, response, this.cacheSecondsForSessionAttributeHandlers, true);
- // Prepare cached set of session attributes names.
- } else {
- // Uses configured default cacheSeconds setting.
- checkAndPrepare(request, response, true);
- }
-
- // Execute invokeHandlerMethod in synchronized block if required.
- if (this.synchronizeOnSession) {
- HttpSession session = request.getSession(false);
- if (session != null) {
- Object mutex = WebUtils.getSessionMutex(session);
- synchronized (mutex) {
- return invokeHandlerMethod(request, response, handler);
- }
- }
- }
-
- return invokeHandlerMethod(request, response, handler);
- }
-
- protected ModelAndView invokeHandlerMethod(HttpServletRequest request, HttpServletResponse response, Object handler)
- throws Exception {
-
- ServletHandlerMethodResolver methodResolver = getMethodResolver(handler);
- Method handlerMethod = methodResolver.resolveHandlerMethod(request);
- ServletHandlerMethodInvoker methodInvoker = new ServletHandlerMethodInvoker(methodResolver, actionInterceptors);
- ServletWebRequest webRequest = new ServletWebRequest(request, response);
- ExtendedModelMap implicitModel = new BindingAwareModelMap();
-
-
- return methodInvoker.interceptingInvokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
- //Object result = methodInvoker.invokeHandlerMethod(handlerMethod, handler, webRequest, implicitModel);
- //ModelAndView mav =
- // methodInvoker.getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, webRequest);
- // methodInvoker.updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
- // return mav;
- }
-
- public long getLastModified(HttpServletRequest request, Object handler) {
- return -1;
- }
-
- /**
- * Build a HandlerMethodResolver for the given handler type.
- */
- private ServletHandlerMethodResolver getMethodResolver(Object handler) {
- Class handlerClass = ClassUtils.getUserClass(handler);
- ServletHandlerMethodResolver resolver = this.methodResolverCache.get(handlerClass);
- if (resolver == null) {
- resolver = new ServletHandlerMethodResolver(handlerClass);
- this.methodResolverCache.put(handlerClass, resolver);
- }
- return resolver;
- }
-
-
- /**
- * Template method for creating a new ServletRequestDataBinder instance.
- *
The default implementation creates a standard ServletRequestDataBinder.
- * This can be overridden for custom ServletRequestDataBinder subclasses.
- *
- * @param request current HTTP request
- * @param target the target object to bind onto (or null
- * if the binder is just used to convert a plain parameter value)
- * @param objectName the objectName of the target object
- * @return the ServletRequestDataBinder instance to use
- * @throws Exception in case of invalid state or arguments
- * @see ServletRequestDataBinder#bind(javax.servlet.ServletRequest)
- * @see ServletRequestDataBinder#convertIfNecessary(Object, Class, org.springframework.core.MethodParameter)
- */
- protected ServletRequestDataBinder createBinder(HttpServletRequest request, Object target, String objectName)
- throws Exception {
- return new ServletRequestDataBinder(target, objectName);
- }
-
- /**
- * Template method for creating a new HttpInputMessage instance.
- *
The default implementation creates a standard {@link ServletServerHttpRequest}.
- * This can be overridden for custom {@code HttpInputMessage} implementations
- *
- * @param servletRequest current HTTP request
- * @return the HttpInputMessage instance to use
- * @throws Exception in case of errors
- */
- protected HttpInputMessage createHttpInputMessage(HttpServletRequest servletRequest) throws Exception {
- return new ServletServerHttpRequest(servletRequest);
- }
-
- /**
- * Template method for creating a new HttpOuputMessage instance.
- *
The default implementation creates a standard {@link ServletServerHttpResponse}.
- * This can be overridden for custom {@code HttpOutputMessage} implementations
- *
- * @param servletResponse current HTTP response
- * @return the HttpInputMessage instance to use
- * @throws Exception in case of errors
- */
- protected HttpOutputMessage createHttpOutputMessage(HttpServletResponse servletResponse) throws Exception {
- return new ServletServerHttpResponse(servletResponse);
- }
-
-
- /**
- * Servlet-specific subclass of {@link HandlerMethodResolver}.
- */
- private class ServletHandlerMethodResolver extends HandlerMethodResolver {
-
- private final Map mappings = new HashMap();
-
- private ServletHandlerMethodResolver(Class> handlerType) {
- init(handlerType);
- }
-
- @Override
- protected boolean isHandlerMethod(Method method) {
- if (this.mappings.containsKey(method)) {
- return true;
- }
- RequestMapping mapping = AnnotationUtils.findAnnotation(method, RequestMapping.class);
- if (mapping != null) {
- RequestMappingInfo mappingInfo = new RequestMappingInfo();
- mappingInfo.patterns = mapping.value();
- if (!hasTypeLevelMapping() || !Arrays.equals(mapping.method(), getTypeLevelMapping().method())) {
- mappingInfo.methods = mapping.method();
- }
- if (!hasTypeLevelMapping() || !Arrays.equals(mapping.params(), getTypeLevelMapping().params())) {
- mappingInfo.params = mapping.params();
- }
- if (!hasTypeLevelMapping() || !Arrays.equals(mapping.headers(), getTypeLevelMapping().headers())) {
- mappingInfo.headers = mapping.headers();
- }
- this.mappings.put(method, mappingInfo);
- return true;
- }
- return false;
- }
-
- public Method resolveHandlerMethod(HttpServletRequest request) throws ServletException {
- String lookupPath = urlPathHelper.getLookupPathForRequest(request);
- Comparator pathComparator = pathMatcher.getPatternComparator(lookupPath);
- Map targetHandlerMethods = new LinkedHashMap();
- Set allowedMethods = new LinkedHashSet(7);
- String resolvedMethodName = null;
- for (Method handlerMethod : getHandlerMethods()) {
- RequestMappingInfo mappingInfo = this.mappings.get(handlerMethod);
- boolean match = false;
- if (mappingInfo.hasPatterns()) {
- List matchingPatterns = new ArrayList(mappingInfo.patterns.length);
- for (String pattern : mappingInfo.patterns) {
- if (!hasTypeLevelMapping() && !pattern.startsWith("/")) {
- pattern = "/" + pattern;
- }
- String combinedPattern = getCombinedPattern(pattern, lookupPath, request);
- if (combinedPattern != null) {
- if (mappingInfo.matches(request)) {
- match = true;
- matchingPatterns.add(combinedPattern);
- } else {
- if (!mappingInfo.matchesRequestMethod(request)) {
- allowedMethods.addAll(mappingInfo.methodNames());
- }
- break;
- }
- }
- }
- Collections.sort(matchingPatterns, pathComparator);
- mappingInfo.matchedPatterns = matchingPatterns;
- } else {
- // No paths specified: parameter match sufficient.
- match = mappingInfo.matches(request);
- if (match && mappingInfo.methods.length == 0 && mappingInfo.params.length == 0 &&
- resolvedMethodName != null && !resolvedMethodName.equals(handlerMethod.getName())) {
- match = false;
- } else {
- if (!mappingInfo.matchesRequestMethod(request)) {
- allowedMethods.addAll(mappingInfo.methodNames());
- }
- }
- }
- if (match) {
- Method oldMappedMethod = targetHandlerMethods.put(mappingInfo, handlerMethod);
- if (oldMappedMethod != null && oldMappedMethod != handlerMethod) {
- if (methodNameResolver != null && mappingInfo.patterns.length == 0) {
- if (!oldMappedMethod.getName().equals(handlerMethod.getName())) {
- if (resolvedMethodName == null) {
- resolvedMethodName = methodNameResolver.getHandlerMethodName(request);
- }
- if (!resolvedMethodName.equals(oldMappedMethod.getName())) {
- oldMappedMethod = null;
- }
- if (!resolvedMethodName.equals(handlerMethod.getName())) {
- if (oldMappedMethod != null) {
- targetHandlerMethods.put(mappingInfo, oldMappedMethod);
- oldMappedMethod = null;
- } else {
- targetHandlerMethods.remove(mappingInfo);
- }
- }
- }
- }
- if (oldMappedMethod != null) {
- throw new IllegalStateException(
- "Ambiguous handler methods mapped for HTTP path '" + lookupPath + "': {" +
- oldMappedMethod + ", " + handlerMethod +
- "}. If you intend to handle the same path in multiple methods, then factor " +
- "them out into a dedicated handler class with that path mapped at the type level!");
- }
- }
- }
- }
- if (!targetHandlerMethods.isEmpty()) {
- List matches = new ArrayList(targetHandlerMethods.keySet());
- RequestMappingInfoComparator requestMappingInfoComparator =
- new RequestMappingInfoComparator(pathComparator, request);
- Collections.sort(matches, requestMappingInfoComparator);
- RequestMappingInfo bestMappingMatch = matches.get(0);
- String bestMatchedPath = bestMappingMatch.bestMatchedPattern();
- if (bestMatchedPath != null) {
- extractHandlerMethodUriTemplates(bestMatchedPath, lookupPath, request);
- }
- return targetHandlerMethods.get(bestMappingMatch);
- } else {
- if (!allowedMethods.isEmpty()) {
- throw new HttpRequestMethodNotSupportedException(request.getMethod(),
- StringUtils.toStringArray(allowedMethods));
- }
- throw new NoSuchRequestHandlingMethodException(lookupPath, request.getMethod(),
- request.getParameterMap());
- }
- }
-
- /**
- * Determines the combined pattern for the given methodLevelPattern and path.
- * Uses the following algorithm:
- * If there is a type-level mapping with path information, it is {@linkplain
- * PathMatcher#combine(String, String) combined} with the method-level pattern.
- * If there is a {@linkplain HandlerMapping#BEST_MATCHING_PATTERN_ATTRIBUTE best matching pattern} in the
- * request, it is combined with the method-level pattern.
- * Otherwise, the method-level pattern is returned.
- *
- */
- private String getCombinedPattern(String methodLevelPattern, String lookupPath, HttpServletRequest request) {
- if (hasTypeLevelMapping() && (!ObjectUtils.isEmpty(getTypeLevelMapping().value()))) {
- String[] typeLevelPatterns = getTypeLevelMapping().value();
- for (String typeLevelPattern : typeLevelPatterns) {
- if (!typeLevelPattern.startsWith("/")) {
- typeLevelPattern = "/" + typeLevelPattern;
- }
- String combinedPattern = pathMatcher.combine(typeLevelPattern, methodLevelPattern);
- if (isPathMatchInternal(combinedPattern, lookupPath)) {
- return combinedPattern;
- }
- }
- return null;
- }
- String bestMatchingPattern = (String) request.getAttribute(HandlerMapping.BEST_MATCHING_PATTERN_ATTRIBUTE);
- if (StringUtils.hasText(bestMatchingPattern) && bestMatchingPattern.endsWith("*")) {
- String combinedPattern = pathMatcher.combine(bestMatchingPattern, methodLevelPattern);
- if (!combinedPattern.equals(bestMatchingPattern) &&
- (isPathMatchInternal(combinedPattern, lookupPath))) {
- return combinedPattern;
- }
- }
- if (isPathMatchInternal(methodLevelPattern, lookupPath)) {
- return methodLevelPattern;
- }
- return null;
- }
-
- private boolean isPathMatchInternal(String pattern, String lookupPath) {
- if (pattern.equals(lookupPath) || pathMatcher.match(pattern, lookupPath)) {
- return true;
- }
- boolean hasSuffix = pattern.indexOf('.') != -1;
- if (!hasSuffix && pathMatcher.match(pattern + ".*", lookupPath)) {
- return true;
- }
- boolean endsWithSlash = pattern.endsWith("/");
- if (!endsWithSlash && pathMatcher.match(pattern + "/", lookupPath)) {
- return true;
- }
- return false;
- }
-
- @SuppressWarnings("unchecked")
- private void extractHandlerMethodUriTemplates(String mappedPattern,
- String lookupPath,
- HttpServletRequest request) {
-
- Map variables =
- (Map) request.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
-
- int patternVariableCount = StringUtils.countOccurrencesOf(mappedPattern, "{");
-
- if ((variables == null || patternVariableCount != variables.size())
- && pathMatcher.match(mappedPattern, lookupPath)) {
- variables = pathMatcher.extractUriTemplateVariables(mappedPattern, lookupPath);
- request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, variables);
- }
- }
- }
-
-
- /**
- * Servlet-specific subclass of {@link HandlerMethodInvoker}.
- */
- private class ServletHandlerMethodInvoker extends InterceptingHandlerMethodInvoker {
-
- private boolean responseArgumentUsed = false;
-
- private ServletHandlerMethodInvoker(HandlerMethodResolver resolver, ActionInterceptor[] actionInterceptors) {
- super(resolver, webBindingInitializer, amhaSessionAttributeStore, parameterNameDiscoverer,
- customArgumentResolvers, messageConverters, actionInterceptors);
- }
-
- public ModelAndView interceptingInvokeHandlerMethod(Method handlerMethod, Object handler,
- NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
-
- int interceptorIndex = -1;
- ModelAndView mav = null;
- ActionExecutingContext executingContext = null;
- Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
- try {
- boolean debug = logger.isDebugEnabled();
- for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
- Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
- if (attrValue != null) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
- Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
- Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
- }
- String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
- if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
- continue;
- }
- ReflectionUtils.makeAccessible(attributeMethodToInvoke);
- Object attrValue = attributeMethodToInvoke.invoke(handler, args);
- if ("".equals(attrName)) {
- Class resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
- attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
- }
- if (!implicitModel.containsAttribute(attrName)) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
- }
- ReflectionUtils.makeAccessible(handlerMethodToInvoke);
-
- executingContext = new ActionExecutingContext((ServletWebRequest) webRequest, handler, handlerMethodToInvoke, args, implicitModel);
-
- // Apply preHandle methods of registered interceptors.
- ActionInterceptor[] interceptors = getActionInterceptors();
- if (interceptors != null) {
- for (int i = 0; i < interceptors.length; i++) {
- ActionInterceptor interceptor = interceptors[i];
- if (!interceptor.preHandle(executingContext)) {
- triggerAfterCompletion(executingContext, interceptorIndex, null, null);
- return null; //TODO verify null is ok
- }
- interceptorIndex = i;
- }
- }
-
- // Actually invoke the handler
- Object result = handlerMethodToInvoke.invoke(handler, args);
-
-
- mav = getModelAndView(handlerMethod, handler.getClass(), result, implicitModel, (ServletWebRequest) webRequest);
- updateModelAttributes(handler, (mav != null ? mav.getModel() : null), implicitModel, webRequest);
-
- // Trigger after-completion for successful outcome
- triggerAfterCompletion(executingContext, interceptorIndex, mav, null);
-
- return mav;
- } catch (IllegalStateException ex) {
- // Internal assertion failed (e.g. invalid signature):
- // throw exception with full handler method context...
- triggerAfterCompletion(executingContext, interceptorIndex, mav, ex);
- throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
- } catch (InvocationTargetException ex) {
- // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
- triggerAfterCompletion(executingContext, interceptorIndex, mav, ex);
- ReflectionUtils.rethrowException(ex.getTargetException());
- return null;
- }
- }
-
- private void triggerAfterCompletion(ActionExecutingContext executingContext,
- int interceptorIndex,
- ModelAndView modelAndView,
- Exception ex) throws Exception {
-
- // Apply afterCompletion methods of registered interceptors.
- if (executingContext.getHandler() != null) {
- //TODO should be passed in;
- ActionInterceptor[] interceptors = getActionInterceptors();
- if (interceptors != null) {
- for (int i = interceptorIndex; i >= 0; i--) {
- ActionInterceptor interceptor = interceptors[i];
- ActionExecutedContext actionExecutedContext = new ActionExecutedContext(executingContext, modelAndView, ex);
- try {
- interceptor.afterCompletion(actionExecutedContext);
- } catch (Throwable ex2) {
- logger.error("ActionInterceptor threw exception", ex2);
- }
- }
- }
- }
- }
-
-
- @Override
- protected void raiseMissingParameterException(String paramName, Class paramType) throws Exception {
- throw new MissingServletRequestParameterException(paramName, paramType.getSimpleName());
- }
-
- @Override
- protected void raiseSessionRequiredException(String message) throws Exception {
- throw new HttpSessionRequiredException(message);
- }
-
- @Override
- protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
- throws Exception {
-
- return AnnotationMethodHandlerAdapter.this.createBinder(
- webRequest.getNativeRequest(HttpServletRequest.class), target, objectName);
- }
-
- @Override
- protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
- ServletRequestDataBinder servletBinder = (ServletRequestDataBinder) binder;
- servletBinder.bind(webRequest.getNativeRequest(ServletRequest.class));
- }
-
- @Override
- protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
- HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
- return AnnotationMethodHandlerAdapter.this.createHttpInputMessage(servletRequest);
- }
-
- @Override
- protected HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) throws Exception {
- HttpServletResponse servletResponse = (HttpServletResponse) webRequest.getNativeResponse();
- return AnnotationMethodHandlerAdapter.this.createHttpOutputMessage(servletResponse);
- }
-
- @Override
- protected Object resolveDefaultValue(String value) {
- if (beanFactory == null) {
- return value;
- }
- String placeholdersResolved = beanFactory.resolveEmbeddedValue(value);
- BeanExpressionResolver exprResolver = beanFactory.getBeanExpressionResolver();
- if (exprResolver == null) {
- return value;
- }
- return exprResolver.evaluate(placeholdersResolved, expressionContext);
- }
-
- @Override
- protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
- Cookie cookieValue = WebUtils.getCookie(servletRequest, cookieName);
- if (Cookie.class.isAssignableFrom(paramType)) {
- return cookieValue;
- } else if (cookieValue != null) {
- return urlPathHelper.decodeRequestString(servletRequest, cookieValue.getValue());
- } else {
- return null;
- }
- }
-
- @Override
- @SuppressWarnings({"unchecked"})
- protected String resolvePathVariable(String pathVarName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
- Map uriTemplateVariables =
- (Map) servletRequest.getAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE);
- if (uriTemplateVariables == null || !uriTemplateVariables.containsKey(pathVarName)) {
- throw new IllegalStateException(
- "Could not find @PathVariable [" + pathVarName + "] in @RequestMapping");
- }
- return uriTemplateVariables.get(pathVarName);
- }
-
- @Override
- protected Object resolveStandardArgument(Class> parameterType, NativeWebRequest webRequest) throws Exception {
- HttpServletRequest request = webRequest.getNativeRequest(HttpServletRequest.class);
- HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
-
- if (ServletRequest.class.isAssignableFrom(parameterType) ||
- MultipartRequest.class.isAssignableFrom(parameterType)) {
- Object nativeRequest = webRequest.getNativeRequest(parameterType);
- if (nativeRequest == null) {
- throw new IllegalStateException(
- "Current request is not of type [" + parameterType.getName() + "]: " + request);
- }
- return nativeRequest;
- } else if (ServletResponse.class.isAssignableFrom(parameterType)) {
- this.responseArgumentUsed = true;
- Object nativeResponse = webRequest.getNativeResponse(parameterType);
- if (nativeResponse == null) {
- throw new IllegalStateException(
- "Current response is not of type [" + parameterType.getName() + "]: " + response);
- }
- return nativeResponse;
- } else if (HttpSession.class.isAssignableFrom(parameterType)) {
- return request.getSession();
- } else if (Principal.class.isAssignableFrom(parameterType)) {
- return request.getUserPrincipal();
- } else if (Locale.class.equals(parameterType)) {
- return RequestContextUtils.getLocale(request);
- } else if (InputStream.class.isAssignableFrom(parameterType)) {
- return request.getInputStream();
- } else if (Reader.class.isAssignableFrom(parameterType)) {
- return request.getReader();
- } else if (OutputStream.class.isAssignableFrom(parameterType)) {
- this.responseArgumentUsed = true;
- return response.getOutputStream();
- } else if (Writer.class.isAssignableFrom(parameterType)) {
- this.responseArgumentUsed = true;
- return response.getWriter();
- }
- return super.resolveStandardArgument(parameterType, webRequest);
- }
-
- @SuppressWarnings("unchecked")
- public ModelAndView getModelAndView(Method handlerMethod, Class handlerType, Object returnValue,
- ExtendedModelMap implicitModel, ServletWebRequest webRequest) throws Exception {
-
- ResponseStatus responseStatusAnn = AnnotationUtils.findAnnotation(handlerMethod, ResponseStatus.class);
- if (responseStatusAnn != null) {
- HttpStatus responseStatus = responseStatusAnn.value();
- String reason = responseStatusAnn.reason();
- if (!StringUtils.hasText(reason)) {
- webRequest.getResponse().setStatus(responseStatus.value());
- } else {
- webRequest.getResponse().sendError(responseStatus.value(), reason);
- }
-
- // to be picked up by the RedirectView
- webRequest.getRequest().setAttribute(View.RESPONSE_STATUS_ATTRIBUTE, responseStatus);
-
- responseArgumentUsed = true;
- }
-
- // Invoke custom resolvers if present...
- if (customModelAndViewResolvers != null) {
- for (ModelAndViewResolver mavResolver : customModelAndViewResolvers) {
- ModelAndView mav = mavResolver.resolveModelAndView(
- handlerMethod, handlerType, returnValue, implicitModel, webRequest);
- if (mav != ModelAndViewResolver.UNRESOLVED) {
- return mav;
- }
- }
- }
-
- if (returnValue instanceof HttpEntity) {
- handleHttpEntityResponse((HttpEntity>) returnValue, webRequest);
- return null;
- } else if (AnnotationUtils.findAnnotation(handlerMethod, ResponseBody.class) != null) {
- handleResponseBody(returnValue, webRequest);
- return null;
- } else if (returnValue instanceof ModelAndView) {
- ModelAndView mav = (ModelAndView) returnValue;
- mav.getModelMap().mergeAttributes(implicitModel);
- return mav;
- } else if (returnValue instanceof Model) {
- return new ModelAndView().addAllObjects(implicitModel).addAllObjects(((Model) returnValue).asMap());
- } else if (returnValue instanceof View) {
- return new ModelAndView((View) returnValue).addAllObjects(implicitModel);
- } else if (AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class) != null) {
- addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
- return new ModelAndView().addAllObjects(implicitModel);
- } else if (returnValue instanceof Map) {
- return new ModelAndView().addAllObjects(implicitModel).addAllObjects((Map) returnValue);
- } else if (returnValue instanceof String) {
- return new ModelAndView((String) returnValue).addAllObjects(implicitModel);
- } else if (returnValue == null) {
- // Either returned null or was 'void' return.
- if (this.responseArgumentUsed || webRequest.isNotModified()) {
- return null;
- } else {
- // Assuming view name translation...
- return new ModelAndView().addAllObjects(implicitModel);
- }
- } else if (!BeanUtils.isSimpleProperty(returnValue.getClass())) {
- // Assume a single model attribute...
- addReturnValueAsModelAttribute(handlerMethod, handlerType, returnValue, implicitModel);
- return new ModelAndView().addAllObjects(implicitModel);
- } else {
- throw new IllegalArgumentException("Invalid handler method return value: " + returnValue);
- }
- }
-
- private void handleResponseBody(Object returnValue, ServletWebRequest webRequest)
- throws Exception {
- if (returnValue == null) {
- return;
- }
- HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
- HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
- writeWithMessageConverters(returnValue, inputMessage, outputMessage);
- }
-
- private void handleHttpEntityResponse(HttpEntity> responseEntity, ServletWebRequest webRequest)
- throws Exception {
- if (responseEntity == null) {
- return;
- }
- HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
- HttpOutputMessage outputMessage = createHttpOutputMessage(webRequest);
- if (responseEntity instanceof ResponseEntity && outputMessage instanceof ServerHttpResponse) {
- ((ServerHttpResponse) outputMessage).setStatusCode(((ResponseEntity) responseEntity).getStatusCode());
- }
- HttpHeaders entityHeaders = responseEntity.getHeaders();
- if (!entityHeaders.isEmpty()) {
- outputMessage.getHeaders().putAll(entityHeaders);
- }
- Object body = responseEntity.getBody();
- if (body != null) {
- writeWithMessageConverters(body, inputMessage, outputMessage);
- } else {
- // flush headers
- outputMessage.getBody();
- }
- }
-
- @SuppressWarnings("unchecked")
- private void writeWithMessageConverters(Object returnValue,
- HttpInputMessage inputMessage, HttpOutputMessage outputMessage)
- throws IOException, HttpMediaTypeNotAcceptableException {
- List acceptedMediaTypes = inputMessage.getHeaders().getAccept();
- if (acceptedMediaTypes.isEmpty()) {
- acceptedMediaTypes = Collections.singletonList(MediaType.ALL);
- }
- MediaType.sortByQualityValue(acceptedMediaTypes);
- Class> returnValueType = returnValue.getClass();
- List allSupportedMediaTypes = new ArrayList();
- if (getMessageConverters() != null) {
- for (MediaType acceptedMediaType : acceptedMediaTypes) {
- for (HttpMessageConverter messageConverter : getMessageConverters()) {
- if (messageConverter.canWrite(returnValueType, acceptedMediaType)) {
- messageConverter.write(returnValue, acceptedMediaType, outputMessage);
- if (logger.isDebugEnabled()) {
- MediaType contentType = outputMessage.getHeaders().getContentType();
- if (contentType == null) {
- contentType = acceptedMediaType;
- }
- logger.debug("Written [" + returnValue + "] as \"" + contentType +
- "\" using [" + messageConverter + "]");
- }
- this.responseArgumentUsed = true;
- return;
- }
- }
- }
- for (HttpMessageConverter messageConverter : messageConverters) {
- allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
- }
- }
- throw new HttpMediaTypeNotAcceptableException(allSupportedMediaTypes);
- }
-
- }
-
-
- /**
- * Holder for request mapping metadata. Allows for finding a best matching candidate.
- */
- static class RequestMappingInfo {
-
- String[] patterns = new String[0];
-
- List matchedPatterns = Collections.emptyList();
-
- RequestMethod[] methods = new RequestMethod[0];
-
- String[] params = new String[0];
-
- String[] headers = new String[0];
-
- public boolean hasPatterns() {
- return patterns.length > 0;
- }
-
- public String bestMatchedPattern() {
- return (!this.matchedPatterns.isEmpty() ? this.matchedPatterns.get(0) : null);
- }
-
- public boolean matches(HttpServletRequest request) {
- return matchesRequestMethod(request) && matchesParameters(request) && matchesHeaders(request);
- }
-
- public boolean matchesHeaders(HttpServletRequest request) {
- return ServletAnnotationMappingUtils.checkHeaders(this.headers, request);
- }
-
- public boolean matchesParameters(HttpServletRequest request) {
- return ServletAnnotationMappingUtils.checkParameters(this.params, request);
- }
-
- public boolean matchesRequestMethod(HttpServletRequest request) {
- return ServletAnnotationMappingUtils.checkRequestMethod(this.methods, request);
- }
-
- public Set methodNames() {
- Set methodNames = new LinkedHashSet(methods.length);
- for (RequestMethod method : methods) {
- methodNames.add(method.name());
- }
- return methodNames;
- }
-
- @Override
- public boolean equals(Object obj) {
- RequestMappingInfo other = (RequestMappingInfo) obj;
- return (Arrays.equals(this.patterns, other.patterns) && Arrays.equals(this.methods, other.methods) &&
- Arrays.equals(this.params, other.params) && Arrays.equals(this.headers, other.headers));
- }
-
- @Override
- public int hashCode() {
- return (Arrays.hashCode(this.patterns) * 23 + Arrays.hashCode(this.methods) * 29 +
- Arrays.hashCode(this.params) * 31 + Arrays.hashCode(this.headers));
- }
-
- @Override
- public String toString() {
- StringBuilder builder = new StringBuilder();
- builder.append(Arrays.asList(patterns));
- if (methods.length > 0) {
- builder.append(',');
- builder.append(Arrays.asList(methods));
- }
- if (headers.length > 0) {
- builder.append(',');
- builder.append(Arrays.asList(headers));
- }
- if (params.length > 0) {
- builder.append(',');
- builder.append(Arrays.asList(params));
- }
- return builder.toString();
- }
- }
-
-
- /**
- * Comparator capable of sorting {@link RequestMappingInfo}s (RHIs) so that sorting a list with this comparator will
- * result in:
- *
- * RHIs with {@linkplain RequestMappingInfo#matchedPatterns better matched paths} take prescedence
- * over those with a weaker match (as expressed by the {@linkplain PathMatcher#getPatternComparator(String) path
- * pattern comparator}.) Typically, this means that patterns without wild cards and uri templates will be ordered
- * before those without.
- * RHIs with one single {@linkplain RequestMappingInfo#methods request method} will be
- * ordered before those without a method, or with more than one method.
- * RHIs with more {@linkplain RequestMappingInfo#params request parameters} will be ordered before those with
- * less parameters
- *
- */
- static class RequestMappingInfoComparator implements Comparator {
-
- private final Comparator pathComparator;
-
- private final ServerHttpRequest request;
-
- RequestMappingInfoComparator(Comparator pathComparator, HttpServletRequest request) {
- this.pathComparator = pathComparator;
- this.request = new ServletServerHttpRequest(request);
- }
-
- public int compare(RequestMappingInfo info1, RequestMappingInfo info2) {
- int pathComparison = pathComparator.compare(info1.bestMatchedPattern(), info2.bestMatchedPattern());
- if (pathComparison != 0) {
- return pathComparison;
- }
- int info1ParamCount = info1.params.length;
- int info2ParamCount = info2.params.length;
- if (info1ParamCount != info2ParamCount) {
- return info2ParamCount - info1ParamCount;
- }
- int info1HeaderCount = info1.headers.length;
- int info2HeaderCount = info2.headers.length;
- if (info1HeaderCount != info2HeaderCount) {
- return info2HeaderCount - info1HeaderCount;
- }
- int acceptComparison = compareAcceptHeaders(info1, info2);
- if (acceptComparison != 0) {
- return acceptComparison;
- }
- int info1MethodCount = info1.methods.length;
- int info2MethodCount = info2.methods.length;
- if (info1MethodCount == 0 && info2MethodCount > 0) {
- return 1;
- } else if (info2MethodCount == 0 && info1MethodCount > 0) {
- return -1;
- } else if (info1MethodCount == 1 & info2MethodCount > 1) {
- return -1;
- } else if (info2MethodCount == 1 & info1MethodCount > 1) {
- return 1;
- }
- return 0;
- }
-
- private int compareAcceptHeaders(RequestMappingInfo info1, RequestMappingInfo info2) {
- List requestAccepts = request.getHeaders().getAccept();
- MediaType.sortByQualityValue(requestAccepts);
-
- List info1Accepts = getAcceptHeaderValue(info1);
- List info2Accepts = getAcceptHeaderValue(info2);
-
- for (MediaType requestAccept : requestAccepts) {
- int pos1 = indexOfIncluded(info1Accepts, requestAccept);
- int pos2 = indexOfIncluded(info2Accepts, requestAccept);
- if (pos1 != pos2) {
- return pos2 - pos1;
- }
- }
- return 0;
- }
-
- private int indexOfIncluded(List infoAccepts, MediaType requestAccept) {
- for (int i = 0; i < infoAccepts.size(); i++) {
- MediaType info1Accept = infoAccepts.get(i);
- if (requestAccept.includes(info1Accept)) {
- return i;
- }
- }
- return -1;
- }
-
- private List getAcceptHeaderValue(RequestMappingInfo info) {
- for (String header : info.headers) {
- int separator = header.indexOf('=');
- if (separator != -1) {
- String key = header.substring(0, separator);
- String value = header.substring(separator + 1);
- if ("Accept".equalsIgnoreCase(key)) {
- return MediaType.parseMediaTypes(value);
- }
- }
- }
- return Collections.emptyList();
- }
- }
-
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/ServletAnnotationMappingUtils.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/ServletAnnotationMappingUtils.java
deleted file mode 100644
index 5d0bd7386..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/ServletAnnotationMappingUtils.java
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.document.web.servlet.mvc.annotation;
-
-import java.util.Iterator;
-import java.util.List;
-import javax.servlet.http.HttpServletRequest;
-
-import org.springframework.http.MediaType;
-import org.springframework.util.ObjectUtils;
-import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.util.WebUtils;
-
-/**
- * Helper class for annotation-based request mapping.
- *
- * @author Juergen Hoeller
- * @author Arjen Poutsma
- * @since 2.5.2
- */
-abstract class ServletAnnotationMappingUtils {
-
- /**
- * Check whether the given request matches the specified request methods.
- *
- * @param methods the HTTP request methods to check against
- * @param request the current HTTP request to check
- */
- public static boolean checkRequestMethod(RequestMethod[] methods, HttpServletRequest request) {
- if (ObjectUtils.isEmpty(methods)) {
- return true;
- }
- for (RequestMethod method : methods) {
- if (method.name().equals(request.getMethod())) {
- return true;
- }
- }
- return false;
- }
-
- /**
- * Check whether the given request matches the specified parameter conditions.
- *
- * @param params the parameter conditions, following
- * {@link org.springframework.web.bind.annotation.RequestMapping#params() RequestMapping.#params()}
- * @param request the current HTTP request to check
- */
- public static boolean checkParameters(String[] params, HttpServletRequest request) {
- if (!ObjectUtils.isEmpty(params)) {
- for (String param : params) {
- int separator = param.indexOf('=');
- if (separator == -1) {
- if (param.startsWith("!")) {
- if (WebUtils.hasSubmitParameter(request, param.substring(1))) {
- return false;
- }
- } else if (!WebUtils.hasSubmitParameter(request, param)) {
- return false;
- }
- } else {
- boolean negated = separator > 0 && param.charAt(separator - 1) == '!';
- String key = !negated ? param.substring(0, separator) : param.substring(0, separator - 1);
- String value = param.substring(separator + 1);
- if (!value.equals(request.getParameter(key))) {
- return negated;
- }
- }
- }
- }
- return true;
- }
-
- /**
- * Check whether the given request matches the specified header conditions.
- *
- * @param headers the header conditions, following
- * {@link org.springframework.web.bind.annotation.RequestMapping#headers() RequestMapping.headers()}
- * @param request the current HTTP request to check
- */
- public static boolean checkHeaders(String[] headers, HttpServletRequest request) {
- if (!ObjectUtils.isEmpty(headers)) {
- for (String header : headers) {
- int separator = header.indexOf('=');
- if (separator == -1) {
- if (header.startsWith("!")) {
- if (request.getHeader(header.substring(1)) != null) {
- return false;
- }
- } else if (request.getHeader(header) == null) {
- return false;
- }
- } else {
- boolean negated = separator > 0 && header.charAt(separator - 1) == '!';
- String key = !negated ? header.substring(0, separator) : header.substring(0, separator - 1);
- String value = header.substring(separator + 1);
- if (isMediaTypeHeader(key)) {
- List requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(key));
- List valueMediaTypes = MediaType.parseMediaTypes(value);
- boolean found = false;
- for (Iterator valIter = valueMediaTypes.iterator(); valIter.hasNext() && !found;) {
- MediaType valueMediaType = valIter.next();
- for (Iterator reqIter = requestMediaTypes.iterator();
- reqIter.hasNext() && !found;) {
- MediaType requestMediaType = reqIter.next();
- if (valueMediaType.includes(requestMediaType)) {
- found = true;
- }
- }
-
- }
- if (!found) {
- return negated;
- }
- } else if (!value.equals(request.getHeader(key))) {
- return negated;
- }
- }
- }
- }
- return true;
- }
-
- private static boolean isMediaTypeHeader(String headerName) {
- return "Accept".equalsIgnoreCase(headerName) || "Content-Type".equalsIgnoreCase(headerName);
- }
-
-}
diff --git a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/support/InterceptingHandlerMethodInvoker.java b/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/support/InterceptingHandlerMethodInvoker.java
deleted file mode 100644
index 76abcbc31..000000000
--- a/spring-data-document-core/src/main/java/org/springframework/data/document/web/servlet/mvc/annotation/support/InterceptingHandlerMethodInvoker.java
+++ /dev/null
@@ -1,828 +0,0 @@
-/*
- * 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.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.springframework.data.document.web.servlet.mvc.annotation.support;
-
-import java.lang.annotation.Annotation;
-import java.lang.reflect.*;
-import java.util.*;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.core.*;
-import org.springframework.core.annotation.AnnotationUtils;
-import org.springframework.data.document.web.servlet.ActionInterceptor;
-import org.springframework.http.*;
-import org.springframework.http.converter.HttpMessageConverter;
-import org.springframework.ui.ExtendedModelMap;
-import org.springframework.ui.Model;
-import org.springframework.util.*;
-import org.springframework.validation.BindException;
-import org.springframework.validation.BindingResult;
-import org.springframework.validation.Errors;
-import org.springframework.web.HttpMediaTypeNotSupportedException;
-import org.springframework.web.bind.WebDataBinder;
-import org.springframework.web.bind.annotation.*;
-import org.springframework.web.bind.annotation.support.HandlerMethodInvocationException;
-import org.springframework.web.bind.annotation.support.HandlerMethodResolver;
-import org.springframework.web.bind.support.*;
-import org.springframework.web.context.request.NativeWebRequest;
-import org.springframework.web.context.request.WebRequest;
-import org.springframework.web.multipart.MultipartFile;
-import org.springframework.web.multipart.MultipartRequest;
-
-/**
- * Support class for invoking an annotated handler method. Operates on the introspection results of a {@link
- * HandlerMethodResolver} for a specific handler type.
- *
- * Used by {@link org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter} and {@link
- * org.springframework.web.portlet.mvc.annotation.AnnotationMethodHandlerAdapter}.
- *
- * @author Juergen Hoeller
- * @author Arjen Poutsma
- * @see #invokeHandlerMethod
- * @since 2.5.2
- */
-public class InterceptingHandlerMethodInvoker {
-
- private static final String MODEL_KEY_PREFIX_STALE = SessionAttributeStore.class.getName() + ".STALE.";
-
- /**
- * We'll create a lot of these objects, so we don't want a new logger every time.
- */
- private static final Log logger = LogFactory.getLog(InterceptingHandlerMethodInvoker.class);
-
- protected final HandlerMethodResolver methodResolver;
-
- private final WebBindingInitializer bindingInitializer;
-
- protected final SessionAttributeStore sessionAttributeStore;
-
- private final ParameterNameDiscoverer parameterNameDiscoverer;
-
- private final WebArgumentResolver[] customArgumentResolvers;
-
- private final HttpMessageConverter[] messageConverters;
-
- private final ActionInterceptor[] actionInterceptors;
-
- private final SimpleSessionStatus sessionStatus = new SimpleSessionStatus();
-
-
- public InterceptingHandlerMethodInvoker(HandlerMethodResolver methodResolver) {
- this(methodResolver, null);
- }
-
- public InterceptingHandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer) {
- this(methodResolver, bindingInitializer, new DefaultSessionAttributeStore(), null, null, null, null);
- }
-
- public InterceptingHandlerMethodInvoker(HandlerMethodResolver methodResolver, WebBindingInitializer bindingInitializer,
- SessionAttributeStore sessionAttributeStore, ParameterNameDiscoverer parameterNameDiscoverer,
- WebArgumentResolver[] customArgumentResolvers, HttpMessageConverter[] messageConverters, ActionInterceptor[] actionInterceptors) {
-
- this.methodResolver = methodResolver;
- this.bindingInitializer = bindingInitializer;
- this.sessionAttributeStore = sessionAttributeStore;
- this.parameterNameDiscoverer = parameterNameDiscoverer;
- this.customArgumentResolvers = customArgumentResolvers;
- this.messageConverters = messageConverters;
- this.actionInterceptors = actionInterceptors;
- }
-
- protected ActionInterceptor[] getActionInterceptors() {
- return actionInterceptors;
- }
-
-
- public final Object invokeHandlerMethod(Method handlerMethod, Object handler,
- NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
-
- Method handlerMethodToInvoke = BridgeMethodResolver.findBridgedMethod(handlerMethod);
- try {
- boolean debug = logger.isDebugEnabled();
- for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
- Object attrValue = this.sessionAttributeStore.retrieveAttribute(webRequest, attrName);
- if (attrValue != null) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- for (Method attributeMethod : this.methodResolver.getModelAttributeMethods()) {
- Method attributeMethodToInvoke = BridgeMethodResolver.findBridgedMethod(attributeMethod);
- Object[] args = resolveHandlerArguments(attributeMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking model attribute method: " + attributeMethodToInvoke);
- }
- String attrName = AnnotationUtils.findAnnotation(attributeMethod, ModelAttribute.class).value();
- if (!"".equals(attrName) && implicitModel.containsAttribute(attrName)) {
- continue;
- }
- ReflectionUtils.makeAccessible(attributeMethodToInvoke);
- Object attrValue = attributeMethodToInvoke.invoke(handler, args);
- if ("".equals(attrName)) {
- Class resolvedType = GenericTypeResolver.resolveReturnType(attributeMethodToInvoke, handler.getClass());
- attrName = Conventions.getVariableNameForReturnType(attributeMethodToInvoke, resolvedType, attrValue);
- }
- if (!implicitModel.containsAttribute(attrName)) {
- implicitModel.addAttribute(attrName, attrValue);
- }
- }
- Object[] args = resolveHandlerArguments(handlerMethodToInvoke, handler, webRequest, implicitModel);
- if (debug) {
- logger.debug("Invoking request handler method: " + handlerMethodToInvoke);
- }
- ReflectionUtils.makeAccessible(handlerMethodToInvoke);
- return handlerMethodToInvoke.invoke(handler, args);
- } catch (IllegalStateException ex) {
- // Internal assertion failed (e.g. invalid signature):
- // throw exception with full handler method context...
- throw new HandlerMethodInvocationException(handlerMethodToInvoke, ex);
- } catch (InvocationTargetException ex) {
- // User-defined @ModelAttribute/@InitBinder/@RequestMapping method threw an exception...
- ReflectionUtils.rethrowException(ex.getTargetException());
- return null;
- }
- }
-
- public final void updateModelAttributes(Object handler, Map mavModel,
- ExtendedModelMap implicitModel, NativeWebRequest webRequest) throws Exception {
-
- if (this.methodResolver.hasSessionAttributes() && this.sessionStatus.isComplete()) {
- for (String attrName : this.methodResolver.getActualSessionAttributeNames()) {
- this.sessionAttributeStore.cleanupAttribute(webRequest, attrName);
- }
- }
-
- // Expose model attributes as session attributes, if required.
- // Expose BindingResults for all attributes, making custom editors available.
- Map model = (mavModel != null ? mavModel : implicitModel);
- if (model != null) {
- try {
- String[] originalAttrNames = model.keySet().toArray(new String[model.size()]);
- for (String attrName : originalAttrNames) {
- Object attrValue = model.get(attrName);
- boolean isSessionAttr = this.methodResolver.isSessionAttribute(
- attrName, (attrValue != null ? attrValue.getClass() : null));
- if (isSessionAttr) {
- if (this.sessionStatus.isComplete()) {
- implicitModel.put(MODEL_KEY_PREFIX_STALE + attrName, Boolean.TRUE);
- } else if (!implicitModel.containsKey(MODEL_KEY_PREFIX_STALE + attrName)) {
- this.sessionAttributeStore.storeAttribute(webRequest, attrName, attrValue);
- }
- }
- if (!attrName.startsWith(BindingResult.MODEL_KEY_PREFIX) &&
- (isSessionAttr || isBindingCandidate(attrValue))) {
- String bindingResultKey = BindingResult.MODEL_KEY_PREFIX + attrName;
- if (mavModel != null && !model.containsKey(bindingResultKey)) {
- WebDataBinder binder = createBinder(webRequest, attrValue, attrName);
- initBinder(handler, attrName, binder, webRequest);
- mavModel.put(bindingResultKey, binder.getBindingResult());
- }
- }
- }
- } catch (InvocationTargetException ex) {
- // User-defined @InitBinder method threw an exception...
- ReflectionUtils.rethrowException(ex.getTargetException());
- }
- }
- }
-
-
- protected Object[] resolveHandlerArguments(Method handlerMethod, Object handler,
- NativeWebRequest webRequest, ExtendedModelMap implicitModel) throws Exception {
-
- Class[] paramTypes = handlerMethod.getParameterTypes();
- Object[] args = new Object[paramTypes.length];
-
- for (int i = 0; i < args.length; i++) {
- MethodParameter methodParam = new MethodParameter(handlerMethod, i);
- methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
- GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
- String paramName = null;
- String headerName = null;
- boolean requestBodyFound = false;
- String cookieName = null;
- String pathVarName = null;
- String attrName = null;
- boolean required = false;
- String defaultValue = null;
- boolean validate = false;
- int annotationsFound = 0;
- Annotation[] paramAnns = methodParam.getParameterAnnotations();
-
- for (Annotation paramAnn : paramAnns) {
- if (RequestParam.class.isInstance(paramAnn)) {
- RequestParam requestParam = (RequestParam) paramAnn;
- paramName = requestParam.value();
- required = requestParam.required();
- defaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
- annotationsFound++;
- } else if (RequestHeader.class.isInstance(paramAnn)) {
- RequestHeader requestHeader = (RequestHeader) paramAnn;
- headerName = requestHeader.value();
- required = requestHeader.required();
- defaultValue = parseDefaultValueAttribute(requestHeader.defaultValue());
- annotationsFound++;
- } else if (RequestBody.class.isInstance(paramAnn)) {
- requestBodyFound = true;
- annotationsFound++;
- } else if (CookieValue.class.isInstance(paramAnn)) {
- CookieValue cookieValue = (CookieValue) paramAnn;
- cookieName = cookieValue.value();
- required = cookieValue.required();
- defaultValue = parseDefaultValueAttribute(cookieValue.defaultValue());
- annotationsFound++;
- } else if (PathVariable.class.isInstance(paramAnn)) {
- PathVariable pathVar = (PathVariable) paramAnn;
- pathVarName = pathVar.value();
- annotationsFound++;
- } else if (ModelAttribute.class.isInstance(paramAnn)) {
- ModelAttribute attr = (ModelAttribute) paramAnn;
- attrName = attr.value();
- annotationsFound++;
- } else if (Value.class.isInstance(paramAnn)) {
- defaultValue = ((Value) paramAnn).value();
- } else if ("Valid".equals(paramAnn.annotationType().getSimpleName())) {
- validate = true;
- }
- }
-
- if (annotationsFound > 1) {
- throw new IllegalStateException("Handler parameter annotations are exclusive choices - " +
- "do not specify more than one such annotation on the same parameter: " + handlerMethod);
- }
-
- if (annotationsFound == 0) {
- Object argValue = resolveCommonArgument(methodParam, webRequest);
- if (argValue != WebArgumentResolver.UNRESOLVED) {
- args[i] = argValue;
- } else if (defaultValue != null) {
- args[i] = resolveDefaultValue(defaultValue);
- } else {
- Class paramType = methodParam.getParameterType();
- if (Model.class.isAssignableFrom(paramType) || Map.class.isAssignableFrom(paramType)) {
- args[i] = implicitModel;
- } else if (SessionStatus.class.isAssignableFrom(paramType)) {
- args[i] = this.sessionStatus;
- } else if (HttpEntity.class.isAssignableFrom(paramType)) {
- args[i] = resolveHttpEntityRequest(methodParam, webRequest);
- } else if (Errors.class.isAssignableFrom(paramType)) {
- throw new IllegalStateException("Errors/BindingResult argument declared " +
- "without preceding model attribute. Check your handler method signature!");
- } else if (BeanUtils.isSimpleProperty(paramType)) {
- paramName = "";
- } else {
- attrName = "";
- }
- }
- }
-
- if (paramName != null) {
- args[i] = resolveRequestParam(paramName, required, defaultValue, methodParam, webRequest, handler);
- } else if (headerName != null) {
- args[i] = resolveRequestHeader(headerName, required, defaultValue, methodParam, webRequest, handler);
- } else if (requestBodyFound) {
- args[i] = resolveRequestBody(methodParam, webRequest, handler);
- } else if (cookieName != null) {
- args[i] = resolveCookieValue(cookieName, required, defaultValue, methodParam, webRequest, handler);
- } else if (pathVarName != null) {
- args[i] = resolvePathVariable(pathVarName, methodParam, webRequest, handler);
- } else if (attrName != null) {
- WebDataBinder binder =
- resolveModelAttribute(attrName, methodParam, implicitModel, webRequest, handler);
- boolean assignBindingResult = (args.length > i + 1 && Errors.class.isAssignableFrom(paramTypes[i + 1]));
- if (binder.getTarget() != null) {
- doBind(binder, webRequest, validate, !assignBindingResult);
- }
- args[i] = binder.getTarget();
- if (assignBindingResult) {
- args[i + 1] = binder.getBindingResult();
- i++;
- }
- implicitModel.putAll(binder.getBindingResult().getModel());
- }
- }
-
- return args;
- }
-
- protected void initBinder(Object handler, String attrName, WebDataBinder binder, NativeWebRequest webRequest)
- throws Exception {
-
- if (this.bindingInitializer != null) {
- this.bindingInitializer.initBinder(binder, webRequest);
- }
- if (handler != null) {
- Set initBinderMethods = this.methodResolver.getInitBinderMethods();
- if (!initBinderMethods.isEmpty()) {
- boolean debug = logger.isDebugEnabled();
- for (Method initBinderMethod : initBinderMethods) {
- Method methodToInvoke = BridgeMethodResolver.findBridgedMethod(initBinderMethod);
- String[] targetNames = AnnotationUtils.findAnnotation(initBinderMethod, InitBinder.class).value();
- if (targetNames.length == 0 || Arrays.asList(targetNames).contains(attrName)) {
- Object[] initBinderArgs =
- resolveInitBinderArguments(handler, methodToInvoke, binder, webRequest);
- if (debug) {
- logger.debug("Invoking init-binder method: " + methodToInvoke);
- }
- ReflectionUtils.makeAccessible(methodToInvoke);
- Object returnValue = methodToInvoke.invoke(handler, initBinderArgs);
- if (returnValue != null) {
- throw new IllegalStateException(
- "InitBinder methods must not have a return value: " + methodToInvoke);
- }
- }
- }
- }
- }
- }
-
- private Object[] resolveInitBinderArguments(Object handler, Method initBinderMethod,
- WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
-
- Class[] initBinderParams = initBinderMethod.getParameterTypes();
- Object[] initBinderArgs = new Object[initBinderParams.length];
-
- for (int i = 0; i < initBinderArgs.length; i++) {
- MethodParameter methodParam = new MethodParameter(initBinderMethod, i);
- methodParam.initParameterNameDiscovery(this.parameterNameDiscoverer);
- GenericTypeResolver.resolveParameterType(methodParam, handler.getClass());
- String paramName = null;
- boolean paramRequired = false;
- String paramDefaultValue = null;
- String pathVarName = null;
- Annotation[] paramAnns = methodParam.getParameterAnnotations();
-
- for (Annotation paramAnn : paramAnns) {
- if (RequestParam.class.isInstance(paramAnn)) {
- RequestParam requestParam = (RequestParam) paramAnn;
- paramName = requestParam.value();
- paramRequired = requestParam.required();
- paramDefaultValue = parseDefaultValueAttribute(requestParam.defaultValue());
- break;
- } else if (ModelAttribute.class.isInstance(paramAnn)) {
- throw new IllegalStateException(
- "@ModelAttribute is not supported on @InitBinder methods: " + initBinderMethod);
- } else if (PathVariable.class.isInstance(paramAnn)) {
- PathVariable pathVar = (PathVariable) paramAnn;
- pathVarName = pathVar.value();
- }
- }
-
- if (paramName == null && pathVarName == null) {
- Object argValue = resolveCommonArgument(methodParam, webRequest);
- if (argValue != WebArgumentResolver.UNRESOLVED) {
- initBinderArgs[i] = argValue;
- } else {
- Class paramType = initBinderParams[i];
- if (paramType.isInstance(binder)) {
- initBinderArgs[i] = binder;
- } else if (BeanUtils.isSimpleProperty(paramType)) {
- paramName = "";
- } else {
- throw new IllegalStateException("Unsupported argument [" + paramType.getName() +
- "] for @InitBinder method: " + initBinderMethod);
- }
- }
- }
-
- if (paramName != null) {
- initBinderArgs[i] =
- resolveRequestParam(paramName, paramRequired, paramDefaultValue, methodParam, webRequest, null);
- } else if (pathVarName != null) {
- initBinderArgs[i] = resolvePathVariable(pathVarName, methodParam, webRequest, null);
- }
- }
-
- return initBinderArgs;
- }
-
- @SuppressWarnings("unchecked")
- private Object resolveRequestParam(String paramName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (Map.class.isAssignableFrom(paramType) && paramName.length() == 0) {
- return resolveRequestParamMap((Class extends Map>) paramType, webRequest);
- }
- if (paramName.length() == 0) {
- paramName = getRequiredParameterName(methodParam);
- }
- Object paramValue = null;
- MultipartRequest multipartRequest = webRequest.getNativeRequest(MultipartRequest.class);
- if (multipartRequest != null) {
- List files = multipartRequest.getFiles(paramName);
- if (!files.isEmpty()) {
- if (files.size() == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
- paramValue = files.get(0);
- } else {
- paramValue = files;
- }
- }
- }
- if (paramValue == null) {
- String[] paramValues = webRequest.getParameterValues(paramName);
- if (paramValues != null) {
- if (paramValues.length == 1 && !paramType.isArray() && !Collection.class.isAssignableFrom(paramType)) {
- paramValue = paramValues[0];
- } else {
- paramValue = paramValues;
- }
- }
- }
- if (paramValue == null) {
- if (defaultValue != null) {
- paramValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingParameterException(paramName, paramType);
- }
- paramValue = checkValue(paramName, paramValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, paramName);
- initBinder(handlerForInitBinderCall, paramName, binder, webRequest);
- return binder.convertIfNecessary(paramValue, paramType, methodParam);
- }
-
- private Map resolveRequestParamMap(Class extends Map> mapType, NativeWebRequest webRequest) {
- Map parameterMap = webRequest.getParameterMap();
- if (MultiValueMap.class.isAssignableFrom(mapType)) {
- MultiValueMap result = new LinkedMultiValueMap(parameterMap.size());
- for (Map.Entry entry : parameterMap.entrySet()) {
- for (String value : entry.getValue()) {
- result.add(entry.getKey(), value);
- }
- }
- return result;
- } else {
- Map result = new LinkedHashMap(parameterMap.size());
- for (Map.Entry entry : parameterMap.entrySet()) {
- if (entry.getValue().length > 0) {
- result.put(entry.getKey(), entry.getValue()[0]);
- }
- }
- return result;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Object resolveRequestHeader(String headerName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (Map.class.isAssignableFrom(paramType)) {
- return resolveRequestHeaderMap((Class extends Map>) paramType, webRequest);
- }
- if (headerName.length() == 0) {
- headerName = getRequiredParameterName(methodParam);
- }
- Object headerValue = null;
- String[] headerValues = webRequest.getHeaderValues(headerName);
- if (headerValues != null) {
- headerValue = (headerValues.length == 1 ? headerValues[0] : headerValues);
- }
- if (headerValue == null) {
- if (defaultValue != null) {
- headerValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingHeaderException(headerName, paramType);
- }
- headerValue = checkValue(headerName, headerValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, headerName);
- initBinder(handlerForInitBinderCall, headerName, binder, webRequest);
- return binder.convertIfNecessary(headerValue, paramType, methodParam);
- }
-
- private Map resolveRequestHeaderMap(Class extends Map> mapType, NativeWebRequest webRequest) {
- if (MultiValueMap.class.isAssignableFrom(mapType)) {
- MultiValueMap result;
- if (HttpHeaders.class.isAssignableFrom(mapType)) {
- result = new HttpHeaders();
- } else {
- result = new LinkedMultiValueMap();
- }
- for (Iterator iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
- String headerName = iterator.next();
- for (String headerValue : webRequest.getHeaderValues(headerName)) {
- result.add(headerName, headerValue);
- }
- }
- return result;
- } else {
- Map result = new LinkedHashMap();
- for (Iterator iterator = webRequest.getHeaderNames(); iterator.hasNext();) {
- String headerName = iterator.next();
- String headerValue = webRequest.getHeader(headerName);
- result.put(headerName, headerValue);
- }
- return result;
- }
- }
-
- /**
- * Resolves the given {@link RequestBody @RequestBody} annotation.
- */
- protected Object resolveRequestBody(MethodParameter methodParam, NativeWebRequest webRequest, Object handler)
- throws Exception {
-
- return readWithMessageConverters(methodParam, createHttpInputMessage(webRequest), methodParam.getParameterType());
- }
-
- private HttpEntity resolveHttpEntityRequest(MethodParameter methodParam, NativeWebRequest webRequest)
- throws Exception {
-
- HttpInputMessage inputMessage = createHttpInputMessage(webRequest);
- Class> paramType = getHttpEntityType(methodParam);
- Object body = readWithMessageConverters(methodParam, inputMessage, paramType);
- return new HttpEntity(body, inputMessage.getHeaders());
- }
-
- private Object readWithMessageConverters(MethodParameter methodParam, HttpInputMessage inputMessage, Class paramType)
- throws Exception {
-
- MediaType contentType = inputMessage.getHeaders().getContentType();
- if (contentType == null) {
- StringBuilder builder = new StringBuilder(ClassUtils.getShortName(methodParam.getParameterType()));
- String paramName = methodParam.getParameterName();
- if (paramName != null) {
- builder.append(' ');
- builder.append(paramName);
- }
- throw new HttpMediaTypeNotSupportedException(
- "Cannot extract parameter (" + builder.toString() + "): no Content-Type found");
- }
-
- List allSupportedMediaTypes = new ArrayList();
- if (this.messageConverters != null) {
- for (HttpMessageConverter> messageConverter : this.messageConverters) {
- allSupportedMediaTypes.addAll(messageConverter.getSupportedMediaTypes());
- if (messageConverter.canRead(paramType, contentType)) {
- if (logger.isDebugEnabled()) {
- logger.debug("Reading [" + paramType.getName() + "] as \"" + contentType
- + "\" using [" + messageConverter + "]");
- }
- return messageConverter.read(paramType, inputMessage);
- }
- }
- }
- throw new HttpMediaTypeNotSupportedException(contentType, allSupportedMediaTypes);
- }
-
- private Class> getHttpEntityType(MethodParameter methodParam) {
- Assert.isAssignable(HttpEntity.class, methodParam.getParameterType());
- ParameterizedType type = (ParameterizedType) methodParam.getGenericParameterType();
- if (type.getActualTypeArguments().length == 1) {
- Type typeArgument = type.getActualTypeArguments()[0];
- if (typeArgument instanceof Class) {
- return (Class>) typeArgument;
- } else if (typeArgument instanceof GenericArrayType) {
- Type componentType = ((GenericArrayType) typeArgument).getGenericComponentType();
- if (componentType instanceof Class) {
- // Surely, there should be a nicer way to do this
- Object array = Array.newInstance((Class>) componentType, 0);
- return array.getClass();
- }
- }
- }
- throw new IllegalArgumentException(
- "HttpEntity parameter (" + methodParam.getParameterName() + ") is not parameterized");
-
- }
-
- private Object resolveCookieValue(String cookieName, boolean required, String defaultValue,
- MethodParameter methodParam, NativeWebRequest webRequest, Object handlerForInitBinderCall)
- throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (cookieName.length() == 0) {
- cookieName = getRequiredParameterName(methodParam);
- }
- Object cookieValue = resolveCookieValue(cookieName, paramType, webRequest);
- if (cookieValue == null) {
- if (defaultValue != null) {
- cookieValue = resolveDefaultValue(defaultValue);
- } else if (required) {
- raiseMissingCookieException(cookieName, paramType);
- }
- cookieValue = checkValue(cookieName, cookieValue, paramType);
- }
- WebDataBinder binder = createBinder(webRequest, null, cookieName);
- initBinder(handlerForInitBinderCall, cookieName, binder, webRequest);
- return binder.convertIfNecessary(cookieValue, paramType, methodParam);
- }
-
- /**
- * Resolves the given {@link CookieValue @CookieValue} annotation.
- * Throws an UnsupportedOperationException by default.
- */
- protected Object resolveCookieValue(String cookieName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- throw new UnsupportedOperationException("@CookieValue not supported");
- }
-
- private Object resolvePathVariable(String pathVarName, MethodParameter methodParam,
- NativeWebRequest webRequest, Object handlerForInitBinderCall) throws Exception {
-
- Class> paramType = methodParam.getParameterType();
- if (pathVarName.length() == 0) {
- pathVarName = getRequiredParameterName(methodParam);
- }
- String pathVarValue = resolvePathVariable(pathVarName, paramType, webRequest);
- WebDataBinder binder = createBinder(webRequest, null, pathVarName);
- initBinder(handlerForInitBinderCall, pathVarName, binder, webRequest);
- return binder.convertIfNecessary(pathVarValue, paramType, methodParam);
- }
-
- /**
- * Resolves the given {@link PathVariable @PathVariable} annotation.
- *
Throws an UnsupportedOperationException by default.
- */
- protected String resolvePathVariable(String pathVarName, Class paramType, NativeWebRequest webRequest)
- throws Exception {
-
- throw new UnsupportedOperationException("@PathVariable not supported");
- }
-
- private String getRequiredParameterName(MethodParameter methodParam) {
- String name = methodParam.getParameterName();
- if (name == null) {
- throw new IllegalStateException(
- "No parameter name specified for argument of type [" + methodParam.getParameterType().getName() +
- "], and no parameter name information found in class file either.");
- }
- return name;
- }
-
- private Object checkValue(String name, Object value, Class paramType) {
- if (value == null) {
- if (boolean.class.equals(paramType)) {
- return Boolean.FALSE;
- } else if (paramType.isPrimitive()) {
- throw new IllegalStateException("Optional " + paramType + " parameter '" + name +
- "' is not present but cannot be translated into a null value due to being declared as a " +
- "primitive type. Consider declaring it as object wrapper for the corresponding primitive type.");
- }
- }
- return value;
- }
-
- private WebDataBinder resolveModelAttribute(String attrName, MethodParameter methodParam,
- ExtendedModelMap implicitModel, NativeWebRequest webRequest, Object handler) throws Exception {
-
- // Bind request parameter onto object...
- String name = attrName;
- if ("".equals(name)) {
- name = Conventions.getVariableNameForParameter(methodParam);
- }
- Class> paramType = methodParam.getParameterType();
- Object bindObject;
- if (implicitModel.containsKey(name)) {
- bindObject = implicitModel.get(name);
- } else if (this.methodResolver.isSessionAttribute(name, paramType)) {
- bindObject = this.sessionAttributeStore.retrieveAttribute(webRequest, name);
- if (bindObject == null) {
- raiseSessionRequiredException("Session attribute '" + name + "' required - not found in session");
- }
- } else {
- bindObject = BeanUtils.instantiateClass(paramType);
- }
- WebDataBinder binder = createBinder(webRequest, bindObject, name);
- initBinder(handler, name, binder, webRequest);
- return binder;
- }
-
-
- /**
- * Determine whether the given value qualifies as a "binding candidate", i.e. might potentially be subject to
- * bean-style data binding later on.
- */
- protected boolean isBindingCandidate(Object value) {
- return (value != null && !value.getClass().isArray() && !(value instanceof Collection) &&
- !(value instanceof Map) && !BeanUtils.isSimpleValueType(value.getClass()));
- }
-
- protected void raiseMissingParameterException(String paramName, Class paramType) throws Exception {
- throw new IllegalStateException("Missing parameter '" + paramName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseMissingHeaderException(String headerName, Class paramType) throws Exception {
- throw new IllegalStateException("Missing header '" + headerName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseMissingCookieException(String cookieName, Class paramType) throws Exception {
- throw new IllegalStateException(
- "Missing cookie value '" + cookieName + "' of type [" + paramType.getName() + "]");
- }
-
- protected void raiseSessionRequiredException(String message) throws Exception {
- throw new IllegalStateException(message);
- }
-
- protected WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName)
- throws Exception {
-
- return new WebRequestDataBinder(target, objectName);
- }
-
- private void doBind(WebDataBinder binder, NativeWebRequest webRequest, boolean validate, boolean failOnErrors)
- throws Exception {
-
- doBind(binder, webRequest);
- if (validate) {
- binder.validate();
- }
- if (failOnErrors && binder.getBindingResult().hasErrors()) {
- throw new BindException(binder.getBindingResult());
- }
- }
-
- protected void doBind(WebDataBinder binder, NativeWebRequest webRequest) throws Exception {
- ((WebRequestDataBinder) binder).bind(webRequest);
- }
-
- /**
- * Return a {@link HttpInputMessage} for the given {@link NativeWebRequest}.
- *
Throws an UnsupportedOperation1Exception by default.
- */
- protected HttpInputMessage createHttpInputMessage(NativeWebRequest webRequest) throws Exception {
- throw new UnsupportedOperationException("@RequestBody not supported");
- }
-
- /**
- * Return a {@link HttpOutputMessage} for the given {@link NativeWebRequest}.
- *
Throws an UnsupportedOperationException by default.
- */
- protected HttpOutputMessage createHttpOutputMessage(NativeWebRequest webRequest) throws Exception {
- throw new UnsupportedOperationException("@ResponseBody not supported");
- }
-
- protected String parseDefaultValueAttribute(String value) {
- return (ValueConstants.DEFAULT_NONE.equals(value) ? null : value);
- }
-
- protected Object resolveDefaultValue(String value) {
- return value;
- }
-
- protected Object resolveCommonArgument(MethodParameter methodParameter, NativeWebRequest webRequest)
- throws Exception {
-
- // Invoke custom argument resolvers if present...
- if (this.customArgumentResolvers != null) {
- for (WebArgumentResolver argumentResolver : this.customArgumentResolvers) {
- Object value = argumentResolver.resolveArgument(methodParameter, webRequest);
- if (value != WebArgumentResolver.UNRESOLVED) {
- return value;
- }
- }
- }
-
- // Resolution of standard parameter types...
- Class paramType = methodParameter.getParameterType();
- Object value = resolveStandardArgument(paramType, webRequest);
- if (value != WebArgumentResolver.UNRESOLVED && !ClassUtils.isAssignableValue(paramType, value)) {
- throw new IllegalStateException("Standard argument type [" + paramType.getName() +
- "] resolved to incompatible value of type [" + (value != null ? value.getClass() : null) +
- "]. Consider declaring the argument type in a less specific fashion.");
- }
- return value;
- }
-
- protected Object resolveStandardArgument(Class> parameterType, NativeWebRequest webRequest) throws Exception {
- if (WebRequest.class.isAssignableFrom(parameterType)) {
- return webRequest;
- }
- return WebArgumentResolver.UNRESOLVED;
- }
-
- protected final void addReturnValueAsModelAttribute(Method handlerMethod, Class handlerType,
- Object returnValue, ExtendedModelMap implicitModel) {
-
- ModelAttribute attr = AnnotationUtils.findAnnotation(handlerMethod, ModelAttribute.class);
- String attrName = (attr != null ? attr.value() : "");
- if ("".equals(attrName)) {
- Class resolvedType = GenericTypeResolver.resolveReturnType(handlerMethod, handlerType);
- attrName = Conventions.getVariableNameForReturnType(handlerMethod, resolvedType, returnValue);
- }
- implicitModel.addAttribute(attrName, returnValue);
- }
-
-}