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 protected int queueTimeout = 0;
82
83
84
85
86
87 protected boolean enablePooling = true;
88
89
90
91
92 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 super(descriptor, model);
114
115 descriptorQueueName = descriptor.getName() + ".component";
116 queueTimeout = model.getQueueTimeout();
117 enablePooling = model.isEnablePooling();
118 componentPerRequest = model.isComponentPerRequest();
119 poolingProfile = model.getPoolingProfile();
120 queueProfile = model.getQueueProfile();
121 }
122
123
124
125
126
127
128
129
130
131
132 public synchronized void doInitialise() throws InitialisationException
133 {
134
135 ThreadingProfile tp = descriptor.getThreadingProfile();
136 workManager = tp.createWorkManager(descriptor.getName());
137
138 queueProfile = descriptor.getQueueProfile();
139 if (queueProfile == null)
140 {
141 queueProfile = ((SedaModel) model).getQueueProfile();
142 }
143
144 poolingProfile = descriptor.getPoolingProfile();
145 if (poolingProfile == null)
146 {
147 poolingProfile = ((SedaModel) model).getPoolingProfile();
148 }
149
150 try
151 {
152
153 queueProfile.configureQueue(descriptorQueueName);
154 }
155 catch (InitialisationException e)
156 {
157 throw e;
158 }
159 catch (Throwable e)
160 {
161 throw new InitialisationException(
162 CoreMessages.objectFailedToInitialise("Component Queue"), e, this);
163 }
164 }
165
166 protected ComponentStatistics createStatistics()
167 {
168 return new SedaComponentStatistics(getName(), descriptor.getThreadingProfile().getMaxThreadsActive(),
169 poolingProfile.getMaxActive());
170 }
171
172 protected ObjectPool createPool() throws InitialisationException
173 {
174 return getPoolingProfile().getPoolFactory().createPool(descriptor, model,
175 getPoolingProfile());
176 }
177
178 protected void initialisePool() throws InitialisationException
179 {
180 try
181 {
182 int initPolicy = getPoolingProfile().getInitialisationPolicy();
183 if (initPolicy == PoolingProfile.INITIALISE_ALL)
184 {
185 int numToBorrow = getPoolingProfile().getMaxActive();
186 List holderList = new ArrayList(numToBorrow);
187
188 try
189 {
190 for (int t = 0; t < numToBorrow; t++)
191 {
192 holderList.add(proxyPool.borrowObject());
193 }
194 }
195 finally
196 {
197 for (int t = 0; t < holderList.size(); t++)
198 {
199 Object obj = holderList.get(t);
200 if (obj != null)
201 {
202 try
203 {
204 proxyPool.returnObject(obj);
205 }
206 finally
207 {
208
209 }
210 }
211 }
212 }
213 }
214 else if (initPolicy == PoolingProfile.INITIALISE_ONE)
215 {
216 Object obj = null;
217 try
218 {
219 obj = proxyPool.borrowObject();
220 }
221 finally
222 {
223 if (obj != null)
224 {
225 proxyPool.returnObject(obj);
226 }
227 }
228 }
229
230 poolInitialised.set(true);
231 }
232 catch (Exception e)
233 {
234 throw new InitialisationException(
235 CoreMessages.objectFailedToInitialise("Proxy Pool"), e, this);
236 }
237 }
238
239 protected MuleProxy createComponentProxy() throws InitialisationException
240 {
241 try
242 {
243 Object component = lookupComponent();
244 MuleProxy componentProxy = new DefaultMuleProxy(component, descriptor, model);
245 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(-1);
246 componentProxy.setStatistics(getStatistics());
247 componentProxy.start();
248 return componentProxy;
249 }
250 catch (UMOException e)
251 {
252 throw new InitialisationException(e, this);
253 }
254 }
255
256 public void doForceStop() throws UMOException
257 {
258 doStop();
259 }
260
261 public void doStop() throws UMOException
262 {
263 if (MuleManager.getInstance().getQueueManager().getQueueSession().getQueue(
264 descriptor.getName() + ".component").size() > 0)
265 {
266 try
267 {
268 stopping.whenFalse(null);
269 }
270 catch (InterruptedException e)
271 {
272
273
274 }
275 }
276 workManager.stop();
277 if (proxyPool != null)
278 {
279 try
280 {
281 proxyPool.stop();
282 proxyPool.clearPool();
283 }
284 catch (Exception e)
285 {
286
287 logger.error("Failed to stop component pool: " + e.getMessage(), e);
288 }
289 poolInitialised.set(false);
290 }
291 else if (componentProxy != null)
292 {
293 componentProxy.stop();
294 }
295 }
296
297 public void doStart() throws UMOException
298 {
299
300 try
301 {
302
303
304 if (!poolInitialised.get() && enablePooling)
305 {
306 proxyPool = this.createPool();
307 this.initialisePool();
308 proxyPool.start();
309 }
310 else if (!componentPerRequest)
311 {
312 componentProxy = createComponentProxy();
313 }
314 workManager.start();
315 workManager.scheduleWork(this, WorkManager.INDEFINITE, null, this);
316 }
317 catch (Exception e)
318 {
319 throw new LifecycleException(
320 CoreMessages.failedToStart("Component: " + descriptor.getName()), e, this);
321 }
322 }
323
324 protected void doDispose()
325 {
326
327 try
328 {
329
330 if (workManager != null)
331 {
332 workManager.dispose();
333 }
334 }
335 catch (Exception e)
336 {
337
338 logger.error("Component Thread Pool did not close properly: " + e);
339 }
340 try
341 {
342 if (proxyPool != null)
343 {
344 proxyPool.clearPool();
345 }
346 else if (componentProxy != null)
347 {
348 componentProxy.dispose();
349 }
350 }
351 catch (Exception e)
352 {
353
354 logger.error("Proxy Pool did not close properly: " + e);
355 }
356 }
357
358 protected void doDispatch(UMOEvent event) throws UMOException
359 {
360
361 if (stats.isEnabled())
362 {
363 stats.incReceivedEventASync();
364 }
365 if (logger.isDebugEnabled())
366 {
367 logger.debug("Component: " + descriptor.getName() + " has received asynchronous event on: "
368 + event.getEndpoint().getEndpointURI());
369 }
370
371
372 try
373 {
374 enqueue(event);
375 if (stats.isEnabled())
376 {
377 stats.incQueuedEvent();
378 }
379 }
380 catch (Exception e)
381 {
382 FailedToQueueEventException e1 =
383 new FailedToQueueEventException(
384 CoreMessages.interruptedQueuingEventFor(this.getName()),
385 event.getMessage(), this, e);
386 handleException(e1);
387 }
388
389 if (logger.isTraceEnabled())
390 {
391 logger.trace("Event added to queue for: " + descriptor.getName());
392 }
393 }
394
395 public UMOMessage doSend(UMOEvent event) throws UMOException
396 {
397 UMOMessage result = null;
398 MuleProxy proxy = null;
399 try
400 {
401 proxy = getProxy();
402 if (logger.isDebugEnabled())
403 {
404 logger.debug(this + " : got proxy for " + event.getId() + " = " + proxy);
405 }
406 result = (UMOMessage) proxy.onCall(event);
407 }
408 catch (UMOException e)
409 {
410 throw e;
411 }
412 catch (Exception e)
413 {
414 throw new ComponentException(event.getMessage(), this, e);
415 }
416
417 finally
418 {
419 releaseProxy(proxy);
420 }
421 return result;
422 }
423
424
425
426
427 ObjectPool getProxyPool()
428 {
429 return proxyPool;
430 }
431
432 public int getQueueSize()
433 {
434 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
435 return queueSession.getQueue(descriptor.getName()).size();
436 }
437
438
439
440
441
442 public void run()
443 {
444 MuleEvent event = null;
445 MuleProxy proxy = null;
446 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
447
448 while (!stopped.get())
449 {
450 try
451 {
452
453 paused.whenFalse(null);
454
455
456
457 if (stopping.get())
458 {
459 if (queueSession == null || queueSession.getQueue(descriptorQueueName).size() == 0)
460 {
461 stopping.set(false);
462 break;
463 }
464 }
465
466 event = (MuleEvent) dequeue();
467 if (event != null)
468 {
469 if (stats.isEnabled())
470 {
471 stats.decQueuedEvent();
472 }
473
474 if (logger.isDebugEnabled())
475 {
476 logger.debug("Component: " + descriptor.getName() + " dequeued event on: "
477 + event.getEndpoint().getEndpointURI());
478 }
479
480 proxy = getProxy();
481 proxy.start();
482 proxy.onEvent(queueSession, event);
483 workManager.scheduleWork(proxy, WorkManager.INDEFINITE, null, this);
484 }
485 }
486 catch (Exception e)
487 {
488
489
490 releaseProxy(proxy);
491
492 if (e instanceof InterruptedException)
493 {
494 stopping.set(false);
495 break;
496 }
497 else if (e instanceof NoSuchElementException)
498 {
499 handleException(new ComponentException(CoreMessages.proxyPoolTimedOut(),
500 (event == null ? null : event.getMessage()), this, e));
501 }
502 else if (e instanceof UMOException)
503 {
504 handleException(e);
505 }
506 else if (e instanceof WorkException)
507 {
508 handleException(
509 new ComponentException(
510 CoreMessages.eventProcessingFailedFor(descriptor.getName()),
511 (event == null ? null : event.getMessage()), this, e));
512 }
513 else
514 {
515 handleException(
516 new ComponentException(
517 CoreMessages.failedToGetPooledObject(),
518 (event == null ? null : event.getMessage()), this, e));
519 }
520 }
521 finally
522 {
523 stopping.set(false);
524
525
526
527
528
529
530
531
532 }
533 }
534 }
535
536
537
538
539 protected MuleProxy getProxy() throws Exception
540 {
541 MuleProxy proxy;
542 if (proxyPool != null)
543 {
544 proxy = (MuleProxy) proxyPool.borrowObject();
545 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
546 }
547 else if (componentPerRequest)
548 {
549 proxy = createComponentProxy();
550 }
551 else
552 {
553 proxy = componentProxy;
554 }
555 proxy.setStatistics(getStatistics());
556 return proxy;
557 }
558
559 public void release()
560 {
561 stopping.set(false);
562 }
563
564 protected void enqueue(UMOEvent event) throws Exception
565 {
566 QueueSession session = MuleManager.getInstance().getQueueManager().getQueueSession();
567 session.getQueue(descriptorQueueName).put(event);
568 }
569
570 protected UMOEvent dequeue() throws Exception
571 {
572
573 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
574 return (UMOEvent) queueSession.getQueue(descriptorQueueName).poll(queueTimeout);
575 }
576
577 public void workAccepted(WorkEvent event)
578 {
579 handleWorkException(event, "workAccepted");
580 }
581
582
583
584
585
586
587
588 public void workRejected(WorkEvent event)
589 {
590 handleWorkException(event, "workRejected");
591
592 if (event.getWork() instanceof MuleProxy)
593 {
594 releaseProxy((MuleProxy) event.getWork());
595 }
596 }
597
598 public void workStarted(WorkEvent event)
599 {
600 handleWorkException(event, "workStarted");
601 }
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618 public void workCompleted(WorkEvent event)
619 {
620 handleWorkException(event, "workCompleted");
621
622 if (event.getWork() instanceof MuleProxy)
623 {
624 releaseProxy((MuleProxy) event.getWork());
625 }
626 }
627
628 protected void handleWorkException(WorkEvent event, String type)
629 {
630 Throwable e;
631
632 if (event != null && event.getException() != null)
633 {
634 e = event.getException();
635 }
636 else
637 {
638 return;
639 }
640
641 if (event.getException().getCause() != null)
642 {
643 e = event.getException().getCause();
644 }
645
646 logger.error("Work caused exception on '" + type + "'. Work being executed was: "
647 + event.getWork().toString());
648
649 if (e instanceof Exception)
650 {
651 handleException((Exception) e);
652 }
653 else
654 {
655 throw new MuleRuntimeException(
656 CoreMessages.componentCausedErrorIs(this.getName()), e);
657 }
658 }
659
660 public PoolingProfile getPoolingProfile()
661 {
662 return poolingProfile;
663 }
664
665 public void setPoolingProfile(PoolingProfile poolingProfile)
666 {
667 this.poolingProfile = poolingProfile;
668 }
669
670 public QueueProfile getQueueProfile()
671 {
672 return queueProfile;
673 }
674
675 public void setQueueProfile(QueueProfile queueProfile)
676 {
677 this.queueProfile = queueProfile;
678 }
679
680
681
682
683
684
685
686
687
688
689
690
691 private void releaseProxy(MuleProxy proxy)
692 {
693 if (proxy == null)
694 {
695 return;
696 }
697
698 try
699 {
700 doReleaseProxy(proxy);
701 }
702 catch (Exception ex)
703 {
704 handleException(ex);
705 }
706
707 }
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724 protected void doReleaseProxy(MuleProxy proxy) throws Exception
725 {
726 assert (proxy != null);
727
728 if (proxyPool != null)
729 {
730 proxyPool.returnObject(proxy);
731 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
732 }
733 else if (componentPerRequest)
734 {
735 proxy.dispose();
736 }
737
738 }
739 }