View Javadoc
1   /*
2    * Copyright 2002-2014 the original author or authors.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  
17  package org.springframework.web.servlet.mvc.method.annotation;
18  
19  import java.io.OutputStream;
20  import java.io.Writer;
21  import java.lang.reflect.Method;
22  import javax.servlet.ServletResponse;
23  import javax.servlet.http.HttpServletResponse;
24  
25  import org.springframework.core.MethodParameter;
26  import org.springframework.web.bind.support.WebDataBinderFactory;
27  import org.springframework.web.context.request.NativeWebRequest;
28  import org.springframework.web.method.support.HandlerMethodArgumentResolver;
29  import org.springframework.web.method.support.ModelAndViewContainer;
30  
31  /**
32   * Resolves response-related method argument values of types:
33   * <ul>
34   * <li>{@link ServletResponse}
35   * <li>{@link OutputStream}
36   * <li>{@link Writer}
37   * </ul>
38   *
39   * @author Arjen Poutsma
40   * @author Rossen Stoyanchev
41   * @since 3.1
42   */
43  public class ServletResponseMethodArgumentResolver implements HandlerMethodArgumentResolver {
44  
45  	@Override
46  	public boolean supportsParameter(MethodParameter parameter) {
47  		Class<?> paramType = parameter.getParameterType();
48  		return (ServletResponse.class.isAssignableFrom(paramType) ||
49  				OutputStream.class.isAssignableFrom(paramType) ||
50  				Writer.class.isAssignableFrom(paramType));
51  	}
52  
53  	/**
54  	 * Set {@link ModelAndViewContainer#setRequestHandled(boolean)} to
55  	 * {@code false} to indicate that the method signature provides access
56  	 * to the response. If subsequently the underlying method returns
57  	 * {@code null}, the request is considered directly handled.
58  	 */
59  	@Override
60  	public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
61  			NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
62  
63  		if (mavContainer != null) {
64  			mavContainer.setRequestHandled(true);
65  		}
66  
67  		HttpServletResponse response = webRequest.getNativeResponse(HttpServletResponse.class);
68  		Class<?> paramType = parameter.getParameterType();
69  
70  		if (ServletResponse.class.isAssignableFrom(paramType)) {
71  			Object nativeResponse = webRequest.getNativeResponse(paramType);
72  			if (nativeResponse == null) {
73  				throw new IllegalStateException(
74  						"Current response is not of type [" + paramType.getName() + "]: " + response);
75  			}
76  			return nativeResponse;
77  		}
78  		else if (OutputStream.class.isAssignableFrom(paramType)) {
79  			return response.getOutputStream();
80  		}
81  		else if (Writer.class.isAssignableFrom(paramType)) {
82  			return response.getWriter();
83  		}
84  		else {
85  			// should not happen
86  			Method method = parameter.getMethod();
87  			throw new UnsupportedOperationException("Unknown parameter type: " + paramType + " in method: " + method);
88  		}
89  	}
90  
91  }