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.inbound;
8   
9   import org.mule.DefaultMuleEvent;
10  import org.mule.DefaultMuleMessage;
11  import org.mule.MessageExchangePattern;
12  import org.mule.RequestContext;
13  import org.mule.api.MuleEvent;
14  import org.mule.api.MuleException;
15  import org.mule.api.MuleMessage;
16  import org.mule.api.endpoint.ImmutableEndpoint;
17  import org.mule.api.endpoint.InboundEndpoint;
18  import org.mule.api.processor.MessageProcessor;
19  import org.mule.api.routing.filter.Filter;
20  import org.mule.api.routing.filter.FilterUnacceptedException;
21  import org.mule.api.security.EndpointSecurityFilter;
22  import org.mule.context.notification.EndpointMessageNotification;
23  import org.mule.context.notification.SecurityNotification;
24  import org.mule.endpoint.AbstractEndpoint;
25  import org.mule.endpoint.AbstractMessageProcessorTestCase;
26  import org.mule.endpoint.EndpointURIEndpointBuilder;
27  import org.mule.message.DefaultExceptionPayload;
28  import org.mule.processor.NullMessageProcessor;
29  import org.mule.tck.security.TestSecurityFilter;
30  import org.mule.transformer.simple.InboundAppendTransformer;
31  import org.mule.transformer.simple.ResponseAppendTransformer;
32  
33  import java.util.HashMap;
34  import java.util.Map;
35  
36  import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
37  import org.junit.Test;
38  
39  import static org.junit.Assert.assertEquals;
40  import static org.junit.Assert.assertFalse;
41  import static org.junit.Assert.assertNotNull;
42  import static org.junit.Assert.assertNull;
43  import static org.junit.Assert.assertTrue;
44  
45  public class InboundEndpointTestCase extends AbstractMessageProcessorTestCase
46  {
47      private static final String TEST_MESSAGE = "test";
48      private InboundEndpoint endpoint;
49      private SensingNullMessageProcessor inboundListener;
50      private MuleMessage inMessage;
51      private MuleEvent requestEvent;
52      private MuleEvent responseEvent;
53      private MuleEvent result;
54  
55      private static String RESPONSE_MESSAGE = "response-message";
56  
57      @Override
58      protected void doSetUp() throws Exception
59      {
60          super.doSetUp();
61          inMessage = createTestRequestMessage();
62          inboundListener = new SensingNullMessageProcessor();
63      }
64  
65      @Test
66      public void testDefaultFlowSync() throws Exception
67      {
68          endpoint = createTestInboundEndpoint(null, null, null, null, 
69              MessageExchangePattern.REQUEST_RESPONSE, null);
70          endpoint.setListener(inboundListener);
71          requestEvent = createTestRequestEvent(endpoint);
72          responseEvent = createTestResponseEvent(endpoint);
73  
74          MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
75          result = mpChain.process(requestEvent);
76  
77          assertMessageSentSame(true);
78          assertEquals(responseEvent.getMessage(), result.getMessage());
79      }
80  
81      @Test
82      public void testDefaultFlowAsync() throws Exception
83      {
84          endpoint = createTestInboundEndpoint(null, null, null, null, 
85              MessageExchangePattern.ONE_WAY, null);
86          endpoint.setListener(inboundListener);
87          requestEvent = createTestRequestEvent(endpoint);
88          responseEvent = createTestResponseEvent(endpoint);
89  
90          MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
91          result = mpChain.process(requestEvent);
92  
93          assertMessageSentSame(false);
94          assertEquals(responseEvent.getMessage(), result.getMessage());
95      }
96  
97      @Test
98      public void testFilterAccept() throws Exception
99      {
100         endpoint = createTestInboundEndpoint(new TestFilter(true), null, null, null, 
101             MessageExchangePattern.REQUEST_RESPONSE, null);
102         endpoint.setListener(inboundListener);
103         requestEvent = createTestRequestEvent(endpoint);
104         responseEvent = createTestResponseEvent(endpoint);
105 
106         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
107         result = mpChain.process(requestEvent);
108 
109         assertMessageSentSame(true);
110         assertEquals(responseEvent.getMessage(), result.getMessage());
111 
112     }
113 
114     @Test
115     public void testFilterNotAccept() throws Exception
116     {
117         endpoint = createTestInboundEndpoint(new TestFilter(false), null, null, null, 
118             MessageExchangePattern.REQUEST_RESPONSE, null);
119         endpoint.setListener(inboundListener);
120         requestEvent = createTestRequestEvent(endpoint);
121         responseEvent = createTestResponseEvent(endpoint);
122 
123         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
124 
125         result = mpChain.process(requestEvent);
126         assertNotNull(result);
127         assertNotNull("Filter should have thrown a FilterException", result.getMessage().getExceptionPayload());
128         assertTrue(result.getMessage().getExceptionPayload().getException() instanceof FilterUnacceptedException);
129 
130         assertMessageNotSent();
131     }
132 
133     @Test
134     public void testSecurityFilterAccept() throws Exception
135     {
136         endpoint = createTestInboundEndpoint(null, new TestSecurityFilter(true), null, null, 
137             MessageExchangePattern.REQUEST_RESPONSE, null);
138         endpoint.setListener(inboundListener);
139         requestEvent = createTestRequestEvent(endpoint);
140         responseEvent = createTestResponseEvent(endpoint);
141 
142         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
143         result = mpChain.process(requestEvent);
144 
145         assertMessageSentSame(true);
146         assertEquals(responseEvent.getMessage(), result.getMessage());
147 
148     }
149 
150     @Test
151     public void testSecurityFilterNotAccept() throws Exception
152     {
153         TestSecurityNotificationListener securityNotificationListener = new TestSecurityNotificationListener();
154         muleContext.registerListener(securityNotificationListener);
155 
156         endpoint = createTestInboundEndpoint(null, new TestSecurityFilter(false), null, null, 
157             MessageExchangePattern.REQUEST_RESPONSE, null);
158         endpoint.setListener(inboundListener);
159         requestEvent = createTestRequestEvent(endpoint);
160         responseEvent = createTestResponseEvent(endpoint);
161 
162         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
163         
164         // Required for UnauthorisedException creation
165         RequestContext.setEvent(requestEvent);
166         
167         result = mpChain.process(requestEvent);
168 
169         assertMessageNotSent();
170         assertNotNull(result);
171         assertEquals(TestSecurityFilter.SECURITY_EXCEPTION_MESSAGE, result.getMessage().getPayloadAsString());
172         assertNotNull(result.getMessage().getExceptionPayload());
173         assertTrue(result.getMessage().getExceptionPayload().getException() instanceof TestSecurityFilter.StaticMessageUnauthorisedException);
174 
175         assertTrue(securityNotificationListener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
176         assertEquals(SecurityNotification.SECURITY_AUTHENTICATION_FAILED,
177             securityNotificationListener.securityNotification.getAction());
178         assertEquals(securityNotificationListener.securityNotification.getResourceIdentifier(),
179             TestSecurityFilter.StaticMessageUnauthorisedException.class.getName());
180     }
181 
182     /**
183      * Assert that {@link EndpointSecurityFilter} is only invoked if endpoint
184      * {@link Filter} accepts message.
185      */
186     @Test
187     public void testFilterFirstThenSecurityFilter() throws Exception
188     {
189         TestSecurityFilter securityFilter = new TestSecurityFilter(false);
190         endpoint = createTestInboundEndpoint(new TestFilter(false), securityFilter, null, null, 
191             MessageExchangePattern.REQUEST_RESPONSE, null);
192         endpoint.setListener(inboundListener);
193         requestEvent = createTestRequestEvent(endpoint);
194         responseEvent = createTestResponseEvent(endpoint);
195 
196         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
197 
198         result = mpChain.process(requestEvent);
199         assertNotNull(result);
200         assertNotNull("Filter should have thrown a FilterException", result.getMessage().getExceptionPayload());
201         assertTrue(result.getMessage().getExceptionPayload().getException() instanceof FilterUnacceptedException);
202 
203         assertFalse(securityFilter.wasCalled());
204         assertMessageNotSent();
205     }
206 
207     @Test
208     public void testMessagePropertyErrorMapping() throws Exception
209     {
210         endpoint = createTestInboundEndpoint(null, null, null, null, 
211             MessageExchangePattern.REQUEST_RESPONSE, null);
212         endpoint.setListener(inboundListener);
213         requestEvent = createTestRequestEvent(endpoint);
214         responseEvent = createTestResponseEvent(endpoint);
215         responseEvent.getMessage().setExceptionPayload(new DefaultExceptionPayload(new RuntimeException()));
216 
217         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
218         result = mpChain.process(requestEvent);
219 
220         assertMessageSentSame(true);
221         assertEquals(responseEvent.getMessage(), result.getMessage());
222         final int status = result.getMessage().getOutboundProperty("status", 0);
223         assertEquals(500, status);
224     }
225 
226     @Test
227     public void testResponseTransformerExceptionDetailAfterRequestFlowInterupt() throws Exception
228     {
229         endpoint = createTestInboundEndpoint(null, new TestSecurityFilter(false), null,
230             new ResponseAppendTransformer(), MessageExchangePattern.REQUEST_RESPONSE, null);
231         endpoint.setListener(inboundListener);
232         requestEvent = createTestRequestEvent(endpoint);
233         responseEvent = createTestResponseEvent(endpoint);
234         responseEvent.getMessage().setExceptionPayload(new DefaultExceptionPayload(new RuntimeException()));
235 
236         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
237         
238         // Required for UnauthorisedException creation
239         RequestContext.setEvent(requestEvent);
240         
241         result = mpChain.process(requestEvent);
242 
243         assertMessageNotSent();
244         assertNotNull(result);
245         assertEquals(TestSecurityFilter.SECURITY_EXCEPTION_MESSAGE + ResponseAppendTransformer.APPEND_STRING,
246             result.getMessage().getPayloadAsString());
247         final int status = result.getMessage().getOutboundProperty("status", 0);
248         assertEquals(403, status);
249 
250         assertNotNull(result.getMessage().getExceptionPayload());
251         assertTrue(result.getMessage().getExceptionPayload().getException() instanceof TestSecurityFilter.StaticMessageUnauthorisedException);
252     }
253 
254     @Test
255     public void testNotfication() throws Exception
256     {
257         TestEndpointMessageNotificationListener listener = new TestEndpointMessageNotificationListener();
258         muleContext.registerListener(listener);
259 
260         endpoint = createTestInboundEndpoint(null, null, null, null, 
261             MessageExchangePattern.REQUEST_RESPONSE, null);
262         endpoint.setListener(inboundListener);
263         requestEvent = createTestRequestEvent(endpoint);
264         responseEvent = createTestResponseEvent(endpoint);
265 
266         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
267         result = mpChain.process(requestEvent);
268 
269         assertTrue(listener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
270         assertEquals(EndpointMessageNotification.MESSAGE_RECEIVED, listener.messageNotification.getAction());
271         assertEquals(endpoint.getEndpointURI().getUri().toString(),
272             listener.messageNotification.getEndpoint());
273         assertTrue(listener.messageNotification.getSource() instanceof MuleMessage);
274         assertEquals(inMessage.getPayload(),
275             ((MuleMessage) listener.messageNotification.getSource()).getPayload());
276     }
277 
278     @Test
279     public void testTransformers() throws Exception
280     {
281         endpoint = createTestInboundEndpoint(null, null, new InboundAppendTransformer(),
282             new ResponseAppendTransformer(), MessageExchangePattern.REQUEST_RESPONSE, null);
283         endpoint.setListener(inboundListener);
284         requestEvent = createTestRequestEvent(endpoint);
285         responseEvent = createTestResponseEvent(endpoint);
286 
287         MessageProcessor mpChain = ((AbstractEndpoint) endpoint).getMessageProcessorChain(requestEvent.getFlowConstruct());
288         result = mpChain.process(requestEvent);
289 
290         assertMessageSent(true);
291         assertEquals(TEST_MESSAGE + InboundAppendTransformer.APPEND_STRING,
292             inboundListener.sensedEvent.getMessageAsString());
293 
294         assertNotNull(result);
295         assertEquals(RESPONSE_MESSAGE + ResponseAppendTransformer.APPEND_STRING,
296             result.getMessage().getPayloadAsString());
297     }
298     
299     @Test
300     public void testObjectAwareInjection() throws Exception
301     {
302         EndpointURIEndpointBuilder endpointBuilder = new EndpointURIEndpointBuilder(TEST_URI, muleContext);
303         endpointBuilder.addMessageProcessor(new ObjectAwareProcessor());
304 
305         endpoint = endpointBuilder.buildInboundEndpoint();
306         endpoint.setListener(new NullMessageProcessor());
307         endpoint.setFlowConstruct(getTestService());
308         endpoint.start();
309 
310         ObjectAwareProcessor objectAware = (ObjectAwareProcessor) endpoint.getMessageProcessors().get(0);
311         
312         assertEquals(muleContext, objectAware.context);
313         assertEquals(endpoint, objectAware.endpoint);
314 
315         endpoint.stop();
316     }
317 
318     protected MuleMessage createTestRequestMessage()
319     {
320         Map<String, Object> props = new HashMap<String, Object>();
321         props.put("prop1", "value1");
322         return new DefaultMuleMessage(TEST_MESSAGE, props, muleContext);
323     }
324 
325     protected MuleEvent createTestRequestEvent(ImmutableEndpoint endpoint) throws Exception
326     {
327         return new DefaultMuleEvent(inMessage, endpoint, getTestSession(getTestService(), muleContext));
328     }
329     
330     protected MuleEvent createTestResponseEvent(ImmutableEndpoint endpoint) throws Exception
331     {
332         return new DefaultMuleEvent(new DefaultMuleMessage(RESPONSE_MESSAGE, muleContext),
333             endpoint, getTestSession(getTestService(), muleContext));
334     }
335 
336     protected MuleEvent assertMessageSent(boolean sync) throws MuleException
337     {
338         MuleEvent event = inboundListener.sensedEvent;
339         assertNotNull(event);
340         assertEquals(sync, event.getEndpoint().getExchangePattern().hasResponse());
341         assertNotNull(event.getMessage());
342         return event;
343     }
344 
345     protected MuleEvent assertMessageSentSame(boolean sync) throws MuleException
346     {
347         assertMessageSent(sync);
348         MuleEvent event = inboundListener.sensedEvent;
349         assertEquals(inMessage, event.getMessage());
350         assertEquals(TEST_MESSAGE, event.getMessageAsString());
351         assertEquals("value1", event.getMessage().getOutboundProperty("prop1"));
352         return event;
353     }
354 
355     protected void assertMessageNotSent() throws MuleException
356     {
357         MuleEvent event = inboundListener.sensedEvent;
358         assertNull(event);
359     }
360 
361     class SensingNullMessageProcessor implements MessageProcessor
362     {
363         MuleEvent sensedEvent;
364 
365         public MuleEvent process(MuleEvent event) throws MuleException
366         {
367             sensedEvent = event;
368             return responseEvent;
369         }
370     }
371 }