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