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