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(descriptor.getName());
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, null);
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 workManager.stop();
264 if (proxyPool != null)
265 {
266 try
267 {
268 proxyPool.stop();
269 proxyPool.clearPool();
270 }
271 catch (Exception e)
272 {
273
274 logger.error("Failed to stop component pool: " + e.getMessage(), e);
275 }
276 poolInitialised.set(false);
277 }
278 else if (componentProxy != null)
279 {
280 componentProxy.stop();
281 }
282 }
283
284 public void doStart() throws UMOException
285 {
286
287 try
288 {
289
290
291 if (!poolInitialised.get() && enablePooling)
292 {
293 proxyPool = this.createPool();
294 this.initialisePool();
295 proxyPool.start();
296 }
297 else if (!componentPerRequest)
298 {
299 componentProxy = createComponentProxy();
300 }
301 workManager.start();
302 workManager.scheduleWork(this, WorkManager.INDEFINITE, null, this);
303 }
304 catch (Exception e)
305 {
306 throw new LifecycleException(
307 CoreMessages.failedToStart("Component: " + descriptor.getName()), e, this);
308 }
309 }
310
311 protected void doDispose()
312 {
313
314 try
315 {
316
317 if (workManager != null)
318 {
319 workManager.dispose();
320 }
321 }
322 catch (Exception e)
323 {
324
325 logger.error("Component Thread Pool did not close properly: " + e);
326 }
327 try
328 {
329 if (proxyPool != null)
330 {
331 proxyPool.clearPool();
332 }
333 else if (componentProxy != null)
334 {
335 componentProxy.dispose();
336 }
337 }
338 catch (Exception e)
339 {
340
341 logger.error("Proxy Pool did not close properly: " + e);
342 }
343 }
344
345 protected void doDispatch(UMOEvent event) throws UMOException
346 {
347
348 if (stats.isEnabled())
349 {
350 stats.incReceivedEventASync();
351 }
352 if (logger.isDebugEnabled())
353 {
354 logger.debug("Component: " + descriptor.getName() + " has received asynchronous event on: "
355 + event.getEndpoint().getEndpointURI());
356 }
357
358
359 try
360 {
361 enqueue(event);
362 if (stats.isEnabled())
363 {
364 stats.incQueuedEvent();
365 }
366 }
367 catch (Exception e)
368 {
369 FailedToQueueEventException e1 =
370 new FailedToQueueEventException(
371 CoreMessages.interruptedQueuingEventFor(this.getName()),
372 event.getMessage(), this, e);
373 handleException(e1);
374 }
375
376 if (logger.isTraceEnabled())
377 {
378 logger.trace("Event added to queue for: " + descriptor.getName());
379 }
380 }
381
382 public UMOMessage doSend(UMOEvent event) throws UMOException
383 {
384 UMOMessage result = null;
385 MuleProxy proxy = null;
386 try
387 {
388 proxy = getProxy();
389 if (logger.isDebugEnabled())
390 {
391 logger.debug(this + " : got proxy for " + event.getId() + " = " + proxy);
392 }
393 result = (UMOMessage) proxy.onCall(event);
394 }
395 catch (UMOException e)
396 {
397 throw e;
398 }
399 catch (Exception e)
400 {
401 throw new ComponentException(event.getMessage(), this, e);
402 }
403 finally
404 {
405 try
406 {
407 if (proxy != null)
408 {
409 if (proxyPool != null)
410 {
411 proxyPool.returnObject(proxy);
412 }
413 else if (componentPerRequest)
414 {
415 proxy.dispose();
416 }
417 }
418 }
419 catch (Exception e)
420 {
421
422 throw new ComponentException(event.getMessage(), this, e);
423 }
424
425 if (proxyPool != null)
426 {
427 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
428 }
429 }
430 return result;
431 }
432
433
434
435
436 ObjectPool getProxyPool()
437 {
438 return proxyPool;
439 }
440
441 public int getQueueSize()
442 {
443 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
444 return queueSession.getQueue(descriptor.getName()).size();
445 }
446
447
448
449
450
451 public void run()
452 {
453 MuleEvent event = null;
454 MuleProxy proxy = null;
455 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
456
457 while (!stopped.get())
458 {
459 try
460 {
461
462 paused.whenFalse(null);
463
464
465
466 if (stopping.get())
467 {
468 if (queueSession == null || queueSession.getQueue(descriptorQueueName).size() == 0)
469 {
470 stopping.set(false);
471 break;
472 }
473 }
474
475 event = (MuleEvent) dequeue();
476 if (event != null)
477 {
478 if (stats.isEnabled())
479 {
480 stats.decQueuedEvent();
481 }
482
483 if (logger.isDebugEnabled())
484 {
485 logger.debug("Component: " + descriptor.getName() + " dequeued event on: "
486 + event.getEndpoint().getEndpointURI());
487 }
488
489 proxy = getProxy();
490 proxy.start();
491 proxy.onEvent(queueSession, event);
492 workManager.scheduleWork(proxy, WorkManager.INDEFINITE, null, this);
493 }
494 }
495 catch (Exception e)
496 {
497 if (proxy != null && proxyPool != null)
498 {
499 try
500 {
501 proxyPool.returnObject(proxy);
502 }
503 catch (Exception e2)
504 {
505
506 logger.info("Failed to return proxy to pool", e2);
507 }
508 }
509
510 if (e instanceof InterruptedException)
511 {
512 stopping.set(false);
513 break;
514 }
515 else if (e instanceof NoSuchElementException)
516 {
517 handleException(new ComponentException(CoreMessages.proxyPoolTimedOut(),
518 (event == null ? null : event.getMessage()), this, e));
519 }
520 else if (e instanceof UMOException)
521 {
522 handleException(e);
523 }
524 else if (e instanceof WorkException)
525 {
526 handleException(
527 new ComponentException(
528 CoreMessages.eventProcessingFailedFor(descriptor.getName()),
529 (event == null ? null : event.getMessage()), this, e));
530 }
531 else
532 {
533 handleException(
534 new ComponentException(
535 CoreMessages.failedToGetPooledObject(),
536 (event == null ? null : event.getMessage()), this, e));
537 }
538 }
539 finally
540 {
541 stopping.set(false);
542 if (proxy != null && componentPerRequest)
543 {
544 proxy.dispose();
545 }
546 }
547 }
548 }
549
550
551
552
553 protected MuleProxy getProxy() throws Exception
554 {
555 MuleProxy proxy;
556 if (proxyPool != null)
557 {
558 proxy = (MuleProxy) proxyPool.borrowObject();
559 ((SedaComponentStatistics) getStatistics()).setComponentPoolSize(proxyPool.getSize());
560 }
561 else if (componentPerRequest)
562 {
563 proxy = createComponentProxy();
564 }
565 else
566 {
567 proxy = componentProxy;
568 }
569 proxy.setStatistics(getStatistics());
570 return proxy;
571 }
572
573 public void release()
574 {
575 stopping.set(false);
576 }
577
578 protected void enqueue(UMOEvent event) throws Exception
579 {
580 QueueSession session = MuleManager.getInstance().getQueueManager().getQueueSession();
581 session.getQueue(descriptorQueueName).put(event);
582 }
583
584 protected UMOEvent dequeue() throws Exception
585 {
586
587 QueueSession queueSession = MuleManager.getInstance().getQueueManager().getQueueSession();
588 return (UMOEvent) queueSession.getQueue(descriptorQueueName).poll(queueTimeout);
589 }
590
591 public void workAccepted(WorkEvent event)
592 {
593 handleWorkException(event, "workAccepted");
594 }
595
596 public void workRejected(WorkEvent event)
597 {
598 handleWorkException(event, "workRejected");
599 }
600
601 public void workStarted(WorkEvent event)
602 {
603 handleWorkException(event, "workStarted");
604 }
605
606 public void workCompleted(WorkEvent event)
607 {
608 handleWorkException(event, "workCompleted");
609 }
610
611 protected void handleWorkException(WorkEvent event, String type)
612 {
613 Throwable e;
614
615 if (event != null && event.getException() != null)
616 {
617 e = event.getException();
618 }
619 else
620 {
621 return;
622 }
623
624 if (event.getException().getCause() != null)
625 {
626 e = event.getException().getCause();
627 }
628
629 logger.error("Work caused exception on '" + type + "'. Work being executed was: "
630 + event.getWork().toString());
631
632 if (e instanceof Exception)
633 {
634 handleException((Exception) e);
635 }
636 else
637 {
638 throw new MuleRuntimeException(
639 CoreMessages.componentCausedErrorIs(this.getName()), e);
640 }
641 }
642
643 public PoolingProfile getPoolingProfile()
644 {
645 return poolingProfile;
646 }
647
648 public void setPoolingProfile(PoolingProfile poolingProfile)
649 {
650 this.poolingProfile = poolingProfile;
651 }
652
653 public QueueProfile getQueueProfile()
654 {
655 return queueProfile;
656 }
657
658 public void setQueueProfile(QueueProfile queueProfile)
659 {
660 this.queueProfile = queueProfile;
661 }
662 }