1
2
3
4
5
6
7 package org.mule.endpoint.outbound;
8
9 import static edu.emory.mathcs.backport.java.util.concurrent.TimeUnit.MILLISECONDS;
10 import static org.junit.Assert.assertEquals;
11 import static org.junit.Assert.assertNotNull;
12 import static org.junit.Assert.assertNotSame;
13 import static org.junit.Assert.assertNull;
14 import static org.junit.Assert.assertTrue;
15 import static org.mockito.Mockito.mock;
16 import static org.mockito.Mockito.times;
17 import static org.mockito.Mockito.verify;
18 import static org.mockito.Mockito.when;
19 import org.mule.MessageExchangePattern;
20 import org.mule.api.MuleEvent;
21 import org.mule.api.MuleException;
22 import org.mule.api.MuleMessage;
23 import org.mule.api.config.MuleProperties;
24 import org.mule.api.endpoint.EndpointBuilder;
25 import org.mule.api.endpoint.OutboundEndpoint;
26 import org.mule.api.registry.ServiceException;
27 import org.mule.api.registry.ServiceType;
28 import org.mule.api.routing.filter.Filter;
29 import org.mule.api.security.SecurityFilter;
30 import org.mule.api.transaction.TransactionConfig;
31 import org.mule.api.transformer.Transformer;
32 import org.mule.api.transport.MessageDispatcher;
33 import org.mule.context.notification.EndpointMessageNotification;
34 import org.mule.context.notification.SecurityNotification;
35 import org.mule.endpoint.AbstractMessageProcessorTestCase;
36 import org.mule.endpoint.DynamicOutboundEndpoint;
37 import org.mule.tck.probe.PollingProber;
38 import org.mule.tck.probe.Probe;
39 import org.mule.tck.probe.Prober;
40 import org.mule.tck.security.TestSecurityFilter;
41 import org.mule.tck.testmodels.mule.TestMessageDispatcher;
42 import org.mule.tck.testmodels.mule.TestMessageDispatcherFactory;
43 import org.mule.transformer.simple.OutboundAppendTransformer;
44 import org.mule.transformer.simple.ResponseAppendTransformer;
45 import org.mule.transport.service.DefaultTransportServiceDescriptor;
46
47 import java.util.Properties;
48
49 import edu.emory.mathcs.backport.java.util.concurrent.TimeUnit;
50 import org.junit.Before;
51 import org.junit.Test;
52
53
54
55
56
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(endpoint);
75
76 MuleEvent result = endpoint.process(testOutboundEvent);
77
78 assertEventSent();
79
80
81
82
83 assertNotSame(responseMessage, result.getMessage());
84
85
86
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(endpoint);
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(endpoint);
110
111 MuleEvent result = endpoint.process(testOutboundEvent);
112
113 assertEventSent();
114 assertMessageSentEqual(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
115
116
117
118
119 assertNotSame(responseMessage, result.getMessage());
120
121
122
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(endpoint);
134
135 MuleEvent result = endpoint.process(testOutboundEvent);
136
137 assertNull(MyMessageDispatcherFactory.dispatcher);
138 assertNotNull(result);
139 assertEquals(TestSecurityFilter.SECURITY_EXCEPTION_MESSAGE, result.getMessage().getPayloadAsString());
140 assertNotNull(result.getMessage().getExceptionPayload());
141 assertTrue(result.getMessage().getExceptionPayload().getException() instanceof TestSecurityFilter.StaticMessageUnauthorisedException);
142
143 assertTrue(securityNotificationListener.latch.await(RECEIVE_TIMEOUT, MILLISECONDS));
144 assertEquals(SecurityNotification.SECURITY_AUTHENTICATION_FAILED,
145 securityNotificationListener.securityNotification.getAction());
146 assertEquals(securityNotificationListener.securityNotification.getResourceIdentifier(),
147 TestSecurityFilter.StaticMessageUnauthorisedException.class.getName());
148 }
149
150 @Test
151 public void testSendNotification() throws Exception
152 {
153 TestEndpointMessageNotificationListener listener = new TestEndpointMessageNotificationListener();
154 muleContext.registerListener(listener);
155
156 OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
157 MuleEvent outboundEvent = createTestOutboundEvent(endpoint);
158
159 endpoint.process(outboundEvent);
160
161 assertEventSent();
162 assertTrue(listener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
163 assertEquals(EndpointMessageNotification.MESSAGE_SENT, listener.messageNotification.getAction());
164 assertTrue(listener.messageNotification.getSource() instanceof MuleMessage);
165 assertEquals(outboundEvent.getMessage().getPayload(), listener.messageNotification.getSource().getPayload());
166 }
167
168 @Test
169 public void testDispatchNotification() throws Exception
170 {
171 TestEndpointMessageNotificationListener listener = new TestEndpointMessageNotificationListener();
172 muleContext.registerListener(listener);
173
174 OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.ONE_WAY, null);
175 MuleEvent outboundEvent = createTestOutboundEvent(endpoint);
176
177 endpoint.process(outboundEvent);
178
179 assertEventDispatched();
180 assertTrue(listener.latch.await(RECEIVE_TIMEOUT, TimeUnit.MILLISECONDS));
181 assertEquals(EndpointMessageNotification.MESSAGE_DISPATCHED, listener.messageNotification.getAction());
182 assertTrue(listener.messageNotification.getSource() instanceof MuleMessage);
183 assertEquals(outboundEvent.getMessage().getPayload(), listener.messageNotification.getSource().getPayload());
184 }
185
186 @Test
187 public void testTransformers() throws Exception
188 {
189 OutboundEndpoint endpoint = createOutboundEndpoint(null, null, new OutboundAppendTransformer(),
190 new ResponseAppendTransformer(), MessageExchangePattern.REQUEST_RESPONSE, null);
191
192 testOutboundEvent = createTestOutboundEvent(endpoint);
193
194 MuleEvent result = endpoint.process(testOutboundEvent);
195
196 assertNotNull(result);
197 assertEquals(TEST_MESSAGE + OutboundAppendTransformer.APPEND_STRING, MyMessageDispatcherFactory.dispatcher.sensedSendEvent.getMessageAsString());
198 assertEquals(RESPONSE_MESSAGE + ResponseAppendTransformer.APPEND_STRING, result.getMessageAsString());
199 }
200
201 @Test(expected = UnsupportedOperationException.class)
202 public void testConnectorNotAvailableOnDynamicEndpoint() throws Exception
203 {
204 OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
205
206 endpoint.getConnector();
207 }
208
209 @Test
210 public void testTimeoutSetOnEvent() throws Exception
211 {
212 int testTimeout = 999;
213
214 OutboundEndpoint endpoint = createOutboundEndpoint(null, null, null, null, MessageExchangePattern.REQUEST_RESPONSE, null);
215
216 testOutboundEvent = createTestOutboundEvent(endpoint);
217 testOutboundEvent.getMessage().setOutboundProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, testTimeout);
218
219 MuleEvent response = endpoint.process(testOutboundEvent);
220
221 assertEquals(testTimeout, response.getTimeout());
222 }
223
224 @Test
225 public void testTransaction()
226 {
227
228 }
229
230 @Test
231 public void testExceptionHandling()
232 {
233
234 }
235
236 @Test
237 public void cachesResolvedStaticEndpoints() throws Exception
238 {
239 OutboundEndpoint prototypeEndpoint = mock(OutboundEndpoint.class);
240 when(prototypeEndpoint.getMuleContext()).thenReturn(muleContext);
241
242 EndpointBuilder staticEndpointBuilder = mock(EndpointBuilder.class);
243 when(staticEndpointBuilder.buildOutboundEndpoint()).thenReturn(prototypeEndpoint);
244
245 EndpointBuilder endpointBuilder = mock(EndpointBuilder.class);
246 when(endpointBuilder.buildOutboundEndpoint()).thenReturn(prototypeEndpoint);
247 when(endpointBuilder.clone()).thenReturn(staticEndpointBuilder);
248
249 DynamicOutboundEndpoint dynamicOutboundEndpoint = new DynamicOutboundEndpoint(endpointBuilder, "test://localhost:#[header:port]");
250
251 testOutboundEvent = createTestOutboundEvent(dynamicOutboundEndpoint);
252 dynamicOutboundEndpoint.process(testOutboundEvent);
253 dynamicOutboundEndpoint.process(testOutboundEvent);
254
255 verify(endpointBuilder, times(1)).buildOutboundEndpoint();
256 }
257
258 protected void assertMessageSentEqual(MuleEvent event) throws MuleException
259 {
260 assertEquals(TEST_MESSAGE, event.getMessageAsString());
261 assertEquals("value1", event.getMessage().getOutboundProperty("prop1"));
262 }
263
264 protected void assertMessageEqualEncodingPropertyAdded(MuleMessage expect, MuleMessage actual)
265 {
266 assertEquals(expect.getPayload(), actual.getPayload());
267 assertEquals(expect.getEncoding(), actual.getEncoding());
268 assertEquals(expect.getUniqueId(), actual.getUniqueId());
269 assertEquals(expect.getExceptionPayload(), actual.getExceptionPayload());
270
271 assertEquals(muleContext.getConfiguration().getDefaultEncoding(),
272 actual.getOutboundProperty(MuleProperties.MULE_ENCODING_PROPERTY));
273
274 }
275
276 private void assertEventDispatched()
277 {
278 Prober prober = new PollingProber();
279 prober.check(new Probe()
280 {
281 public boolean isSatisfied()
282 {
283 return MyMessageDispatcherFactory.dispatcher != null && MyMessageDispatcherFactory.dispatcher.dispatchedEvent;
284 }
285
286 public String describeFailure()
287 {
288 return "Expected dispatcher was not called";
289 }
290 });
291
292 assertNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
293 assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent);
294 assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent.getMessage());
295 }
296
297 private void assertEventSent()
298 {
299 Prober prober = new PollingProber();
300 prober.check(new Probe()
301 {
302 public boolean isSatisfied()
303 {
304 return MyMessageDispatcherFactory.dispatcher != null && MyMessageDispatcherFactory.dispatcher.sentEvent;
305 }
306
307 public String describeFailure()
308 {
309 return "Expected dispatcher was not called";
310 }
311 });
312
313 assertNull(MyMessageDispatcherFactory.dispatcher.sensedDispatchEvent);
314 assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent);
315 assertNotNull(MyMessageDispatcherFactory.dispatcher.sensedSendEvent.getMessage());
316 }
317
318 private void overrideDispatcherInServiceDescriptor() throws ServiceException
319 {
320 Properties props = new Properties();
321 props.put(MuleProperties.CONNECTOR_DISPATCHER_FACTORY, MyMessageDispatcherFactory.class.getName());
322 DefaultTransportServiceDescriptor serviceDescriptor = (DefaultTransportServiceDescriptor) muleContext.getRegistry().lookupServiceDescriptor(ServiceType.TRANSPORT, "test", null);
323 props.put(MuleProperties.CONNECTOR_INBOUND_EXCHANGE_PATTERNS, "ONE_WAY, REQUEST_RESPONSE");
324 props.put(MuleProperties.CONNECTOR_OUTBOUND_EXCHANGE_PATTERNS, "ONE_WAY, REQUEST_RESPONSE");
325 serviceDescriptor.setOverrides(props);
326 }
327
328 protected OutboundEndpoint createOutboundEndpoint(Filter filter,
329 SecurityFilter securityFilter,
330 Transformer in,
331 Transformer response,
332 MessageExchangePattern exchangePattern,
333 TransactionConfig txConfig) throws Exception
334 {
335
336 return createTestOutboundEndpoint("test://localhost:#[header:port]", filter, securityFilter, in, response,
337 exchangePattern, txConfig);
338 }
339
340 private static class FakeMessageDispatcher extends TestMessageDispatcher
341 {
342
343 private MuleEvent sensedSendEvent;
344 private MuleEvent sensedDispatchEvent;
345 private boolean sentEvent;
346 private boolean dispatchedEvent;
347
348 public FakeMessageDispatcher(OutboundEndpoint endpoint)
349 {
350 super(endpoint);
351 }
352
353 @Override
354 protected MuleMessage doSend(MuleEvent event) throws Exception
355 {
356 sensedSendEvent = event;
357 sentEvent = true;
358 return responseMessage;
359 }
360
361 @Override
362 protected void doDispatch(MuleEvent event) throws Exception
363 {
364 sensedDispatchEvent = event;
365 dispatchedEvent = true;
366 }
367 }
368
369 public static class MyMessageDispatcherFactory extends TestMessageDispatcherFactory
370 {
371
372 static FakeMessageDispatcher dispatcher;
373
374 @Override
375 public synchronized MessageDispatcher create(OutboundEndpoint ep) throws MuleException
376 {
377 if (dispatcher != null)
378 {
379 throw new IllegalStateException("Dispatcher for this test was already created");
380 }
381
382 dispatcher = new FakeMessageDispatcher(ep);
383 return dispatcher;
384 }
385 }
386 }