Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
OptimisedMuleProxy |
|
| 2.789473684210526;2.789 |
1 | /* | |
2 | * $Id: OptimisedMuleProxy.java 7963 2007-08-21 08:53:15Z dirk.olmes $ | |
3 | * -------------------------------------------------------------------------------------- | |
4 | * Copyright (c) MuleSource, Inc. All rights reserved. http://www.mulesource.com | |
5 | * | |
6 | * The software in this package is published under the terms of the CPAL v1.0 | |
7 | * license, a copy of which has been included with this distribution in the | |
8 | * LICENSE.txt file. | |
9 | */ | |
10 | ||
11 | package org.mule.impl.model.seda.optimised; | |
12 | ||
13 | import org.mule.config.i18n.CoreMessages; | |
14 | import org.mule.impl.ImmutableMuleDescriptor; | |
15 | import org.mule.impl.MuleDescriptor; | |
16 | import org.mule.impl.MuleMessage; | |
17 | import org.mule.impl.RequestContext; | |
18 | import org.mule.impl.model.MuleProxy; | |
19 | import org.mule.management.stats.ComponentStatistics; | |
20 | import org.mule.management.stats.SedaComponentStatistics; | |
21 | import org.mule.umo.MessagingException; | |
22 | import org.mule.umo.UMOEvent; | |
23 | import org.mule.umo.UMOEventContext; | |
24 | import org.mule.umo.UMOException; | |
25 | import org.mule.umo.UMOImmutableDescriptor; | |
26 | import org.mule.umo.UMOMessage; | |
27 | import org.mule.umo.lifecycle.Callable; | |
28 | import org.mule.umo.lifecycle.Disposable; | |
29 | import org.mule.umo.lifecycle.Startable; | |
30 | import org.mule.umo.lifecycle.Stoppable; | |
31 | import org.mule.umo.model.ModelException; | |
32 | import org.mule.util.ObjectPool; | |
33 | import org.mule.util.queue.QueueSession; | |
34 | ||
35 | import org.apache.commons.logging.Log; | |
36 | import org.apache.commons.logging.LogFactory; | |
37 | ||
38 | /** | |
39 | * <code>MuleProxy</code> is a proxy to a UMO. It is a poolable object that can be | |
40 | * executed in its own thread. | |
41 | */ | |
42 | ||
43 | public class OptimisedMuleProxy implements MuleProxy | |
44 | { | |
45 | /** | |
46 | * logger used by this class | |
47 | */ | |
48 | 0 | private static Log logger = LogFactory.getLog(OptimisedMuleProxy.class); |
49 | ||
50 | /** | |
51 | * Holds the current event being processed | |
52 | */ | |
53 | private UMOEvent event; | |
54 | ||
55 | /** | |
56 | * holds the UMO descriptor | |
57 | */ | |
58 | private ImmutableMuleDescriptor descriptor; | |
59 | ||
60 | /** | |
61 | * Determines if the proxy is suspended | |
62 | */ | |
63 | 0 | private boolean suspended = true; |
64 | ||
65 | private ObjectPool proxyPool; | |
66 | ||
67 | 0 | private ComponentStatistics stat = null; |
68 | ||
69 | private Callable umo; | |
70 | ||
71 | 0 | private boolean started = false; |
72 | 0 | private boolean disposed = false; |
73 | ||
74 | /** | |
75 | * Constructs a Proxy using the UMO's AbstractMessageDispatcher and the UMO | |
76 | * itself | |
77 | * | |
78 | * @param component the underlying object that with receive events | |
79 | * @param descriptor the UMOComponent descriptor associated with the component | |
80 | */ | |
81 | public OptimisedMuleProxy(Callable component, MuleDescriptor descriptor, ObjectPool proxyPool) | |
82 | throws UMOException | |
83 | 0 | { |
84 | 0 | this.descriptor = new ImmutableMuleDescriptor(descriptor); |
85 | 0 | this.proxyPool = proxyPool; |
86 | 0 | umo = component; |
87 | 0 | } |
88 | ||
89 | public void start() throws UMOException | |
90 | { | |
91 | 0 | checkDisposed(); |
92 | 0 | if (!started && umo instanceof Startable) |
93 | { | |
94 | try | |
95 | { | |
96 | 0 | ((Startable) umo).start(); |
97 | 0 | started = true; |
98 | } | |
99 | 0 | catch (Exception e) |
100 | { | |
101 | 0 | throw new ModelException( |
102 | CoreMessages.failedToStart("Component '" + descriptor.getName() + "'"), e); | |
103 | 0 | } |
104 | } | |
105 | ||
106 | 0 | } |
107 | ||
108 | public boolean isStarted() | |
109 | { | |
110 | 0 | return started; |
111 | } | |
112 | ||
113 | public void stop() throws UMOException | |
114 | { | |
115 | 0 | checkDisposed(); |
116 | ||
117 | 0 | if (started && umo instanceof Stoppable) |
118 | { | |
119 | 0 | started = false; |
120 | try | |
121 | { | |
122 | 0 | ((Stoppable) umo).stop(); |
123 | } | |
124 | 0 | catch (Exception e) |
125 | { | |
126 | 0 | throw new ModelException( |
127 | CoreMessages.failedToStop("Component '" + descriptor.getName() + "'"), e); | |
128 | 0 | } |
129 | } | |
130 | 0 | } |
131 | ||
132 | public void dispose() | |
133 | { | |
134 | 0 | checkDisposed(); |
135 | 0 | if (umo instanceof Disposable) |
136 | { | |
137 | 0 | ((Disposable) umo).dispose(); |
138 | 0 | disposed = true; |
139 | } | |
140 | 0 | } |
141 | ||
142 | private void checkDisposed() | |
143 | { | |
144 | 0 | if (disposed) |
145 | { | |
146 | 0 | throw new IllegalStateException("Components Disposed Of"); |
147 | } | |
148 | 0 | } |
149 | ||
150 | /** | |
151 | * Sets the current event being processed | |
152 | * | |
153 | * @param event the event being processed | |
154 | */ | |
155 | public void onEvent(QueueSession session, UMOEvent event) | |
156 | { | |
157 | 0 | this.event = event; |
158 | 0 | } |
159 | ||
160 | public ComponentStatistics getStatistics() | |
161 | { | |
162 | 0 | return stat; |
163 | } | |
164 | ||
165 | public void setStatistics(ComponentStatistics stat) | |
166 | { | |
167 | 0 | this.stat = stat; |
168 | 0 | } |
169 | ||
170 | /** | |
171 | * Makes a synchronous call on the UMO | |
172 | * | |
173 | * @param event the event to pass to the UMO | |
174 | * @return the return event from the UMO | |
175 | * @throws org.mule.umo.UMOException if the call fails | |
176 | */ | |
177 | public Object onCall(UMOEvent event) throws UMOException | |
178 | { | |
179 | 0 | if (logger.isTraceEnabled()) |
180 | { | |
181 | 0 | logger.trace("MuleProxy: sync call for Mule UMO " + descriptor.getName()); |
182 | } | |
183 | ||
184 | 0 | UMOMessage returnMessage = null; |
185 | try | |
186 | { | |
187 | 0 | if (event.getEndpoint().canReceive()) |
188 | { | |
189 | // RequestContext.setEvent(event); | |
190 | // Object replyTo = event.getMessage().getReplyTo(); | |
191 | // ReplyToHandler replyToHandler = null; | |
192 | // if (replyTo != null) { | |
193 | // replyToHandler = ((AbstractConnector) | |
194 | // event.getEndpoint().getConnector()).getReplyToHandler(); | |
195 | // } | |
196 | ||
197 | // stats | |
198 | 0 | long startTime = 0; |
199 | 0 | if (stat.isEnabled()) |
200 | { | |
201 | 0 | startTime = System.currentTimeMillis(); |
202 | } | |
203 | 0 | returnMessage = invokeUmo(RequestContext.getEventContext()); |
204 | // stats | |
205 | 0 | if (stat.isEnabled()) |
206 | { | |
207 | 0 | stat.addExecutionTime(System.currentTimeMillis() - startTime); |
208 | } | |
209 | // this is the request event | |
210 | 0 | event = RequestContext.getEvent(); |
211 | 0 | if (event.isStopFurtherProcessing()) |
212 | { | |
213 | 0 | logger.debug("Event stop further processing has been set, no outbound routing will be performed."); |
214 | } | |
215 | 0 | if (returnMessage != null && !event.isStopFurtherProcessing()) |
216 | { | |
217 | // Map context = RequestContext.clearProperties(); | |
218 | // if (context != null) { | |
219 | // returnMessage.addProperties(context); | |
220 | // } | |
221 | 0 | if (descriptor.getOutboundRouter().hasEndpoints()) |
222 | { | |
223 | 0 | UMOMessage outboundReturnMessage = descriptor.getOutboundRouter().route( |
224 | returnMessage, event.getSession(), event.isSynchronous()); | |
225 | 0 | if (outboundReturnMessage != null) |
226 | { | |
227 | 0 | returnMessage = outboundReturnMessage; |
228 | } | |
229 | 0 | } |
230 | else | |
231 | { | |
232 | 0 | logger.debug("Outbound router on component '" + descriptor.getName() |
233 | + "' doesn't have any endpoints configured."); | |
234 | } | |
235 | } | |
236 | ||
237 | // Process Response Router | |
238 | // if (returnMessage != null && descriptor.getResponseRouter() != | |
239 | // null) { | |
240 | // logger.debug("Waiting for response router message"); | |
241 | // returnMessage = | |
242 | // descriptor.getResponseRouter().getResponse(returnMessage); | |
243 | // } | |
244 | // | |
245 | // // process repltyTo if there is one | |
246 | // if (returnMessage != null && replyToHandler != null) { | |
247 | // String requestor = (String) | |
248 | // returnMessage.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY); | |
249 | // if ((requestor != null && !requestor.equals(descriptor.getName())) | |
250 | // || requestor == null) { | |
251 | // replyToHandler.processReplyTo(event, returnMessage, replyTo); | |
252 | // } | |
253 | // } | |
254 | ||
255 | 0 | } |
256 | else | |
257 | { | |
258 | 0 | returnMessage = event.getSession().sendEvent(event); |
259 | // processReplyTo(returnMessage); | |
260 | } | |
261 | ||
262 | // stats | |
263 | 0 | if (stat.isEnabled()) |
264 | { | |
265 | 0 | stat.incSentEventSync(); |
266 | } | |
267 | } | |
268 | 0 | catch (Exception e) |
269 | { | |
270 | 0 | event.getSession().setValid(false); |
271 | 0 | if (e instanceof UMOException) |
272 | { | |
273 | 0 | handleException(e); |
274 | } | |
275 | else | |
276 | { | |
277 | 0 | handleException( |
278 | new MessagingException( | |
279 | CoreMessages.eventProcessingFailedFor(descriptor.getName()), | |
280 | event.getMessage(), e)); | |
281 | } | |
282 | 0 | } |
283 | 0 | return returnMessage; |
284 | } | |
285 | ||
286 | protected UMOMessage invokeUmo(UMOEventContext context) throws Exception | |
287 | { | |
288 | 0 | Object result = umo.onCall(RequestContext.getEventContext()); |
289 | 0 | if (result != null) |
290 | { | |
291 | 0 | if (result instanceof UMOMessage) |
292 | { | |
293 | 0 | return (UMOMessage) result; |
294 | } | |
295 | else | |
296 | { | |
297 | 0 | return new MuleMessage(result, context.getMessage()); |
298 | } | |
299 | } | |
300 | 0 | return null; |
301 | } | |
302 | ||
303 | /** | |
304 | * When an exception occurs this method can be called to invoke the configured | |
305 | * UMOExceptionStrategy on the UMO | |
306 | * | |
307 | * @param exception If the UMOExceptionStrategy implementation fails | |
308 | */ | |
309 | public void handleException(Exception exception) | |
310 | { | |
311 | 0 | descriptor.getExceptionListener().exceptionThrown(exception); |
312 | 0 | } |
313 | ||
314 | public String toString() | |
315 | { | |
316 | 0 | return "optimised proxy for: " + descriptor.toString(); |
317 | } | |
318 | ||
319 | /** | |
320 | * Determines if the proxy is suspended | |
321 | * | |
322 | * @return true if the proxy (and the UMO) are suspended | |
323 | */ | |
324 | public boolean isSuspended() | |
325 | { | |
326 | 0 | return suspended; |
327 | } | |
328 | ||
329 | /** | |
330 | * Controls the suspension of the UMO event processing | |
331 | */ | |
332 | public void suspend() | |
333 | { | |
334 | 0 | suspended = true; |
335 | 0 | } |
336 | ||
337 | /** | |
338 | * Triggers the UMO to resume processing of events if it is suspended | |
339 | */ | |
340 | public void resume() | |
341 | { | |
342 | 0 | suspended = false; |
343 | 0 | } |
344 | ||
345 | // private void processReplyTo(UMOMessage returnMessage) throws UMOException | |
346 | // { | |
347 | // if (returnMessage != null && returnMessage.getReplyTo() != null) { | |
348 | // logger.info("sending reply to: " + returnMessage.getReplyTo()); | |
349 | // UMOEndpointURI endpointUri = new | |
350 | // MuleEndpointURI(returnMessage.getReplyTo().toString()); | |
351 | // | |
352 | // // get the endpointUri for this uri | |
353 | // UMOEndpoint endpoint = MuleEndpoint.getOrCreateEndpointForUri(endpointUri, | |
354 | // UMOEndpoint.ENDPOINT_TYPE_SENDER); | |
355 | // | |
356 | // // Create the replyTo event asynchronous | |
357 | // UMOEvent replyToEvent = new MuleEvent(returnMessage, endpoint, | |
358 | // event.getSession(), false); | |
359 | // // make sure remove the replyTo property as not cause a a forever | |
360 | // // replyto loop | |
361 | // replyToEvent.removeProperty(MuleProperties.MULE_REPLY_TO_PROPERTY); | |
362 | // | |
363 | // // queue the event | |
364 | // onEvent(queueSession, replyToEvent); | |
365 | // logger.info("reply to sent: " + returnMessage.getReplyTo()); | |
366 | // if (stat.isEnabled()) { | |
367 | // stat.incSentReplyToEvent(); | |
368 | // } | |
369 | // } | |
370 | // } | |
371 | ||
372 | public void run() | |
373 | { | |
374 | 0 | if (logger.isTraceEnabled()) |
375 | { | |
376 | 0 | logger.trace("MuleProxy: async onEvent for Mule UMO " + descriptor.getName()); |
377 | } | |
378 | ||
379 | try | |
380 | { | |
381 | 0 | if (event.getEndpoint().canReceive()) |
382 | { | |
383 | // dispatch the next receiver | |
384 | 0 | event = RequestContext.setEvent(event); |
385 | // Object replyTo = event.getMessage().getReplyTo(); | |
386 | // ReplyToHandler replyToHandler = null; | |
387 | // if (replyTo != null) { | |
388 | // replyToHandler = ((AbstractConnector) | |
389 | // event.getEndpoint().getConnector()).getReplyToHandler(); | |
390 | // } | |
391 | // InterceptorsInvoker invoker = new | |
392 | // InterceptorsInvoker(interceptorList, descriptor, | |
393 | // event.getMessage()); | |
394 | ||
395 | // do stats | |
396 | 0 | long startTime = 0; |
397 | 0 | if (stat.isEnabled()) |
398 | { | |
399 | 0 | startTime = System.currentTimeMillis(); |
400 | } | |
401 | 0 | UMOMessage result = invokeUmo(RequestContext.getEventContext()); |
402 | 0 | if (stat.isEnabled()) |
403 | { | |
404 | 0 | stat.addExecutionTime(System.currentTimeMillis() - startTime); |
405 | } | |
406 | // processResponse(result, replyTo, replyToHandler); | |
407 | 0 | event = RequestContext.getEvent(); |
408 | 0 | if (result != null && !event.isStopFurtherProcessing()) |
409 | { | |
410 | 0 | descriptor.getOutboundRouter().route(result, event.getSession(), event.isSynchronous()); |
411 | } | |
412 | ||
413 | // process repltyTo if there is one | |
414 | // if (result != null && replyToHandler != null) { | |
415 | // String requestor = (String) | |
416 | // result.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY); | |
417 | // if ((requestor != null && !requestor.equals(descriptor.getName())) | |
418 | // || requestor == null) { | |
419 | // replyToHandler.processReplyTo(event, result, replyTo); | |
420 | // } | |
421 | // } | |
422 | 0 | } |
423 | else | |
424 | { | |
425 | 0 | event.getEndpoint().dispatch(event); |
426 | } | |
427 | ||
428 | 0 | if (stat.isEnabled()) |
429 | { | |
430 | 0 | stat.incSentEventASync(); |
431 | } | |
432 | } | |
433 | 0 | catch (Exception e) |
434 | { | |
435 | 0 | event.getSession().setValid(false); |
436 | 0 | if (e instanceof UMOException) |
437 | { | |
438 | 0 | handleException(e); |
439 | } | |
440 | else | |
441 | { | |
442 | 0 | handleException( |
443 | new MessagingException( | |
444 | CoreMessages.eventProcessingFailedFor(descriptor.getName()), | |
445 | event.getMessage(), e)); | |
446 | } | |
447 | } | |
448 | finally | |
449 | { | |
450 | ||
451 | 0 | try |
452 | { | |
453 | 0 | proxyPool.returnObject(this); |
454 | } | |
455 | 0 | catch (Exception e2) |
456 | { | |
457 | // TODO MULE-863: If this is an error, do something about it | |
458 | 0 | logger.error("Failed to return proxy: " + e2.getMessage(), e2); |
459 | 0 | } |
460 | //TODO RM* clean this up | |
461 | 0 | if (getStatistics() instanceof SedaComponentStatistics) |
462 | { | |
463 | 0 | ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize()); |
464 | } | |
465 | } | |
466 | 0 | } |
467 | ||
468 | public void release() | |
469 | { | |
470 | // nothing to do | |
471 | 0 | } |
472 | ||
473 | public UMOImmutableDescriptor getDescriptor() | |
474 | { | |
475 | 0 | return descriptor; |
476 | } | |
477 | } |