1 | |
|
2 | |
|
3 | |
|
4 | |
|
5 | |
|
6 | |
|
7 | |
|
8 | |
|
9 | |
|
10 | |
|
11 | |
package org.mule.impl.model.seda; |
12 | |
|
13 | |
import org.mule.MuleManager; |
14 | |
import org.mule.MuleRuntimeException; |
15 | |
import org.mule.config.PoolingProfile; |
16 | |
import org.mule.config.QueueProfile; |
17 | |
import org.mule.config.ThreadingProfile; |
18 | |
import org.mule.config.i18n.CoreMessages; |
19 | |
import org.mule.impl.FailedToQueueEventException; |
20 | |
import org.mule.impl.MuleDescriptor; |
21 | |
import org.mule.impl.MuleEvent; |
22 | |
import org.mule.impl.model.AbstractComponent; |
23 | |
import org.mule.impl.model.DefaultMuleProxy; |
24 | |
import org.mule.impl.model.MuleProxy; |
25 | |
import org.mule.management.stats.ComponentStatistics; |
26 | |
import org.mule.management.stats.SedaComponentStatistics; |
27 | |
import org.mule.umo.ComponentException; |
28 | |
import org.mule.umo.UMOEvent; |
29 | |
import org.mule.umo.UMOException; |
30 | |
import org.mule.umo.UMOMessage; |
31 | |
import org.mule.umo.lifecycle.InitialisationException; |
32 | |
import org.mule.umo.lifecycle.LifecycleException; |
33 | |
import org.mule.umo.manager.UMOWorkManager; |
34 | |
import org.mule.util.ObjectPool; |
35 | |
import org.mule.util.queue.QueueSession; |
36 | |
|
37 | |
import java.util.ArrayList; |
38 | |
import java.util.List; |
39 | |
import java.util.NoSuchElementException; |
40 | |
|
41 | |
import javax.resource.spi.work.Work; |
42 | |
import javax.resource.spi.work.WorkEvent; |
43 | |
import javax.resource.spi.work.WorkException; |
44 | |
import javax.resource.spi.work.WorkListener; |
45 | |
import javax.resource.spi.work.WorkManager; |
46 | |
|
47 | |
|
48 | |
|
49 | |
|
50 | |
|
51 | |
|
52 | |
public class SedaComponent extends AbstractComponent implements Work, WorkListener |
53 | |
{ |
54 | |
public static final String QUEUE_PROFILE_PROPERTY = "queueProfile"; |
55 | |
public static final String POOLING_PROFILE_PROPERTY = "poolingProfile"; |
56 | |
|
57 | |
|
58 | |
|
59 | |
private static final long serialVersionUID = 7711976708670893015L; |
60 | |
|
61 | |
|
62 | |
|
63 | |
|
64 | |
|
65 | |
protected ObjectPool proxyPool; |
66 | |
|
67 | |
|
68 | |
|
69 | |
|
70 | |
|
71 | |
|
72 | |
protected MuleProxy componentProxy; |
73 | |
|
74 | |
protected UMOWorkManager workManager; |
75 | |
|
76 | |
protected String descriptorQueueName; |
77 | |
|
78 | |
|
79 | |
|
80 | |
|
81 | 0 | protected int queueTimeout = 0; |
82 | |
|
83 | |
|
84 | |
|
85 | |
|
86 | |
|
87 | 0 | protected boolean enablePooling = true; |
88 | |
|
89 | |
|
90 | |
|
91 | |
|
92 | 0 | protected boolean componentPerRequest = false; |
93 | |
|
94 | |
|
95 | |
|
96 | |
|
97 | |
|
98 | |
protected PoolingProfile poolingProfile; |
99 | |
|
100 | |
|
101 | |
|
102 | |
|
103 | |
protected QueueProfile queueProfile; |
104 | |
|
105 | |
|
106 | |
|
107 | |
|
108 | |
|
109 | |
|
110 | |
|
111 | |
public SedaComponent(MuleDescriptor descriptor, SedaModel model) |
112 | |
{ |
113 | 0 | super(descriptor, model); |
114 | |
|
115 | 0 | descriptorQueueName = descriptor.getName() + ".component"; |
116 | 0 | queueTimeout = model.getQueueTimeout(); |
117 | 0 | enablePooling = model.isEnablePooling(); |
118 | 0 | componentPerRequest = model.isComponentPerRequest(); |
119 | 0 | poolingProfile = model.getPoolingProfile(); |
120 | 0 | queueProfile = model.getQueueProfile(); |
121 | 0 | } |
122 | |
|
123 | |
|
124 | |
|
125 | |
|
126 | |
|
127 | |
|
128 | |
|
129 | |
|
130 | |
|
131 | |
|
132 | |
public synchronized void doInitialise() throws InitialisationException |
133 | |
{ |
134 | |
|
135 | 0 | ThreadingProfile tp = descriptor.getThreadingProfile(); |
136 | 0 | workManager = tp.createWorkManager(descriptor.getName()); |
137 | |
|
138 | 0 | queueProfile = descriptor.getQueueProfile(); |
139 | 0 | if (queueProfile == null) |
140 | |
{ |
141 | 0 | queueProfile = ((SedaModel) model).getQueueProfile(); |
142 | |
} |
143 | |
|
144 | 0 | poolingProfile = descriptor.getPoolingProfile(); |
145 | 0 | if (poolingProfile == null) |
146 | |
{ |
147 | 0 | poolingProfile = ((SedaModel) model).getPoolingProfile(); |
148 | |
} |
149 | |
|
150 | |
try |
151 | |
{ |
152 | |
|
153 | 0 | queueProfile.configureQueue(descriptor.getName()); |
154 | |
} |
155 | 0 | catch (InitialisationException e) |
156 | |
{ |
157 | 0 | throw e; |
158 | |
} |
159 | 0 | catch (Throwable e) |
160 | |
{ |
161 | 0 | throw new InitialisationException( |
162 | |
CoreMessages.objectFailedToInitialise("Component Queue"), e, this); |
163 | 0 | } |
164 | 0 | } |
165 | |
|
166 | |
protected ComponentStatistics createStatistics() |
167 | |
{ |
168 | 0 | return new SedaComponentStatistics(getName(), descriptor.getThreadingProfile().getMaxThreadsActive(), |
169 | |
poolingProfile.getMaxActive()); |
170 | |
} |
171 | |
|
172 | |
protected ObjectPool createPool() throws InitialisationException |
173 | |
{ |
174 | 0 | return getPoolingProfile().getPoolFactory().createPool(descriptor, model, |
175 | |
getPoolingProfile()); |
176 | |
} |
177 | |
|
178 | |
protected void initialisePool() throws InitialisationException |
179 | |
{ |
180 | |
try |
181 | |
{ |
182 | 0 | int initPolicy = getPoolingProfile().getInitialisationPolicy(); |
183 | 0 | if (initPolicy == PoolingProfile.INITIALISE_ALL) |
184 | |
{ |
185 | 0 | int numToBorrow = getPoolingProfile().getMaxActive(); |
186 | 0 | List holderList = new ArrayList(numToBorrow); |
187 | |
|
188 | |
try |
189 | |
{ |
190 | 0 | for (int t = 0; t < numToBorrow; t++) |
191 | |
{ |
192 | 0 | holderList.add(proxyPool.borrowObject()); |
193 | |
} |
194 | 0 | } |
195 | |
finally |
196 | |
{ |
197 | 0 | for (int t = 0; t < holderList.size(); t++) |
198 | |
{ |
199 | 0 | Object obj = holderList.get(t); |
200 | 0 | if (obj != null) |
201 | |
{ |
202 | |
try |
203 | |
{ |
204 | 0 | proxyPool.returnObject(obj); |
205 | |
} |
206 | |
finally |
207 | 0 | { |
208 | |
|
209 | 0 | } |
210 | |
} |
211 | |
} |
212 | 0 | } |
213 | |
} |
214 | 0 | else if (initPolicy == PoolingProfile.INITIALISE_ONE) |
215 | |
{ |
216 | 0 | Object obj = null; |
217 | |
try |
218 | |
{ |
219 | 0 | obj = proxyPool.borrowObject(); |
220 | 0 | } |
221 | |
finally |
222 | |
{ |
223 | 0 | if (obj != null) |
224 | |
{ |
225 | 0 | proxyPool.returnObject(obj); |
226 | |
} |
227 | 0 | } |
228 | |
} |
229 | |
|
230 | 0 | poolInitialised.set(true); |
231 | |
} |
232 | 0 | catch (Exception e) |
233 | |
{ |
234 | 0 | throw new InitialisationException( |
235 | |
CoreMessages.objectFailedToInitialise("Proxy Pool"), e, this); |
236 | 0 | } |
237 | 0 | } |
238 | |
|
239 | |
protected MuleProxy createComponentProxy() throws InitialisationException |
240 | |
{ |
241 | |
try |
242 | |
{ |
243 | 0 | Object component = lookupComponent(); |
244 | 0 | MuleProxy componentProxy = new DefaultMuleProxy(component, descriptor, model, null); |
245 | 0 | ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(-1); |
246 | 0 | componentProxy.setStatistics(getStatistics()); |
247 | 0 | componentProxy.start(); |
248 | 0 | return componentProxy; |
249 | |
} |
250 | 0 | catch (UMOException e) |
251 | |
{ |
252 | 0 | throw new InitialisationException(e, this); |
253 | |
} |
254 | |
} |
255 | |
|
256 | |
public void doForceStop() throws UMOException |
257 | |
{ |
258 | 0 | doStop(); |
259 | 0 | } |
260 | |
|
261 | |
public void doStop() throws UMOException |
262 | |
{ |
263 | 0 | workManager.stop(); |
264 | 0 | if (proxyPool != null) |
265 | |
{ |
266 | |
try |
267 | |
{ |
268 | 0 | proxyPool.stop(); |
269 | 0 | proxyPool.clearPool(); |
270 | |
} |
271 | 0 | catch (Exception e) |
272 | |
{ |
273 | |
|
274 | 0 | logger.error("Failed to stop component pool: " + e.getMessage(), e); |
275 | 0 | } |
276 | 0 | poolInitialised.set(false); |
277 | |
} |
278 | 0 | else if (componentProxy != null) |
279 | |
{ |
280 | 0 | componentProxy.stop(); |
281 | |
} |
282 | 0 | } |
283 | |
|
284 | |
public void doStart() throws UMOException |
285 | |
{ |
286 | |
|
287 | |
try |
288 | |
{ |
289 | |
|
290 | |
|
291 | 0 | if (!poolInitialised.get() && enablePooling) |
292 | |
{ |
293 | 0 | proxyPool = this.createPool(); |
294 | 0 | this.initialisePool(); |
295 | 0 | proxyPool.start(); |
296 | |
} |
297 | 0 | else if (!componentPerRequest) |
298 | |
{ |
299 | 0 | componentProxy = createComponentProxy(); |
300 | |
} |
301 | 0 | workManager.start(); |
302 | 0 | workManager.scheduleWork(this, WorkManager.INDEFINITE, null, this); |
303 | |
} |
304 | 0 | catch (Exception e) |
305 | |
{ |
306 | 0 | throw new LifecycleException( |
307 | |
CoreMessages.failedToStart("Component: " + descriptor.getName()), e, this); |
308 | 0 | } |
309 | 0 | } |
310 | |
|
311 | |
protected void doDispose() |
312 | |
{ |
313 | |
|
314 | |
try |
315 | |
{ |
316 | |
|
317 | 0 | if (workManager != null) |
318 | |
{ |
319 | 0 | workManager.dispose(); |
320 | |
} |
321 | |
} |
322 | 0 | catch (Exception e) |
323 | |
{ |
324 | |
|
325 | 0 | logger.error("Component Thread Pool did not close properly: " + e); |
326 | 0 | } |
327 | |
try |
328 | |
{ |
329 | 0 | if (proxyPool != null) |
330 | |
{ |
331 | 0 | proxyPool.clearPool(); |
332 | |
} |
333 | 0 | else if (componentProxy != null) |
334 | |
{ |
335 | 0 | componentProxy.dispose(); |
336 | |
} |
337 | |
} |
338 | 0 | catch (Exception e) |
339 | |
{ |
340 | |
|
341 | 0 | logger.error("Proxy Pool did not close properly: " + e); |
342 | 0 | } |
343 | 0 | } |
344 | |
|
345 | |
protected void doDispatch(UMOEvent event) throws UMOException |
346 | |
{ |
347 | |
|
348 | 0 | if (stats.isEnabled()) |
349 | |
{ |
350 | 0 | stats.incReceivedEventASync(); |
351 | |
} |
352 | 0 | if (logger.isDebugEnabled()) |
353 | |
{ |
354 | 0 | logger.debug("Component: " + descriptor.getName() + " has received asynchronous event on: " |
355 | |
+ event.getEndpoint().getEndpointURI()); |
356 | |
} |
357 | |
|
358 | |
|
359 | |
try |
360 | |
{ |
361 | 0 | enqueue(event); |
362 | 0 | if (stats.isEnabled()) |
363 | |
{ |
364 | 0 | stats.incQueuedEvent(); |
365 | |
} |
366 | |
} |
367 | 0 | catch (Exception e) |
368 | |
{ |
369 | 0 | FailedToQueueEventException e1 = |
370 | |
new FailedToQueueEventException( |
371 | |
CoreMessages.interruptedQueuingEventFor(this.getName()), |
372 | |
event.getMessage(), this, e); |
373 | 0 | handleException(e1); |
374 | 0 | } |
375 | |
|
376 | 0 | if (logger.isTraceEnabled()) |
377 | |
{ |
378 | 0 | logger.trace("Event added to queue for: " + descriptor.getName()); |
379 | |
} |
380 | 0 | } |
381 | |
|
382 | |
public UMOMessage doSend(UMOEvent event) throws UMOException |
383 | |
{ |
384 | 0 | UMOMessage result = null; |
385 | 0 | MuleProxy proxy = null; |
386 | |
try |
387 | |
{ |
388 | 0 | proxy = getProxy(); |
389 | 0 | if (logger.isDebugEnabled()) |
390 | |
{ |
391 | 0 | logger.debug(this + " : got proxy for " + event.getId() + " = " + proxy); |
392 | |
} |
393 | 0 | result = (UMOMessage) proxy.onCall(event); |
394 | 0 | } |
395 | 0 | catch (UMOException e) |
396 | |
{ |
397 | 0 | throw e; |
398 | |
} |
399 | 0 | catch (Exception e) |
400 | |
{ |
401 | 0 | throw new ComponentException(event.getMessage(), this, e); |
402 | |
} |
403 | |
finally |
404 | |
{ |
405 | 0 | try |
406 | |
{ |
407 | 0 | if (proxy != null) |
408 | |
{ |
409 | 0 | if (proxyPool != null) |
410 | |
{ |
411 | 0 | proxyPool.returnObject(proxy); |
412 | |
} |
413 | 0 | else if (componentPerRequest) |
414 | |
{ |
415 | 0 | proxy.dispose(); |
416 | |
} |
417 | |
} |
418 | |
} |
419 | 0 | catch (Exception e) |
420 | |
{ |
421 | |
|
422 | 0 | throw new ComponentException(event.getMessage(), this, e); |
423 | 0 | } |
424 | |
|
425 | 0 | if (proxyPool != null) |
426 | |
{ |
427 | 0 | ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize()); |
428 | |
} |
429 | 0 | } |
430 | 0 | return result; |
431 | |
} |
432 | |
|
433 | |
|
434 | |
|
435 | |
|
436 | |
ObjectPool getProxyPool() |
437 | |
{ |
438 | 0 | return proxyPool; |
439 | |
} |
440 | |
|
441 | |
public int getQueueSize() |
442 | |
{ |
443 | 0 | QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession(); |
444 | 0 | return queueSession.getQueue(descriptor.getName()).size(); |
445 | |
} |
446 | |
|
447 | |
|
448 | |
|
449 | |
|
450 | |
|
451 | |
public void run() |
452 | |
{ |
453 | 0 | MuleEvent event = null; |
454 | 0 | MuleProxy proxy = null; |
455 | 0 | QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession(); |
456 | |
|
457 | 0 | while (!stopped.get()) |
458 | |
{ |
459 | |
try |
460 | |
{ |
461 | |
|
462 | 0 | paused.whenFalse(null); |
463 | |
|
464 | |
|
465 | |
|
466 | 0 | if (stopping.get()) |
467 | |
{ |
468 | 0 | if (queueSession == null || queueSession.getQueue(descriptorQueueName).size() == 0) |
469 | |
{ |
470 | 0 | stopping.set(false); |
471 | 0 | break; |
472 | |
} |
473 | |
} |
474 | |
|
475 | 0 | event = (MuleEvent) dequeue(); |
476 | 0 | if (event != null) |
477 | |
{ |
478 | 0 | if (stats.isEnabled()) |
479 | |
{ |
480 | 0 | stats.decQueuedEvent(); |
481 | |
} |
482 | |
|
483 | 0 | if (logger.isDebugEnabled()) |
484 | |
{ |
485 | 0 | logger.debug("Component: " + descriptor.getName() + " dequeued event on: " |
486 | |
+ event.getEndpoint().getEndpointURI()); |
487 | |
} |
488 | |
|
489 | 0 | proxy = getProxy(); |
490 | 0 | proxy.start(); |
491 | 0 | proxy.onEvent(queueSession, event); |
492 | 0 | workManager.scheduleWork(proxy, WorkManager.INDEFINITE, null, this); |
493 | |
} |
494 | 0 | } |
495 | 0 | catch (Exception e) |
496 | |
{ |
497 | 0 | if (proxy != null && proxyPool != null) |
498 | |
{ |
499 | |
try |
500 | |
{ |
501 | 0 | proxyPool.returnObject(proxy); |
502 | |
} |
503 | 0 | catch (Exception e2) |
504 | |
{ |
505 | |
|
506 | 0 | logger.info("Failed to return proxy to pool", e2); |
507 | 0 | } |
508 | |
} |
509 | |
|
510 | 0 | if (e instanceof InterruptedException) |
511 | |
{ |
512 | 0 | stopping.set(false); |
513 | 0 | break; |
514 | |
} |
515 | 0 | else if (e instanceof NoSuchElementException) |
516 | |
{ |
517 | 0 | handleException(new ComponentException(CoreMessages.proxyPoolTimedOut(), |
518 | |
(event == null ? null : event.getMessage()), this, e)); |
519 | |
} |
520 | 0 | else if (e instanceof UMOException) |
521 | |
{ |
522 | 0 | handleException(e); |
523 | |
} |
524 | 0 | else if (e instanceof WorkException) |
525 | |
{ |
526 | 0 | handleException( |
527 | |
new ComponentException( |
528 | |
CoreMessages.eventProcessingFailedFor(descriptor.getName()), |
529 | |
(event == null ? null : event.getMessage()), this, e)); |
530 | |
} |
531 | |
else |
532 | |
{ |
533 | 0 | handleException( |
534 | |
new ComponentException( |
535 | |
CoreMessages.failedToGetPooledObject(), |
536 | |
(event == null ? null : event.getMessage()), this, e)); |
537 | |
} |
538 | 0 | } |
539 | |
finally |
540 | |
{ |
541 | 0 | stopping.set(false); |
542 | 0 | if (proxy != null && componentPerRequest) |
543 | |
{ |
544 | 0 | proxy.dispose(); |
545 | |
} |
546 | 0 | } |
547 | |
} |
548 | 0 | } |
549 | |
|
550 | |
|
551 | |
|
552 | |
|
553 | |
protected MuleProxy getProxy() throws Exception |
554 | |
{ |
555 | |
MuleProxy proxy; |
556 | 0 | if (proxyPool != null) |
557 | |
{ |
558 | 0 | proxy = (MuleProxy) proxyPool.borrowObject(); |
559 | 0 | ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize()); |
560 | |
} |
561 | 0 | else if (componentPerRequest) |
562 | |
{ |
563 | 0 | proxy = createComponentProxy(); |
564 | |
} |
565 | |
else |
566 | |
{ |
567 | 0 | proxy = componentProxy; |
568 | |
} |
569 | 0 | proxy.setStatistics(getStatistics()); |
570 | 0 | return proxy; |
571 | |
} |
572 | |
|
573 | |
public void release() |
574 | |
{ |
575 | 0 | stopping.set(false); |
576 | 0 | } |
577 | |
|
578 | |
protected void enqueue(UMOEvent event) throws Exception |
579 | |
{ |
580 | 0 | QueueSession session = MuleManager.getInstance().getQueueManager().getQueueSession(); |
581 | 0 | session.getQueue(descriptorQueueName).put(event); |
582 | 0 | } |
583 | |
|
584 | |
protected UMOEvent dequeue() throws Exception |
585 | |
{ |
586 | |
|
587 | 0 | QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession(); |
588 | 0 | return (UMOEvent) queueSession.getQueue(descriptorQueueName).poll(queueTimeout); |
589 | |
} |
590 | |
|
591 | |
public void workAccepted(WorkEvent event) |
592 | |
{ |
593 | 0 | handleWorkException(event, "workAccepted"); |
594 | 0 | } |
595 | |
|
596 | |
public void workRejected(WorkEvent event) |
597 | |
{ |
598 | 0 | handleWorkException(event, "workRejected"); |
599 | 0 | } |
600 | |
|
601 | |
public void workStarted(WorkEvent event) |
602 | |
{ |
603 | 0 | handleWorkException(event, "workStarted"); |
604 | 0 | } |
605 | |
|
606 | |
public void workCompleted(WorkEvent event) |
607 | |
{ |
608 | 0 | handleWorkException(event, "workCompleted"); |
609 | 0 | } |
610 | |
|
611 | |
protected void handleWorkException(WorkEvent event, String type) |
612 | |
{ |
613 | |
Throwable e; |
614 | |
|
615 | 0 | if (event != null && event.getException() != null) |
616 | |
{ |
617 | 0 | e = event.getException(); |
618 | |
} |
619 | |
else |
620 | |
{ |
621 | 0 | return; |
622 | |
} |
623 | |
|
624 | 0 | if (event.getException().getCause() != null) |
625 | |
{ |
626 | 0 | e = event.getException().getCause(); |
627 | |
} |
628 | |
|
629 | 0 | logger.error("Work caused exception on '" + type + "'. Work being executed was: " |
630 | |
+ event.getWork().toString()); |
631 | |
|
632 | 0 | if (e instanceof Exception) |
633 | |
{ |
634 | 0 | handleException((Exception) e); |
635 | |
} |
636 | |
else |
637 | |
{ |
638 | 0 | throw new MuleRuntimeException( |
639 | |
CoreMessages.componentCausedErrorIs(this.getName()), e); |
640 | |
} |
641 | 0 | } |
642 | |
|
643 | |
public PoolingProfile getPoolingProfile() |
644 | |
{ |
645 | 0 | return poolingProfile; |
646 | |
} |
647 | |
|
648 | |
public void setPoolingProfile(PoolingProfile poolingProfile) |
649 | |
{ |
650 | 0 | this.poolingProfile = poolingProfile; |
651 | 0 | } |
652 | |
|
653 | |
public QueueProfile getQueueProfile() |
654 | |
{ |
655 | 0 | return queueProfile; |
656 | |
} |
657 | |
|
658 | |
public void setQueueProfile(QueueProfile queueProfile) |
659 | |
{ |
660 | 0 | this.queueProfile = queueProfile; |
661 | 0 | } |
662 | |
} |