1   /*
2    * Copyright 2005-2012 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.ws.server;
18  
19  import java.util.Collections;
20  
21  import org.springframework.context.support.StaticApplicationContext;
22  import org.springframework.ws.MockWebServiceMessage;
23  import org.springframework.ws.NoEndpointFoundException;
24  import org.springframework.ws.WebServiceMessageFactory;
25  import org.springframework.ws.context.DefaultMessageContext;
26  import org.springframework.ws.context.MessageContext;
27  import org.springframework.ws.server.endpoint.adapter.PayloadEndpointAdapter;
28  import org.springframework.ws.server.endpoint.mapping.PayloadRootQNameEndpointMapping;
29  import org.springframework.ws.soap.server.endpoint.SimpleSoapExceptionResolver;
30  
31  import org.junit.Assert;
32  import org.junit.Before;
33  import org.junit.Test;
34  
35  import static org.easymock.EasyMock.*;
36  
37  public class MessageDispatcherTest {
38  
39      private MessageDispatcher dispatcher;
40  
41      private MessageContext messageContext;
42  
43      private WebServiceMessageFactory factoryMock;
44  
45      @Before
46      public void setUp() throws Exception {
47          dispatcher = new MessageDispatcher();
48          factoryMock = createMock(WebServiceMessageFactory.class);
49          messageContext = new DefaultMessageContext(new MockWebServiceMessage(), factoryMock);
50      }
51  
52      @Test
53      public void testGetEndpoint() throws Exception {
54          EndpointMapping mappingMock = createMock(EndpointMapping.class);
55          dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
56  
57          EndpointInvocationChain chain = new EndpointInvocationChain(new Object());
58  
59          expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
60  
61          replay(mappingMock, factoryMock);
62  
63          EndpointInvocationChain result = dispatcher.getEndpoint(messageContext);
64  
65          verify(mappingMock, factoryMock);
66  
67          Assert.assertEquals("getEndpoint returns invalid EndpointInvocationChain", chain, result);
68      }
69  
70      @Test
71      public void testGetEndpointAdapterSupportedEndpoint() throws Exception {
72          EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
73          dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
74  
75          Object endpoint = new Object();
76          expect(adapterMock.supports(endpoint)).andReturn(true);
77  
78          replay(adapterMock, factoryMock);
79  
80          EndpointAdapter result = dispatcher.getEndpointAdapter(endpoint);
81  
82          verify(adapterMock, factoryMock);
83  
84          Assert.assertEquals("getEndpointAdapter returns invalid EndpointAdapter", adapterMock, result);
85      }
86  
87      @Test
88      public void testGetEndpointAdapterUnsupportedEndpoint() throws Exception {
89          EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
90          dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
91  
92          Object endpoint = new Object();
93          expect(adapterMock.supports(endpoint)).andReturn(false);
94  
95          replay(adapterMock, factoryMock);
96  
97          try {
98              dispatcher.getEndpointAdapter(endpoint);
99              Assert.fail("getEndpointAdapter does not throw IllegalStateException for unsupported endpoint");
100         }
101         catch (IllegalStateException ex) {
102             // Expected
103         }
104 
105         verify(adapterMock, factoryMock);
106     }
107 
108     @Test
109     public void testResolveException() throws Exception {
110         final Exception ex = new Exception();
111         EndpointMapping endpointMapping = new EndpointMapping() {
112 
113             public EndpointInvocationChain getEndpoint(MessageContext messageContext) throws Exception {
114                 throw ex;
115             }
116         };
117         dispatcher.setEndpointMappings(Collections.singletonList(endpointMapping));
118         EndpointExceptionResolver resolver = new EndpointExceptionResolver() {
119 
120             public boolean resolveException(MessageContext givenMessageContext,
121                                             Object givenEndpoint,
122                                             Exception givenException) {
123                 Assert.assertEquals("Invalid message context", messageContext, givenMessageContext);
124                 Assert.assertNull("Invalid endpoint", givenEndpoint);
125                 Assert.assertEquals("Invalid exception", ex, givenException);
126                 givenMessageContext.getResponse();
127                 return true;
128             }
129 
130         };
131         dispatcher.setEndpointExceptionResolvers(Collections.singletonList(resolver));
132         expect(factoryMock.createWebServiceMessage()).andReturn(new MockWebServiceMessage());
133 
134         replay(factoryMock);
135 
136         dispatcher.dispatch(messageContext);
137         Assert.assertNotNull("processEndpointException sets no response", messageContext.getResponse());
138 
139         verify(factoryMock);
140     }
141 
142     @Test
143     public void testProcessUnsupportedEndpointException() throws Exception {
144         EndpointExceptionResolver resolverMock = createMock(EndpointExceptionResolver.class);
145         dispatcher.setEndpointExceptionResolvers(Collections.singletonList(resolverMock));
146 
147         Object endpoint = new Object();
148         Exception ex = new Exception();
149 
150         expect(resolverMock.resolveException(messageContext, endpoint, ex)).andReturn(false);
151 
152         replay(factoryMock, resolverMock);
153 
154         try {
155             dispatcher.processEndpointException(messageContext, endpoint, ex);
156         }
157         catch (Exception result) {
158             Assert.assertEquals("processEndpointException throws invalid exception", ex, result);
159         }
160         verify(factoryMock, resolverMock);
161     }
162 
163     @Test
164     public void testNormalFlow() throws Exception {
165         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
166         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
167 
168         Object endpoint = new Object();
169         expect(adapterMock.supports(endpoint)).andReturn(true);
170 
171         EndpointMapping mappingMock = createMock(EndpointMapping.class);
172         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
173 
174         EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
175         EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
176 
177         expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
178         expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true);
179 
180         adapterMock.invoke(messageContext, endpoint);
181 
182         expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(true);
183         expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true);
184 
185         interceptorMock2.afterCompletion(messageContext, endpoint, null);
186         interceptorMock1.afterCompletion(messageContext, endpoint, null);
187 
188         EndpointInvocationChain chain =
189                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
190 
191         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
192         expect(factoryMock.createWebServiceMessage()).andReturn(new MockWebServiceMessage());
193 
194         replay(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
195 
196         //  response required for interceptor invocation
197         messageContext.getResponse();
198         dispatcher.dispatch(messageContext);
199 
200         verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
201     }
202 
203     @Test
204     public void testFlowNoResponse() throws Exception {
205         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
206         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
207 
208         Object endpoint = new Object();
209         expect(adapterMock.supports(endpoint)).andReturn(true);
210 
211         EndpointMapping mappingMock = createMock(EndpointMapping.class);
212         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
213 
214         EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
215         EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
216 
217         EndpointInvocationChain chain =
218                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
219         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
220 
221         expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
222         expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(true);
223         interceptorMock2.afterCompletion(messageContext, endpoint, null);
224         interceptorMock1.afterCompletion(messageContext, endpoint, null);
225 
226         adapterMock.invoke(messageContext, endpoint);
227 
228         replay(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
229 
230         dispatcher.dispatch(messageContext);
231 
232         verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
233     }
234 
235     @Test
236     public void testInterceptedRequestFlow() throws Exception {
237         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
238         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
239 
240         EndpointMapping mappingMock = createMock(EndpointMapping.class);
241         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
242 
243         EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
244         EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
245 
246         Object endpoint = new Object();
247 
248         expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(false);
249         expect(interceptorMock1.handleResponse(messageContext, endpoint)).andReturn(true);
250         interceptorMock1.afterCompletion(messageContext, endpoint, null);
251 
252         EndpointInvocationChain chain =
253                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
254 
255         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
256         expect(factoryMock.createWebServiceMessage()).andReturn(new MockWebServiceMessage());
257 
258         replay(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
259 
260         //  response required for interceptor invocation
261         messageContext.getResponse();
262 
263         dispatcher.dispatch(messageContext);
264 
265         verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
266     }
267 
268     @Test
269     public void testInterceptedResponseFlow() throws Exception {
270         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
271         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
272 
273         EndpointMapping mappingMock = createMock(EndpointMapping.class);
274         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
275 
276         EndpointInterceptor interceptorMock1 = createStrictMock("interceptor1", EndpointInterceptor.class);
277         EndpointInterceptor interceptorMock2 = createStrictMock("interceptor2", EndpointInterceptor.class);
278 
279         Object endpoint = new Object();
280         expect(interceptorMock1.handleRequest(messageContext, endpoint)).andReturn(true);
281         expect(interceptorMock2.handleRequest(messageContext, endpoint)).andReturn(false);
282         expect(interceptorMock2.handleResponse(messageContext, endpoint)).andReturn(false);
283         interceptorMock1.afterCompletion(messageContext, endpoint, null);
284         interceptorMock2.afterCompletion(messageContext, endpoint, null);
285 
286         EndpointInvocationChain chain =
287                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock1, interceptorMock2});
288 
289         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
290         expect(factoryMock.createWebServiceMessage()).andReturn(new MockWebServiceMessage());
291 
292         replay(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
293 
294         //  response required for interceptor invocation
295         messageContext.getResponse();
296 
297         dispatcher.dispatch(messageContext);
298 
299         verify(mappingMock, interceptorMock1, interceptorMock2, adapterMock, factoryMock);
300     }
301 
302     @Test
303     public void testResolveExceptionsWithInterceptors() throws Exception {
304         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
305         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
306 
307         Object endpoint = new Object();
308         expect(adapterMock.supports(endpoint)).andReturn(true);
309 
310         EndpointMapping mappingMock = createMock(EndpointMapping.class);
311         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
312 
313         EndpointExceptionResolver resolverMock = createMock(EndpointExceptionResolver.class);
314         dispatcher.setEndpointExceptionResolvers(Collections.singletonList(resolverMock));
315 
316         EndpointInterceptor interceptorMock = createStrictMock("interceptor1", EndpointInterceptor.class);
317 
318         expect(interceptorMock.handleRequest(messageContext, endpoint)).andReturn(true);
319 
320         adapterMock.invoke(messageContext, endpoint);
321         RuntimeException exception = new RuntimeException();
322         expectLastCall().andThrow(exception);
323 
324         expect(resolverMock.resolveException(messageContext, endpoint, exception)).andReturn(true);
325 
326         expect(interceptorMock.handleResponse(messageContext, endpoint)).andReturn(true);
327 
328         interceptorMock.afterCompletion(messageContext, endpoint, null);
329 
330         EndpointInvocationChain chain =
331                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock});
332 
333         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
334         expect(factoryMock.createWebServiceMessage()).andReturn(new MockWebServiceMessage());
335 
336         replay(mappingMock, interceptorMock, adapterMock, factoryMock, resolverMock);
337 
338         //  response required for interceptor invocation
339         messageContext.getResponse();
340         try {
341         dispatcher.dispatch(messageContext);
342         } catch (RuntimeException ex) {
343 
344         }
345 
346         verify(mappingMock, interceptorMock, adapterMock, factoryMock, resolverMock);
347     }
348 
349     @Test
350     public void testFaultFlow() throws Exception {
351         EndpointAdapter adapterMock = createMock(EndpointAdapter.class);
352         dispatcher.setEndpointAdapters(Collections.singletonList(adapterMock));
353 
354         Object endpoint = new Object();
355         expect(adapterMock.supports(endpoint)).andReturn(true);
356 
357         EndpointMapping mappingMock = createMock(EndpointMapping.class);
358         dispatcher.setEndpointMappings(Collections.singletonList(mappingMock));
359 
360         EndpointInterceptor interceptorMock = createStrictMock(EndpointInterceptor.class);
361 
362         expect(interceptorMock.handleRequest(messageContext, endpoint)).andReturn(true);
363         adapterMock.invoke(messageContext, endpoint);
364         expect(interceptorMock.handleFault(messageContext, endpoint)).andReturn(true);
365         interceptorMock.afterCompletion(messageContext, endpoint, null);
366 
367         EndpointInvocationChain chain =
368                 new EndpointInvocationChain(endpoint, new EndpointInterceptor[]{interceptorMock});
369 
370         expect(mappingMock.getEndpoint(messageContext)).andReturn(chain);
371         MockWebServiceMessage response = new MockWebServiceMessage();
372         response.setFault(true);
373         expect(factoryMock.createWebServiceMessage()).andReturn(response);
374 
375         replay(mappingMock, interceptorMock, adapterMock, factoryMock);
376 
377         //  response required for interceptor invocation
378         messageContext.getResponse();
379         dispatcher.dispatch(messageContext);
380 
381         verify(mappingMock, interceptorMock, adapterMock, factoryMock);
382     }
383 
384     @Test
385     public void testNoEndpointFound() throws Exception {
386         dispatcher.setEndpointMappings(Collections.<EndpointMapping>emptyList());
387         try {
388             dispatcher.receive(messageContext);
389             Assert.fail("NoEndpointFoundException expected");
390         }
391         catch (NoEndpointFoundException ex) {
392             // expected
393         }
394     }
395 
396     @Test
397     public void testDetectStrategies() throws Exception {
398         StaticApplicationContext applicationContext = new StaticApplicationContext();
399         applicationContext.registerSingleton("mapping", PayloadRootQNameEndpointMapping.class);
400         applicationContext.registerSingleton("adapter", PayloadEndpointAdapter.class);
401         applicationContext.registerSingleton("resolver", SimpleSoapExceptionResolver.class);
402         dispatcher.setApplicationContext(applicationContext);
403         Assert.assertEquals("Invalid amount of mappings detected", 1, dispatcher.getEndpointMappings().size());
404         Assert.assertTrue("Invalid mappings detected",
405                 dispatcher.getEndpointMappings().get(0) instanceof PayloadRootQNameEndpointMapping);
406         Assert.assertEquals("Invalid amount of adapters detected", 1, dispatcher.getEndpointAdapters().size());
407         Assert.assertTrue("Invalid mappings detected",
408                 dispatcher.getEndpointAdapters().get(0) instanceof PayloadEndpointAdapter);
409         Assert.assertEquals("Invalid amount of resolvers detected", 1,
410                 dispatcher.getEndpointExceptionResolvers().size());
411         Assert.assertTrue("Invalid mappings detected",
412                 dispatcher.getEndpointExceptionResolvers().get(0) instanceof SimpleSoapExceptionResolver);
413     }
414 
415     @Test
416     public void testDefaultStrategies() throws Exception {
417         StaticApplicationContext applicationContext = new StaticApplicationContext();
418         dispatcher.setApplicationContext(applicationContext);
419     }
420 
421 }