1
2
3
4
5
6
7
8
9
10
11 package org.mule.module.client.remoting;
12
13 import org.mule.DefaultMuleEvent;
14 import org.mule.DefaultMuleMessage;
15 import org.mule.MessageExchangePattern;
16 import org.mule.RequestContext;
17 import org.mule.api.DefaultMuleException;
18 import org.mule.api.MuleContext;
19 import org.mule.api.MuleEvent;
20 import org.mule.api.MuleEventContext;
21 import org.mule.api.MuleException;
22 import org.mule.api.MuleMessage;
23 import org.mule.api.MuleSession;
24 import org.mule.api.config.MuleProperties;
25 import org.mule.api.endpoint.EndpointBuilder;
26 import org.mule.api.endpoint.EndpointFactory;
27 import org.mule.api.endpoint.ImmutableEndpoint;
28 import org.mule.api.endpoint.InboundEndpoint;
29 import org.mule.api.endpoint.OutboundEndpoint;
30 import org.mule.api.lifecycle.Callable;
31 import org.mule.api.lifecycle.Initialisable;
32 import org.mule.api.lifecycle.InitialisationException;
33 import org.mule.api.service.Service;
34 import org.mule.api.source.CompositeMessageSource;
35 import org.mule.api.transformer.DataType;
36 import org.mule.api.transformer.TransformerException;
37 import org.mule.api.transformer.wire.WireFormat;
38 import org.mule.component.SimpleCallableJavaComponent;
39 import org.mule.config.i18n.CoreMessages;
40 import org.mule.endpoint.EndpointURIEndpointBuilder;
41 import org.mule.message.DefaultExceptionPayload;
42 import org.mule.model.seda.SedaService;
43 import org.mule.module.client.remoting.notification.RemoteDispatcherNotification;
44 import org.mule.object.PrototypeObjectFactory;
45 import org.mule.session.DefaultMuleSession;
46 import org.mule.transport.AbstractConnector;
47 import org.mule.transport.NullPayload;
48 import org.mule.util.MapUtils;
49
50 import java.io.ByteArrayInputStream;
51 import java.lang.reflect.Method;
52 import java.util.HashMap;
53 import java.util.LinkedList;
54 import java.util.List;
55 import java.util.Map;
56
57 import org.apache.commons.io.output.ByteArrayOutputStream;
58 import org.apache.commons.logging.Log;
59 import org.apache.commons.logging.LogFactory;
60
61
62
63
64
65
66
67
68 public class RemoteDispatcherComponent implements Callable, Initialisable
69 {
70
71
72
73 protected static final Log logger = LogFactory.getLog(RemoteDispatcherComponent.class);
74
75 public static final String MANAGER_COMPONENT_NAME = "_muleManagerComponent";
76
77
78
79
80 protected WireFormat wireFormat;
81
82 protected String encoding;
83
84 protected int synchronousEventTimeout = 5000;
85
86 protected MuleContext muleContext;
87
88 public void initialise() throws InitialisationException
89 {
90 if (wireFormat == null)
91 {
92 throw new InitialisationException(CoreMessages.objectIsNull("wireFormat"), this);
93 }
94 }
95
96 public Object onCall(MuleEventContext context) throws Exception
97 {
98 muleContext = context.getMuleContext();
99 if(context.transformMessageToString().equals(ServerHandshake.SERVER_HANDSHAKE_PROPERTY))
100 {
101 return doHandshake(context);
102 }
103
104 Object result;
105 logger.debug("Message received by RemoteDispatcherComponent");
106 ByteArrayInputStream in = new ByteArrayInputStream((byte[]) context.transformMessage(DataType.BYTE_ARRAY_DATA_TYPE));
107 RemoteDispatcherNotification action = (RemoteDispatcherNotification) ((MuleMessage)wireFormat.read(in)).getPayload();
108
109
110
111 if(action.getMessage()!=null)
112 {
113 Method m = action.getMessage().getClass().getDeclaredMethod("initAfterDeserialisation", MuleContext.class);
114 m.setAccessible(true);
115 m.invoke(action.getMessage(), muleContext);
116 }
117
118 if (RemoteDispatcherNotification.ACTION_INVOKE == action.getAction())
119 {
120 result = invokeAction(action, context);
121 }
122 else if (RemoteDispatcherNotification.ACTION_SEND == action.getAction() ||
123 RemoteDispatcherNotification.ACTION_DISPATCH == action.getAction())
124 {
125 result = sendAction(action, context);
126 }
127 else if (RemoteDispatcherNotification.ACTION_RECEIVE == action.getAction())
128 {
129 result = receiveAction(action, context);
130 }
131 else
132 {
133 result = handleException(null, new DefaultMuleException(
134 CoreMessages.eventTypeNotRecognised("RemoteDispatcherNotification:" + action.getAction())));
135 }
136 return result;
137 }
138
139 protected ServerHandshake doHandshake(MuleEventContext context) throws TransformerException
140 {
141 ServerHandshake handshake = new ServerHandshake();
142 handshake.setWireFormatClass(wireFormat.getClass().getName());
143 return handshake;
144 }
145
146 protected Object invokeAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
147 {
148 String destComponent;
149 MuleMessage result = null;
150 String endpoint = action.getResourceIdentifier();
151 if (action.getResourceIdentifier().startsWith("mule:"))
152 {
153 destComponent = endpoint.substring(endpoint.lastIndexOf("/") + 1);
154 }
155 else
156 {
157 destComponent = endpoint;
158 }
159
160 if (destComponent != null)
161 {
162 Service service = muleContext.getRegistry().lookupService(destComponent);
163 MuleSession session = new DefaultMuleSession(service, muleContext);
164
165
166
167
168 EndpointBuilder builder = new EndpointURIEndpointBuilder(RequestContext.getEvent().getEndpoint());
169
170 builder.setTransformers(new LinkedList());
171 ImmutableEndpoint ep = muleContext.getEndpointFactory().getInboundEndpoint(builder);
172 MuleEvent event = new DefaultMuleEvent(action.getMessage(), ep, context.getSession());
173 event = RequestContext.setEvent(event);
174
175 if (context.getExchangePattern().hasResponse())
176 {
177 MuleEvent resultEvent = service.sendEvent(event);
178 result = resultEvent == null ? null : resultEvent.getMessage();
179 ByteArrayOutputStream out = new ByteArrayOutputStream();
180 wireFormat.write(out, result, getEncoding());
181 return out.toByteArray();
182 }
183 else
184 {
185 service.dispatchEvent(event);
186 return null;
187 }
188 }
189 else
190 {
191 return handleException(result, new DefaultMuleException(
192 CoreMessages.couldNotDetermineDestinationComponentFromEndpoint(endpoint)));
193 }
194 }
195
196 protected Object sendAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
197 {
198 MuleMessage result = null;
199 OutboundEndpoint endpoint = null;
200 MuleContext managementContext = context.getMuleContext();
201 try
202 {
203 if (RemoteDispatcherNotification.ACTION_DISPATCH == action.getAction())
204 {
205 endpoint = managementContext.getEndpointFactory().getOutboundEndpoint(
206 action.getResourceIdentifier());
207 context.dispatchEvent(action.getMessage(), endpoint);
208 return null;
209 }
210 else
211 {
212 EndpointFactory endpointFactory = managementContext.getRegistry().lookupEndpointFactory();
213 EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(action.getResourceIdentifier());
214 endpointBuilder.setExchangePattern(MessageExchangePattern.REQUEST_RESPONSE);
215 endpoint = managementContext.getEndpointFactory().getOutboundEndpoint(endpointBuilder);
216 result = context.sendEvent(action.getMessage(), endpoint);
217 if (result == null)
218 {
219 return null;
220 }
221 else
222 {
223 ByteArrayOutputStream out = new ByteArrayOutputStream();
224 wireFormat.write(out, result, getEncoding());
225 return out.toByteArray();
226 }
227 }
228 }
229 catch (Exception e)
230 {
231 return handleException(result, e);
232 }
233 }
234
235 protected Object receiveAction(RemoteDispatcherNotification action, MuleEventContext context) throws MuleException
236 {
237 MuleMessage result = null;
238 try
239 {
240 ImmutableEndpoint endpoint = context.getMuleContext()
241 .getRegistry()
242 .lookupEndpointFactory()
243 .getOutboundEndpoint(action.getResourceIdentifier());
244
245 long timeout = MapUtils.getLongValue(action.getProperties(),
246 MuleProperties.MULE_EVENT_TIMEOUT_PROPERTY, getSynchronousEventTimeout());
247
248 result = endpoint.getConnector().request(action.getResourceIdentifier(), timeout);
249 if (result != null)
250 {
251
252 List transformers = ((AbstractConnector) endpoint.getConnector()).getDefaultInboundTransformers(endpoint);
253 if (transformers != null)
254 {
255 result.applyTransformers(null, transformers);
256 }
257 ByteArrayOutputStream out = new ByteArrayOutputStream();
258 wireFormat.write(out, result, getEncoding());
259 return out.toByteArray();
260 }
261 else
262 {
263 return null;
264 }
265 }
266 catch (Exception e)
267 {
268 return handleException(result, e);
269 }
270
271 }
272
273
274 public static Service getSerivce(InboundEndpoint endpoint,
275 WireFormat wireFormat,
276 String encoding,
277 int eventTimeout,
278 MuleContext muleContext) throws MuleException
279 {
280 try
281 {
282 Service service = new SedaService(muleContext);
283 service.setName(MANAGER_COMPONENT_NAME);
284 service.setModel(muleContext.getRegistry().lookupSystemModel());
285
286 Map props = new HashMap();
287 props.put("wireFormat", wireFormat);
288 props.put("encoding", encoding);
289 props.put("synchronousEventTimeout", new Integer(eventTimeout));
290 final SimpleCallableJavaComponent component = new SimpleCallableJavaComponent(new PrototypeObjectFactory(RemoteDispatcherComponent.class, props));
291 component.setMuleContext(muleContext);
292 service.setComponent(component);
293
294
295 if (!(service.getMessageSource() instanceof CompositeMessageSource))
296 {
297 throw new IllegalStateException("Only 'CompositeMessageSource' is supported with RemoteDispatcherService");
298 }
299
300 ((CompositeMessageSource) service.getMessageSource()).addSource(endpoint);
301
302 return service;
303 }
304 catch (Exception e)
305 {
306 throw new InitialisationException(e, null);
307 }
308 }
309
310
311
312
313
314
315
316
317
318
319 protected Object handleException(MuleMessage result, Throwable e)
320 {
321 logger.error("Failed to process admin request: " + e.getMessage(), e);
322 if (result == null)
323 {
324 result = new DefaultMuleMessage(NullPayload.getInstance(), (Map) null, muleContext);
325 }
326 result.setExceptionPayload(new DefaultExceptionPayload(e));
327 try
328 {
329 ByteArrayOutputStream out = new ByteArrayOutputStream();
330 wireFormat.write(out, result, getEncoding());
331 return out.toByteArray();
332 }
333 catch (Exception e1)
334 {
335
336
337 logger.error("Failed to format message, using direct string (details at debug level): " + e1.getMessage());
338 logger.debug(e1.toString(), e1);
339 return e.getMessage();
340 }
341 }
342
343 public WireFormat getWireFormat()
344 {
345 return wireFormat;
346 }
347
348 public void setWireFormat(WireFormat wireFormat)
349 {
350 this.wireFormat = wireFormat;
351 }
352
353 public String getEncoding()
354 {
355 return encoding;
356 }
357
358 public void setEncoding(String encoding)
359 {
360 this.encoding = encoding;
361 }
362
363 public int getSynchronousEventTimeout()
364 {
365 return synchronousEventTimeout;
366 }
367
368 public void setSynchronousEventTimeout(int synchronousEventTimeout)
369 {
370 this.synchronousEventTimeout = synchronousEventTimeout;
371 }
372 }