View Javadoc

1   /*
2    * $Id: DynamicOutboundEndpointTestCase.java 23030 2011-09-26 18:02:33Z mike.schilling $
3    * -------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.endpoint.outbound;
12  
13  import org.mule.MessageExchangePattern;
14  import org.mule.api.MuleEvent;
15  import org.mule.api.MuleException;
16  import org.mule.api.MuleMessage;
17  import org.mule.api.config.MuleProperties;
18  import org.mule.api.endpoint.OutboundEndpoint;
19  import org.mule.api.registry.ServiceException;
20  import org.mule.api.registry.ServiceType;
21  import org.mule.api.routing.filter.Filter;
22  import org.mule.api.security.SecurityFilter;
23  import org.mule.api.transaction.TransactionConfig;
24  import org.mule.api.transformer.Transformer;
25  import org.mule.api.transport.MessageDispatcher;
26  import org.mule.context.notification.EndpointMessageNotification;
27  import org.mule.context.notification.SecurityNotification;
28  import org.mule.endpoint.AbstractMessageProcessorTestCase;
29  import org.mule.endpoint.DynamicOutboundEndpoint;
30  import org.mule.tck.probe.PollingProber;
31  import org.mule.tck.probe.Probe;
32  import org.mule.tck.probe.Prober;
33  import org.mule.tck.security.TestSecurityFilter;
34  import org.mule.tck.testmodels.mule.TestMessageDispatcher;
35  import org.mule.tck.testmodels.mule.TestMessageDispatcherFactory;
36  import org.mule.transformer.simple.OutboundAppendTransformer;
37  import org.mule.transformer.simple.ResponseAppendTransformer;
38  import org.mule.transport.service.DefaultTransportServiceDescriptor;
39  
40  import java.util.Properties;
41  import java.util.concurrent.TimeUnit;
42  
43  import org.junit.Before;
44  import org.junit.Test;
45  
46  import static org.junit.Assert.assertEquals;
47  import static org.junit.Assert.assertNotNull;
48  import static org.junit.Assert.assertNotSame;
49  import static org.junit.Assert.assertNull;
50  import static org.junit.Assert.assertTrue;
51  import static org.junit.Assert.fail;
52  
53  /**
54   * Tests flow of messages from {@link org.mule.endpoint.DynamicOutboundEndpoint#process(org.mule.api.MuleEvent)} down to
55   * {@link org.mule.transport.AbstractMessageDispatcher} and the chain of MessageProcessor's that
56   * implement the outbound endpoint processing.
57   */
58  public class DynamicOutboundEndpointTestCase extends AbstractMessageProcessorTestCase
59  {
60  
61      private MuleEvent testOutboundEvent;
62  
63      @Before
64      public void setCurrentTestInstance() throws ServiceException
65      {
66          overrideDispatcherInServiceDescriptor();
67          MyMessageDispatcherFactory.dispatcher = null;
68      }
69  
70      @Test
71      public void testDefaultFlowRequestResponse() throws Exception
72      {
73          OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
74          testOutboundEvent = createTestOutboundEvent();
75  
76          MuleEvent result = endpoint.process(testOutboundEvent);
77  
78          assertEventSent();
79  
80          // Response message is not the same because we rewrite the response event and
81          // this change the properties
82          // (See: OutboundRewriteResponseEventMessageProcessor)
83          assertNotSame(responseMessage, result.getMessage());
84  
85          // Everything else about the message apart from addition of encoding property
86          // is the same though
87          assertMessageEqualEncodingPropertyAdded(responseMessage, result.getMessage());
88      }
89  
90      @Test
91      public void testDefaultFlowOneWay() throws Exception
92      {
93          OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.ONE_WAY, null);
94          assertTrue(endpoint instanceof DynamicOutboundEndpoint);
95  
96          testOutboundEvent = createTestOutboundEvent();
97  
98          MuleEvent result = endpoint.process(testOutboundEvent);
99  
100         assertEventDispatched();
101         assertNull(result);
102         assertMessageSentEqual(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent);
103     }
104 
105     @Test
106     public void testSecurityFilterAccept() throws Exception
107     {
108         OutboundEndpoint endpoint = createOutboundEndpoint(null, new TestSecurityFilter(true), null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
109         testOutboundEvent = createTestOutboundEvent();
110 
111         MuleEvent result = endpoint.process(testOutboundEvent);
112 
113         assertEventSent();
114         assertMessageSentEqual(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
115 
116         // Response message is not the same because we rewrite the response event and
117         // this change the properties
118         // (See: OutboundRewriteResponseEventMessageProcessor)
119         assertNotSame(responseMessage, result.getMessage());
120 
121         // Everything else about the message apart from addition of encoding property
122         // is the same though
123         assertMessageEqualEncodingPropertyAdded(responseMessage, result.getMessage());
124     }
125 
126     @Test
127     public void testSecurityFilterNotAccept() throws Exception
128     {
129         TestSecurityNotificationListener securityNotificationListener = new TestSecurityNotificationListener();
130         muleContext.registerListener(securityNotificationListener);
131 
132         OutboundEndpoint endpoint = createOutboundEndpoint(null, new TestSecurityFilter(false), null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
133         testOutboundEvent = createTestOutboundEvent();
134 
135         try
136         {
137             endpoint.process(testOutboundEvent);
138             fail("Exception expected");
139         }
140         catch (TestSecurityFilter.StaticMessageUnauthorisedException e)
141         {
142             testOutboundEvent.getFlowConstruct().getExceptionListener().handleException(e, testOutboundEvent);
143         }
144 
145         assertNull(MyMessageDispatcherFactory.dispatcher);
146 
147         assertTrue(securityNotificationListener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
148         assertEquals(SecurityNotification.SECURITY_AUTHENTICATION_FAILED,
149                      securityNotificationListener.securityNotification.getAction());
150         assertEquals(securityNotificationListener.securityNotification.getResourceIdentifier(),
151                      TestSecurityFilter.StaticMessageUnauthorisedException.class.getName());
152     }
153 
154     @Test
155     public void testSendNotification() throws Exception
156     {
157         TestEndpointMessageNotificationListener listener = new TestEndpointMessageNotificationListener(2);
158         muleContext.registerListener(listener);
159 
160         OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
161         MuleEvent outboundEvent = createTestOutboundEvent();
162 
163         endpoint.process(outboundEvent);
164 
165         assertEventSent();
166         assertTrue(listener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
167         assertEquals(2, listener.messageNotificationList.size());
168         assertEquals(EndpointMessageNotification.MESSAGE_SEND_BEGIN, listener.messageNotificationList.get(0).getAction());
169         assertEquals(EndpointMessageNotification.MESSAGE_SEND_END, listener.messageNotificationList.get(1).getAction());
170         assertTrue(listener.messageNotificationList.get(0).getSource() instanceof MuleMessage);
171         assertTrue(listener.messageNotificationList.get(1).getSource() instanceof MuleMessage);
172         assertEquals(outboundEvent.getMessage().getPayload(),
173             listener.messageNotificationList.get(0).getSource().getPayload());
174         assertEquals(RESPONSE_MESSAGE,
175             listener.messageNotificationList.get(1).getSource().getPayload());
176     }
177 
178     @Test
179     public void testDispatchNotification() throws Exception
180     {
181         TestEndpointMessageNotificationListener listener = new TestEndpointMessageNotificationListener(2);
182         muleContext.registerListener(listener);
183 
184         OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.ONE_WAY, null);
185         MuleEvent outboundEvent = createTestOutboundEvent();
186 
187         endpoint.process(outboundEvent);
188 
189         assertEventDispatched();
190         assertTrue(listener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
191         assertEquals(2, listener.messageNotificationList.size());
192         assertEquals(EndpointMessageNotification.MESSAGE_DISPATCH_BEGIN, listener.messageNotificationList.get(0).getAction());
193         assertEquals(EndpointMessageNotification.MESSAGE_DISPATCH_END, listener.messageNotificationList.get(1).getAction());
194         assertTrue(listener.messageNotificationList.get(0).getSource() instanceof MuleMessage);
195         assertTrue(listener.messageNotificationList.get(1).getSource() instanceof MuleMessage);
196         assertEquals(outboundEvent.getMessage().getPayload(),
197             listener.messageNotificationList.get(0).getSource().getPayload());
198         assertEquals(outboundEvent.getMessage().getPayload(),
199             listener.messageNotificationList.get(1).getSource().getPayload());;
200     }
201 
202     @Test
203     public void testTransformers() throws Exception
204     {
205         OutboundEndpoint endpoint = createOutboundEndpoint(null, null, new OutboundAppendTransformer(),
206                                                            new ResponseAppendTransformer(), MessageExchangePattern.REQUEST_RESPONSE, null);
207 
208         testOutboundEvent = createTestOutboundEvent();
209 
210         MuleEvent result = endpoint.process(testOutboundEvent);
211 
212         assertNotNull(result);
213         assertEquals(TEST_MESSAGE + OutboundAppendTransformer.APPEND_STRING, MyMessageDispatcherFactory.dispatcher.sensedSendEvent.getMessageAsString());
214         assertEquals(RESPONSE_MESSAGE + ResponseAppendTransformer.APPEND_STRING, result.getMessageAsString());
215     }
216 
217     @Test(expected = UnsupportedOperationException.class)
218     public void testConnectorNotAvailableOnDynamicEndpoint() throws Exception
219     {
220         OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
221 
222         endpoint.getConnector();
223     }
224 
225     @Test
226     public void testTimeoutSetOnEvent() throws Exception
227     {
228         int testTimeout = 999;
229 
230         OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
231 
232         testOutboundEvent = createTestOutboundEvent();
233         testOutboundEvent.getMessage().setOutboundProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, testTimeout);
234 
235         MuleEvent response = endpoint.process(testOutboundEvent);
236 
237         assertEquals(testTimeout, response.getTimeout());
238     }
239 
240     @Test
241     public void testTransaction()
242     {
243         // TODO
244     }
245 
246     @Test
247     public void testExceptionHandling()
248     {
249         // TODO
250     }
251 
252     protected void assertMessageSentEqual(MuleEvent event) throws MuleException
253     {
254         assertEquals(TEST_MESSAGE, event.getMessageAsString());
255         assertEquals("value1", event.getMessage().getOutboundProperty("prop1"));
256     }
257 
258     protected void assertMessageEqualEncodingPropertyAdded(MuleMessage expect, MuleMessage actual)
259     {
260         assertEquals(expect.getPayload(), actual.getPayload());
261         assertEquals(expect.getEncoding(), actual.getEncoding());
262         assertEquals(expect.getUniqueId(), actual.getUniqueId());
263         assertEquals(expect.getExceptionPayload(), actual.getExceptionPayload());
264 
265         assertEquals(muleContext.getConfiguration().getDefaultEncoding(),
266                      actual.getOutboundProperty(MuleProperties.MULE_ENCODING_PROPERTY));
267 
268     }
269 
270     private void assertEventDispatched()
271     {
272         Prober prober = new PollingProber();
273         prober.check(new Probe()
274         {
275             public boolean isSatisfied()
276             {
277                 return MyMessageDispatcherFactory.dispatcher != null && MyMessageDispatcherFactory.dispatcher.dispatchedEvent;
278             }
279 
280             public String describeFailure()
281             {
282                 return "Expected dispatcher was not called";
283             }
284         });
285 
286         assertNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
287         assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent);
288         assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent.getMessage());
289     }
290 
291     private void assertEventSent()
292     {
293         Prober prober = new PollingProber();
294         prober.check(new Probe()
295         {
296             public boolean isSatisfied()
297             {
298                 return MyMessageDispatcherFactory.dispatcher != null && MyMessageDispatcherFactory.dispatcher.sentEvent;
299             }
300 
301             public String describeFailure()
302             {
303                 return "Expected dispatcher was not called";
304             }
305         });
306 
307         assertNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent);
308         assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
309         assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent.getMessage());
310     }
311 
312     private void overrideDispatcherInServiceDescriptor() throws ServiceException
313     {
314         Properties props = new Properties();
315         props.put(MuleProperties.CONNECTOR_DISPATCHER_FACTORY, MyMessageDispatcherFactory.class.getName());
316         DefaultTransportServiceDescriptor serviceDescriptor = (DefaultTransportServiceDescriptor) muleContext.getRegistry().lookupServiceDescriptor(ServiceType.TRANSPORT, "test", null);
317         props.put(MuleProperties.CONNECTOR_INBOUND_EXCHANGE_PATTERNS, "ONE_WAY, REQUEST_RESPONSE");
318         props.put(MuleProperties.CONNECTOR_OUTBOUND_EXCHANGE_PATTERNS, "ONE_WAY, REQUEST_RESPONSE");
319         serviceDescriptor.setOverrides(props);
320     }
321 
322     protected OutboundEndpoint createOutboundEndpoint(Filter filter,
323                                                       SecurityFilter securityFilter,
324                                                       Transformer in,
325                                                       Transformer response,
326                                                       MessageExchangePattern exchangePattern,
327                                                       TransactionConfig txConfig) throws Exception
328     {
329 
330         return createTestOutboundEndpoint("test://localhost:#[header:port]", filter, securityFilter, in, response,
331                                           exchangePattern, txConfig);
332     }
333 
334     private static class FakeMessageDispatcher extends TestMessageDispatcher
335     {
336 
337         private MuleEvent sensedSendEvent;
338         private MuleEvent sensedDispatchEvent;
339         private boolean sentEvent;
340         private boolean dispatchedEvent;
341 
342         public FakeMessageDispatcher(OutboundEndpoint endpoint)
343         {
344             super(endpoint);
345         }
346 
347         @Override
348         protected MuleMessage doSend(MuleEvent event) throws Exception
349         {
350             sensedSendEvent = event;
351             sentEvent = true;
352             return responseMessage;
353         }
354 
355         @Override
356         protected void doDispatch(MuleEvent event) throws Exception
357         {
358             sensedDispatchEvent = event;
359             dispatchedEvent = true;
360         }
361     }
362 
363     public static class MyMessageDispatcherFactory extends TestMessageDispatcherFactory
364     {
365 
366         static FakeMessageDispatcher dispatcher;
367 
368         @Override
369         public synchronized MessageDispatcher create(OutboundEndpoint ep) throws MuleException
370         {
371             if (dispatcher != null)
372             {
373                 throw new IllegalStateException("Dispatcher for this test was already created");
374             }
375 
376             dispatcher = new FakeMessageDispatcher(ep);
377             return dispatcher;
378         }
379     }
380 }