1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.client;
12
13 import org.mule.DefaultMuleEvent;
14 import org.mule.DefaultMuleMessage;
15 import org.mule.DefaultMuleSession;
16 import org.mule.MuleServer;
17 import org.mule.MuleSessionHandler;
18 import org.mule.NullSessionHandler;
19 import org.mule.RegistryContext;
20 import org.mule.RequestContext;
21 import org.mule.api.FutureMessageResult;
22 import org.mule.api.MuleEvent;
23 import org.mule.api.MuleException;
24 import org.mule.api.MuleMessage;
25 import org.mule.api.MuleSession;
26 import org.mule.api.config.MuleProperties;
27 import org.mule.api.endpoint.EndpointBuilder;
28 import org.mule.api.endpoint.EndpointFactory;
29 import org.mule.api.endpoint.ImmutableEndpoint;
30 import org.mule.api.endpoint.OutboundEndpoint;
31 import org.mule.api.lifecycle.Disposable;
32 import org.mule.api.security.Credentials;
33 import org.mule.api.transformer.wire.WireFormat;
34 import org.mule.api.transport.DispatchException;
35 import org.mule.module.client.i18n.ClientMessages;
36 import org.mule.module.client.remoting.RemoteDispatcherException;
37 import org.mule.module.client.remoting.ServerHandshake;
38 import org.mule.module.client.remoting.UnsupportedWireFormatException;
39 import org.mule.module.client.remoting.notification.RemoteDispatcherNotification;
40 import org.mule.security.MuleCredentials;
41 import org.mule.transformer.TransformerUtils;
42 import org.mule.transport.AbstractConnector;
43 import org.mule.util.ClassUtils;
44 import org.mule.util.IOUtils;
45
46 import java.io.ByteArrayInputStream;
47 import java.io.ByteArrayOutputStream;
48 import java.io.InputStream;
49 import java.util.Map;
50
51 import edu.emory.mathcs.backport.java.util.concurrent.Callable;
52 import edu.emory.mathcs.backport.java.util.concurrent.Executor;
53
54 import org.apache.commons.lang.SerializationUtils;
55 import org.apache.commons.logging.Log;
56 import org.apache.commons.logging.LogFactory;
57
58
59
60
61
62
63
64 public class RemoteDispatcher implements Disposable
65 {
66
67
68
69
70 protected static final Log logger = LogFactory.getLog(RemoteDispatcher.class);
71
72
73
74
75 private OutboundEndpoint asyncServerEndpoint;
76 private OutboundEndpoint syncServerEndpoint;
77 private Credentials credentials = null;
78
79
80
81
82 private Executor asyncExecutor;
83
84
85
86
87 private WireFormat wireFormat;
88
89 protected RemoteDispatcher(String endpoint, Credentials credentials) throws MuleException
90 {
91 this(endpoint);
92 this.credentials = credentials;
93 }
94
95 protected RemoteDispatcher(String endpoint) throws MuleException
96 {
97 EndpointFactory endpointFactory = RegistryContext.getRegistry().lookupEndpointFactory();
98 asyncServerEndpoint = endpointFactory.getOutboundEndpoint(endpoint);
99
100 EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(endpoint);
101 endpointBuilder.setRemoteSync(true);
102 syncServerEndpoint = RegistryContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(
103 endpointBuilder);
104
105 wireFormat = requestWireFormat();
106 }
107
108 protected WireFormat requestWireFormat() throws MuleException
109 {
110 MuleMessage msg = new DefaultMuleMessage(ServerHandshake.SERVER_HANDSHAKE_PROPERTY);
111 MuleMessage result = syncServerEndpoint.send(new DefaultMuleEvent(msg, syncServerEndpoint,
112 new DefaultMuleSession(msg, new NullSessionHandler(), MuleServer.getMuleContext()), true));
113
114 if(result==null)
115 {
116 throw new RemoteDispatcherException(ClientMessages.failedToDispatchActionNoResponseFromServer("request wire format", 5000));
117 }
118
119 ServerHandshake handshake;
120 try
121 {
122 ByteArrayInputStream in = new ByteArrayInputStream(result.getPayloadAsBytes());
123 handshake = (ServerHandshake) SerializationUtils.deserialize(in);
124 }
125 catch (Exception e)
126 {
127 throw new RemoteDispatcherException(ClientMessages.failedToDeserializeHandshakeFromServer(), e);
128 }
129
130 try
131 {
132 WireFormat wf = (WireFormat)ClassUtils.instanciateClass(handshake.getWireFormatClass(),
133 ClassUtils.NO_ARGS, getClass());
134
135 return wf;
136 }
137 catch (Exception e)
138 {
139 throw new UnsupportedWireFormatException(handshake.getWireFormatClass(), e);
140 }
141 }
142
143 protected void setExecutor(Executor e)
144 {
145 this.asyncExecutor = e;
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160 public void dispatchToRemoteComponent(String component, Object payload, Map messageProperties)
161 throws MuleException
162 {
163 doToRemoteComponent(component, payload, messageProperties, false);
164 }
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179 public MuleMessage sendToRemoteComponent(String component, Object payload, Map messageProperties)
180 throws MuleException
181 {
182 return doToRemoteComponent(component, payload, messageProperties, true);
183 }
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202 public FutureMessageResult sendAsyncToRemoteComponent(final String component,
203 String transformers,
204 final Object payload,
205 final Map messageProperties) throws MuleException
206 {
207 Callable callable = new Callable()
208 {
209 public Object call() throws Exception
210 {
211 return doToRemoteComponent(component, payload, messageProperties, true);
212 }
213 };
214
215 FutureMessageResult result = new FutureMessageResult(callable);
216
217 if (asyncExecutor != null)
218 {
219 result.setExecutor(asyncExecutor);
220 }
221
222 if (transformers != null)
223 {
224 result.setTransformers(TransformerUtils.getTransformers(transformers));
225 }
226
227 result.execute();
228 return result;
229 }
230
231 public MuleMessage sendRemote(String endpoint, Object payload, Map messageProperties, int timeout)
232 throws MuleException
233 {
234 return doToRemote(endpoint, payload, messageProperties, true, timeout);
235 }
236
237 public MuleMessage sendRemote(String endpoint, Object payload, Map messageProperties) throws MuleException
238 {
239 return doToRemote(endpoint, payload, messageProperties, true,
240 MuleServer.getMuleContext().getConfiguration().getDefaultSynchronousEventTimeout());
241 }
242
243 public void dispatchRemote(String endpoint, Object payload, Map messageProperties) throws MuleException
244 {
245 doToRemote(endpoint, payload, messageProperties, false, -1);
246 }
247
248 public FutureMessageResult sendAsyncRemote(final String endpoint,
249 final Object payload,
250 final Map messageProperties) throws MuleException
251 {
252 Callable callable = new Callable()
253 {
254 public Object call() throws Exception
255 {
256 return doToRemote(endpoint, payload, messageProperties, true, -1);
257 }
258 };
259
260 FutureMessageResult result = new FutureMessageResult(callable);
261
262 if (asyncExecutor != null)
263 {
264 result.setExecutor(asyncExecutor);
265 }
266
267 result.execute();
268 return result;
269 }
270
271 public MuleMessage receiveRemote(String endpoint, int timeout) throws MuleException
272 {
273 RemoteDispatcherNotification action = new RemoteDispatcherNotification(null, RemoteDispatcherNotification.ACTION_RECEIVE, endpoint);
274 action.setProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, "true");
275 action.setProperty(MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, new Long(timeout));
276 return dispatchAction(action, true, timeout);
277 }
278
279 public FutureMessageResult asyncReceiveRemote(final String endpoint, final int timeout)
280 throws MuleException
281 {
282 Callable callable = new Callable()
283 {
284 public Object call() throws Exception
285 {
286 return receiveRemote(endpoint, timeout);
287 }
288 };
289
290 FutureMessageResult result = new FutureMessageResult(callable);
291
292 if (asyncExecutor != null)
293 {
294 result.setExecutor(asyncExecutor);
295 }
296
297 result.execute();
298 return result;
299 }
300
301 protected MuleMessage doToRemoteComponent(String component,
302 Object payload,
303 Map messageProperties,
304 boolean synchronous) throws MuleException
305 {
306 MuleMessage message = new DefaultMuleMessage(payload, messageProperties);
307 message.setBooleanProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, synchronous);
308 setCredentials(message);
309 RemoteDispatcherNotification action = new RemoteDispatcherNotification(message, RemoteDispatcherNotification.ACTION_INVOKE,
310 "mule://" + component);
311 return dispatchAction(action, synchronous,
312 MuleServer.getMuleContext().getConfiguration().getDefaultSynchronousEventTimeout());
313 }
314
315 protected MuleMessage doToRemote(String endpoint,
316 Object payload,
317 Map messageProperties,
318 boolean synchronous,
319 int timeout) throws MuleException
320 {
321 MuleMessage message = new DefaultMuleMessage(payload, messageProperties);
322 message.setProperty(MuleProperties.MULE_REMOTE_SYNC_PROPERTY, String.valueOf(synchronous));
323 setCredentials(message);
324 RemoteDispatcherNotification action = new RemoteDispatcherNotification(message, (synchronous
325 ? RemoteDispatcherNotification.ACTION_SEND : RemoteDispatcherNotification.ACTION_DISPATCH), endpoint);
326
327 return dispatchAction(action, synchronous, timeout);
328 }
329
330 protected MuleMessage dispatchAction(RemoteDispatcherNotification action, boolean synchronous, int timeout)
331 throws MuleException
332 {
333 OutboundEndpoint serverEndpoint;
334 if (synchronous)
335 {
336 serverEndpoint = syncServerEndpoint;
337 }
338 else
339 {
340 serverEndpoint = asyncServerEndpoint;
341 }
342 MuleMessage serializeMessage = new DefaultMuleMessage(action);
343
344 updateContext(serializeMessage, serverEndpoint, synchronous);
345
346 ByteArrayOutputStream out = new ByteArrayOutputStream();
347 wireFormat.write(out, serializeMessage, serverEndpoint.getEncoding());
348 byte[] payload = out.toByteArray();
349
350 MuleMessage message = action.getMessage();
351
352 if (message == null)
353 {
354 message = new DefaultMuleMessage(payload);
355 }
356 else
357 {
358 message = new DefaultMuleMessage(payload, message);
359 }
360
361 message.addProperties(action.getProperties());
362 MuleSession session = new DefaultMuleSession(message,
363 ((AbstractConnector)serverEndpoint.getConnector()).getSessionHandler(), MuleServer.getMuleContext());
364
365 MuleEvent event = new DefaultMuleEvent(message, serverEndpoint, session, true);
366 event.setTimeout(timeout);
367 if (logger.isDebugEnabled())
368 {
369 logger.debug("MuleClient sending remote call to: " + action.getResourceIdentifier() + ". At "
370 + serverEndpoint.toString() + " . Event is: " + event);
371 }
372
373 MuleMessage result;
374
375 try
376 {
377 if (synchronous)
378 {
379 result = serverEndpoint.send(event);
380 }
381 else
382 {
383 serverEndpoint.dispatch(event);
384 return null;
385 }
386
387 if (result != null)
388 {
389 if (result.getPayload() != null)
390 {
391 Object response;
392 if (result.getPayload() instanceof InputStream)
393 {
394 byte[] b = IOUtils.toByteArray((InputStream)result.getPayload());
395 if(b.length==0) return null;
396 ByteArrayInputStream in = new ByteArrayInputStream(b);
397 response = wireFormat.read(in);
398 }
399 else
400 {
401 ByteArrayInputStream in = new ByteArrayInputStream(result.getPayloadAsBytes());
402 response = wireFormat.read(in);
403 }
404
405 if (response instanceof RemoteDispatcherNotification)
406 {
407 response = ((RemoteDispatcherNotification)response).getMessage();
408 }
409 return (MuleMessage)response;
410 }
411 }
412 }
413 catch (Exception e)
414 {
415 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
416 }
417
418 if (logger.isDebugEnabled())
419 {
420 logger.debug("Result of MuleClient remote call is: "
421 + (result == null ? "null" : result.getPayload()));
422 }
423
424 return result;
425 }
426
427 public void dispose()
428 {
429
430 }
431
432 protected void setCredentials(MuleMessage message)
433 {
434 if (credentials != null)
435 {
436 message.setProperty(MuleProperties.MULE_USER_PROPERTY, MuleCredentials.createHeader(
437 credentials.getUsername(), credentials.getPassword()));
438 }
439 }
440
441 public WireFormat getWireFormat()
442 {
443 return wireFormat;
444 }
445
446 public void setWireFormat(WireFormat wireFormat)
447 {
448 this.wireFormat = wireFormat;
449 }
450
451 protected void updateContext(MuleMessage message, ImmutableEndpoint endpoint, boolean synchronous)
452 throws MuleException
453 {
454
455 RequestContext.setEvent(new DefaultMuleEvent(message, endpoint, new DefaultMuleSession(message,
456 new MuleSessionHandler(), MuleServer.getMuleContext()), synchronous));
457 }
458 }