1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.ws.server;
18
19 import java.io.ByteArrayOutputStream;
20 import java.io.IOException;
21 import java.util.ArrayList;
22 import java.util.Collections;
23 import java.util.List;
24 import java.util.Map;
25
26 import org.springframework.beans.BeansException;
27 import org.springframework.beans.factory.BeanFactoryUtils;
28 import org.springframework.beans.factory.BeanNameAware;
29 import org.springframework.context.ApplicationContext;
30 import org.springframework.context.ApplicationContextAware;
31 import org.springframework.core.OrderComparator;
32 import org.springframework.util.CollectionUtils;
33 import org.springframework.util.ObjectUtils;
34 import org.springframework.web.servlet.DispatcherServlet;
35 import org.springframework.ws.FaultAwareWebServiceMessage;
36 import org.springframework.ws.NoEndpointFoundException;
37 import org.springframework.ws.WebServiceMessage;
38 import org.springframework.ws.context.MessageContext;
39 import org.springframework.ws.server.endpoint.MessageEndpoint;
40 import org.springframework.ws.server.endpoint.PayloadEndpoint;
41 import org.springframework.ws.server.endpoint.adapter.MessageEndpointAdapter;
42 import org.springframework.ws.server.endpoint.adapter.PayloadEndpointAdapter;
43 import org.springframework.ws.soap.server.SoapMessageDispatcher;
44 import org.springframework.ws.support.DefaultStrategiesHelper;
45 import org.springframework.ws.transport.WebServiceMessageReceiver;
46
47 import org.apache.commons.logging.Log;
48 import org.apache.commons.logging.LogFactory;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79 public class MessageDispatcher implements WebServiceMessageReceiver, BeanNameAware, ApplicationContextAware {
80
81
82 protected final Log logger = LogFactory.getLog(getClass());
83
84
85 public static final String ENDPOINT_NOT_FOUND_LOG_CATEGORY = "org.springframework.ws.server.EndpointNotFound";
86
87
88 protected static final Log endpointNotFoundLogger =
89 LogFactory.getLog(MessageDispatcher.ENDPOINT_NOT_FOUND_LOG_CATEGORY);
90
91
92 public static final String MESSAGE_TRACING_LOG_CATEGORY = "org.springframework.ws.server.MessageTracing";
93
94
95 protected static final Log sentMessageTracingLogger =
96 LogFactory.getLog(MessageDispatcher.MESSAGE_TRACING_LOG_CATEGORY + ".sent");
97
98
99 protected static final Log receivedMessageTracingLogger =
100 LogFactory.getLog(MessageDispatcher.MESSAGE_TRACING_LOG_CATEGORY + ".received");
101
102 private final DefaultStrategiesHelper defaultStrategiesHelper;
103
104
105 private String beanName;
106
107
108 private List<EndpointAdapter> endpointAdapters;
109
110
111 private List<EndpointExceptionResolver> endpointExceptionResolvers;
112
113
114 private List<EndpointMapping> endpointMappings;
115
116
117 public MessageDispatcher() {
118 defaultStrategiesHelper = new DefaultStrategiesHelper(getClass());
119 }
120
121
122 public List<EndpointAdapter> getEndpointAdapters() {
123 return endpointAdapters;
124 }
125
126
127 public void setEndpointAdapters(List<EndpointAdapter> endpointAdapters) {
128 this.endpointAdapters = endpointAdapters;
129 }
130
131
132 public List<EndpointExceptionResolver> getEndpointExceptionResolvers() {
133 return endpointExceptionResolvers;
134 }
135
136
137 public void setEndpointExceptionResolvers(List<EndpointExceptionResolver> endpointExceptionResolvers) {
138 this.endpointExceptionResolvers = endpointExceptionResolvers;
139 }
140
141
142 public List<EndpointMapping> getEndpointMappings() {
143 return endpointMappings;
144 }
145
146
147 public void setEndpointMappings(List<EndpointMapping> endpointMappings) {
148 this.endpointMappings = endpointMappings;
149 }
150
151 public final void setBeanName(String beanName) {
152 this.beanName = beanName;
153 }
154
155 public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
156 initEndpointAdapters(applicationContext);
157 initEndpointExceptionResolvers(applicationContext);
158 initEndpointMappings(applicationContext);
159 }
160
161 public void receive(MessageContext messageContext) throws Exception {
162
163 String requestContent = "";
164 if (receivedMessageTracingLogger.isTraceEnabled() || sentMessageTracingLogger.isTraceEnabled()) {
165 requestContent = getMessageContent(messageContext.getRequest());
166 }
167 if (receivedMessageTracingLogger.isTraceEnabled()) {
168 receivedMessageTracingLogger.trace("Received request [" + requestContent + "]");
169 }
170 else if (receivedMessageTracingLogger.isDebugEnabled()) {
171 receivedMessageTracingLogger.debug("Received request [" + messageContext.getRequest() + "]");
172 }
173 dispatch(messageContext);
174 if (messageContext.hasResponse()) {
175 WebServiceMessage response = messageContext.getResponse();
176 if (sentMessageTracingLogger.isTraceEnabled()) {
177 String responseContent = getMessageContent(response);
178 sentMessageTracingLogger.trace("Sent response [" + responseContent + "] for request [" +
179 requestContent + "]");
180 }
181 else if (sentMessageTracingLogger.isDebugEnabled()) {
182 sentMessageTracingLogger.debug("Sent response [" + response + "] for request [" +
183 messageContext.getRequest() + "]");
184 }
185 }
186 else if (sentMessageTracingLogger.isDebugEnabled()) {
187 sentMessageTracingLogger
188 .debug("MessageDispatcher with name '" + beanName + "' sends no response for request [" +
189 messageContext.getRequest() + "]");
190 }
191 }
192
193 private String getMessageContent(WebServiceMessage message) throws IOException {
194 ByteArrayOutputStream bos = new ByteArrayOutputStream();
195 message.writeTo(bos);
196 return bos.toString("UTF-8");
197 }
198
199
200
201
202
203
204
205
206 protected final void dispatch(MessageContext messageContext) throws Exception {
207 EndpointInvocationChain mappedEndpoint = null;
208 int interceptorIndex = -1;
209 try {
210 try {
211
212 mappedEndpoint = getEndpoint(messageContext);
213 if (mappedEndpoint == null || mappedEndpoint.getEndpoint() == null) {
214 throw new NoEndpointFoundException(messageContext.getRequest());
215 }
216 if (!handleRequest(mappedEndpoint, messageContext)) {
217 return;
218 }
219
220 if (mappedEndpoint.getInterceptors() != null) {
221 for (int i = 0; i < mappedEndpoint.getInterceptors().length; i++) {
222 EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
223 interceptorIndex = i;
224 if (!interceptor.handleRequest(messageContext, mappedEndpoint.getEndpoint())) {
225 triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
226 triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null);
227 return;
228 }
229 }
230 }
231
232 EndpointAdapter endpointAdapter = getEndpointAdapter(mappedEndpoint.getEndpoint());
233 endpointAdapter.invoke(messageContext, mappedEndpoint.getEndpoint());
234
235
236 triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
237 }
238 catch (NoEndpointFoundException ex) {
239
240 if (endpointNotFoundLogger.isWarnEnabled()) {
241 endpointNotFoundLogger.warn("No endpoint mapping found for [" + messageContext.getRequest() + "]");
242 }
243 throw ex;
244 }
245 catch (Exception ex) {
246 Object endpoint = mappedEndpoint != null ? mappedEndpoint.getEndpoint() : null;
247 processEndpointException(messageContext, endpoint, ex);
248 triggerHandleResponse(mappedEndpoint, interceptorIndex, messageContext);
249 }
250 triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, null);
251 }
252 catch (NoEndpointFoundException ex) {
253 throw ex;
254 }
255 catch (Exception ex) {
256
257 triggerAfterCompletion(mappedEndpoint, interceptorIndex, messageContext, ex);
258 throw ex;
259 }
260 }
261
262
263
264
265
266
267 protected EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
268 for (EndpointMapping endpointMapping : getEndpointMappings()) {
269 EndpointInvocationChain endpoint = endpointMapping.getEndpoint(messageContext);
270 if (endpoint != null) {
271 if (logger.isDebugEnabled()) {
272 logger.debug("Endpoint mapping [" + endpointMapping + "] maps request to endpoint [" +
273 endpoint.getEndpoint() + "]");
274 }
275 return endpoint;
276 }
277 else if (logger.isDebugEnabled()) {
278 logger.debug("Endpoint mapping [" + endpointMapping + "] has no mapping for request");
279 }
280 }
281 return null;
282 }
283
284
285
286
287
288
289
290 protected EndpointAdapter getEndpointAdapter(Object endpoint) {
291 for (EndpointAdapter endpointAdapter : getEndpointAdapters()) {
292 if (logger.isDebugEnabled()) {
293 logger.debug("Testing endpoint adapter [" + endpointAdapter + "]");
294 }
295 if (endpointAdapter.supports(endpoint)) {
296 return endpointAdapter;
297 }
298 }
299 throw new IllegalStateException("No adapter for endpoint [" + endpoint + "]: Is your endpoint annotated with " +
300 "@Endpoint, or does it implement a supported interface like MessageHandler or PayloadEndpoint?");
301 }
302
303
304
305
306
307
308
309
310
311
312
313 protected boolean handleRequest(EndpointInvocationChain mappedEndpoint, MessageContext messageContext) {
314 return true;
315 }
316
317
318
319
320
321
322
323
324
325
326
327 protected void processEndpointException(MessageContext messageContext, Object endpoint, Exception ex)
328 throws Exception {
329 if (!CollectionUtils.isEmpty(getEndpointExceptionResolvers())) {
330 for (EndpointExceptionResolver resolver : getEndpointExceptionResolvers()) {
331 if (resolver.resolveException(messageContext, endpoint, ex)) {
332 if (logger.isDebugEnabled()) {
333 logger.debug("Endpoint invocation resulted in exception - responding with Fault", ex);
334 }
335 return;
336 }
337 }
338 }
339
340 throw ex;
341 }
342
343
344
345
346
347
348
349
350
351
352
353
354 private void triggerHandleResponse(EndpointInvocationChain mappedEndpoint,
355 int interceptorIndex,
356 MessageContext messageContext) throws Exception {
357 if (mappedEndpoint != null && messageContext.hasResponse() &&
358 !ObjectUtils.isEmpty(mappedEndpoint.getInterceptors())) {
359 boolean hasFault = false;
360 WebServiceMessage response = messageContext.getResponse();
361 if (response instanceof FaultAwareWebServiceMessage) {
362 hasFault = ((FaultAwareWebServiceMessage) response).hasFault();
363 }
364 boolean resume = true;
365 for (int i = interceptorIndex; resume && i >= 0; i--) {
366 EndpointInterceptor interceptor = mappedEndpoint.getInterceptors()[i];
367 if (!hasFault) {
368 resume = interceptor.handleResponse(messageContext, mappedEndpoint.getEndpoint());
369 }
370 else {
371 resume = interceptor.handleFault(messageContext, mappedEndpoint.getEndpoint());
372 }
373 }
374 }
375 }
376
377
378
379
380
381
382
383
384
385
386
387
388 private void triggerAfterCompletion(EndpointInvocationChain mappedEndpoint,
389 int interceptorIndex,
390 MessageContext messageContext,
391 Exception ex) throws Exception {
392
393
394 if (mappedEndpoint != null) {
395 EndpointInterceptor[] interceptors = mappedEndpoint.getInterceptors();
396 if (interceptors != null) {
397 for (int i = interceptorIndex; i >= 0; i--) {
398 EndpointInterceptor interceptor = interceptors[i];
399 try {
400 interceptor.afterCompletion(messageContext, mappedEndpoint.getEndpoint(), ex);
401 }
402 catch (Throwable ex2) {
403 logger.error("EndpointInterceptor.afterCompletion threw exception", ex2);
404 }
405 }
406 }
407 }
408 }
409
410
411
412
413
414
415
416
417 private void initEndpointAdapters(ApplicationContext applicationContext) throws BeansException {
418 if (endpointAdapters == null) {
419 Map<String, EndpointAdapter> matchingBeans = BeanFactoryUtils
420 .beansOfTypeIncludingAncestors(applicationContext, EndpointAdapter.class, true, false);
421 if (!matchingBeans.isEmpty()) {
422 endpointAdapters = new ArrayList<EndpointAdapter>(matchingBeans.values());
423 Collections.sort(endpointAdapters, new OrderComparator());
424 }
425 else {
426 endpointAdapters =
427 defaultStrategiesHelper.getDefaultStrategies(EndpointAdapter.class, applicationContext);
428 if (logger.isDebugEnabled()) {
429 logger.debug("No EndpointAdapters found, using defaults");
430 }
431 }
432 }
433 }
434
435
436
437
438
439
440
441 private void initEndpointExceptionResolvers(ApplicationContext applicationContext) throws BeansException {
442 if (endpointExceptionResolvers == null) {
443 Map<String, EndpointExceptionResolver> matchingBeans = BeanFactoryUtils
444 .beansOfTypeIncludingAncestors(applicationContext, EndpointExceptionResolver.class, true, false);
445 if (!matchingBeans.isEmpty()) {
446 endpointExceptionResolvers = new ArrayList<EndpointExceptionResolver>(matchingBeans.values());
447 Collections.sort(endpointExceptionResolvers, new OrderComparator());
448 }
449 else {
450 endpointExceptionResolvers = defaultStrategiesHelper
451 .getDefaultStrategies(EndpointExceptionResolver.class, applicationContext);
452 if (logger.isDebugEnabled()) {
453 logger.debug("No EndpointExceptionResolvers found, using defaults");
454 }
455 }
456 }
457 }
458
459
460
461
462
463
464
465 private void initEndpointMappings(ApplicationContext applicationContext) throws BeansException {
466 if (endpointMappings == null) {
467 Map<String, EndpointMapping> matchingBeans = BeanFactoryUtils
468 .beansOfTypeIncludingAncestors(applicationContext, EndpointMapping.class, true, false);
469 if (!matchingBeans.isEmpty()) {
470 endpointMappings = new ArrayList<EndpointMapping>(matchingBeans.values());
471 Collections.sort(endpointMappings, new OrderComparator());
472 }
473 else {
474 endpointMappings =
475 defaultStrategiesHelper.getDefaultStrategies(EndpointMapping.class, applicationContext);
476 if (logger.isDebugEnabled()) {
477 logger.debug("No EndpointMappings found, using defaults");
478 }
479 }
480 }
481 }
482 }