1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.web.servlet.mvc.method.annotation;
18
19 import java.io.IOException;
20 import java.lang.reflect.ParameterizedType;
21 import java.lang.reflect.Type;
22 import java.util.List;
23
24 import org.springframework.core.MethodParameter;
25 import org.springframework.core.ResolvableType;
26 import org.springframework.http.HttpEntity;
27 import org.springframework.http.HttpHeaders;
28 import org.springframework.http.RequestEntity;
29 import org.springframework.http.ResponseEntity;
30 import org.springframework.http.converter.HttpMessageConverter;
31 import org.springframework.http.server.ServletServerHttpRequest;
32 import org.springframework.http.server.ServletServerHttpResponse;
33 import org.springframework.util.Assert;
34 import org.springframework.web.HttpMediaTypeNotSupportedException;
35 import org.springframework.web.accept.ContentNegotiationManager;
36 import org.springframework.web.bind.support.WebDataBinderFactory;
37 import org.springframework.web.context.request.NativeWebRequest;
38 import org.springframework.web.method.support.ModelAndViewContainer;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 public class HttpEntityMethodProcessor extends AbstractMessageConverterMethodProcessor {
54
55 public HttpEntityMethodProcessor(List<HttpMessageConverter<?>> messageConverters) {
56 super(messageConverters);
57 }
58
59 public HttpEntityMethodProcessor(List<HttpMessageConverter<?>> messageConverters,
60 ContentNegotiationManager contentNegotiationManager) {
61
62 super(messageConverters, contentNegotiationManager);
63 }
64
65 public HttpEntityMethodProcessor(List<HttpMessageConverter<?>> messageConverters,
66 ContentNegotiationManager contentNegotiationManager, List<Object> responseBodyAdvice) {
67
68 super(messageConverters, contentNegotiationManager, responseBodyAdvice);
69 }
70
71
72 @Override
73 public boolean supportsParameter(MethodParameter parameter) {
74 return (HttpEntity.class.equals(parameter.getParameterType()) ||
75 RequestEntity.class.equals(parameter.getParameterType()));
76 }
77
78 @Override
79 public boolean supportsReturnType(MethodParameter returnType) {
80 return (HttpEntity.class.isAssignableFrom(returnType.getParameterType()) &&
81 !RequestEntity.class.isAssignableFrom(returnType.getParameterType()));
82 }
83
84 @Override
85 public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer,
86 NativeWebRequest webRequest, WebDataBinderFactory binderFactory)
87 throws IOException, HttpMediaTypeNotSupportedException {
88
89 ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
90 Type paramType = getHttpEntityType(parameter);
91
92 Object body = readWithMessageConverters(webRequest, parameter, paramType);
93 if (RequestEntity.class.equals(parameter.getParameterType())) {
94 return new RequestEntity<Object>(body, inputMessage.getHeaders(),
95 inputMessage.getMethod(), inputMessage.getURI());
96 }
97 else {
98 return new HttpEntity<Object>(body, inputMessage.getHeaders());
99 }
100 }
101
102 private Type getHttpEntityType(MethodParameter parameter) {
103 Assert.isAssignable(HttpEntity.class, parameter.getParameterType());
104 Type parameterType = parameter.getGenericParameterType();
105 if (parameterType instanceof ParameterizedType) {
106 ParameterizedType type = (ParameterizedType) parameterType;
107 if (type.getActualTypeArguments().length != 1) {
108 throw new IllegalArgumentException("Expected single generic parameter on '" +
109 parameter.getParameterName() + "' in method " + parameter.getMethod());
110 }
111 return type.getActualTypeArguments()[0];
112 }
113 else if (parameterType instanceof Class) {
114 return Object.class;
115 }
116 throw new IllegalArgumentException("HttpEntity parameter '" + parameter.getParameterName() +
117 "' in method " + parameter.getMethod() + " is not parameterized");
118 }
119
120 @Override
121 public void handleReturnValue(Object returnValue, MethodParameter returnType,
122 ModelAndViewContainer mavContainer, NativeWebRequest webRequest) throws Exception {
123
124 mavContainer.setRequestHandled(true);
125 if (returnValue == null) {
126 return;
127 }
128
129 ServletServerHttpRequest inputMessage = createInputMessage(webRequest);
130 ServletServerHttpResponse outputMessage = createOutputMessage(webRequest);
131
132 Assert.isInstanceOf(HttpEntity.class, returnValue);
133 HttpEntity<?> responseEntity = (HttpEntity<?>) returnValue;
134 if (responseEntity instanceof ResponseEntity) {
135 outputMessage.setStatusCode(((ResponseEntity<?>) responseEntity).getStatusCode());
136 }
137
138 HttpHeaders entityHeaders = responseEntity.getHeaders();
139 if (!entityHeaders.isEmpty()) {
140 outputMessage.getHeaders().putAll(entityHeaders);
141 }
142
143 Object body = responseEntity.getBody();
144
145
146 writeWithMessageConverters(body, returnType, inputMessage, outputMessage);
147
148
149 outputMessage.getBody();
150 }
151
152 @Override
153 protected Class<?> getReturnValueType(Object returnValue, MethodParameter returnType) {
154 if (returnValue != null) {
155 return returnValue.getClass();
156 }
157 else {
158 Type type = getHttpEntityType(returnType);
159 return ResolvableType.forMethodParameter(returnType, type).resolve(Object.class);
160 }
161 }
162
163 }