1
2
3
4
5
6
7 package org.mule.service;
8
9 import org.mule.DefaultMuleEvent;
10 import org.mule.RequestContext;
11 import org.mule.api.MuleContext;
12 import org.mule.api.MuleEvent;
13 import org.mule.api.MuleException;
14 import org.mule.api.MuleRuntimeException;
15 import org.mule.api.MuleSession;
16 import org.mule.api.component.Component;
17 import org.mule.api.construct.FlowConstruct;
18 import org.mule.api.construct.FlowConstructAware;
19 import org.mule.api.context.MuleContextAware;
20 import org.mule.api.exception.MessagingExceptionHandler;
21 import org.mule.api.lifecycle.Disposable;
22 import org.mule.api.lifecycle.Initialisable;
23 import org.mule.api.lifecycle.InitialisationException;
24 import org.mule.api.lifecycle.LifecycleCallback;
25 import org.mule.api.lifecycle.LifecycleManager;
26 import org.mule.api.lifecycle.LifecycleState;
27 import org.mule.api.lifecycle.Startable;
28 import org.mule.api.lifecycle.Stoppable;
29 import org.mule.api.model.Model;
30 import org.mule.api.processor.MessageProcessor;
31 import org.mule.api.processor.MessageProcessorChain;
32 import org.mule.api.processor.MessageProcessorChainBuilder;
33 import org.mule.api.routing.MessageInfoMapping;
34 import org.mule.api.routing.OutboundRouterCollection;
35 import org.mule.api.routing.RouterStatisticsRecorder;
36 import org.mule.api.service.Service;
37 import org.mule.api.source.MessageSource;
38 import org.mule.component.simple.PassThroughComponent;
39 import org.mule.config.i18n.CoreMessages;
40 import org.mule.lifecycle.EmptyLifecycleCallback;
41 import org.mule.lifecycle.processor.ProcessIfStartedWaitIfPausedMessageProcessor;
42 import org.mule.management.stats.RouterStatistics;
43 import org.mule.management.stats.ServiceStatistics;
44 import org.mule.processor.AbstractInterceptingMessageProcessor;
45 import org.mule.processor.chain.DefaultMessageProcessorChainBuilder;
46 import org.mule.routing.MuleMessageInfoMapping;
47 import org.mule.routing.outbound.DefaultOutboundRouterCollection;
48 import org.mule.service.processor.ServiceAsyncRequestReplyRequestor;
49 import org.mule.session.DefaultMuleSession;
50 import org.mule.util.ClassUtils;
51
52 import org.apache.commons.logging.Log;
53 import org.apache.commons.logging.LogFactory;
54
55
56
57
58 public abstract class AbstractService implements Service, MessageProcessor
59 {
60
61
62
63
64 protected transient Log logger = LogFactory.getLog(getClass());
65
66 protected ServiceStatistics stats;
67
68
69
70 protected Model model;
71
72 protected MuleContext muleContext;
73
74 protected ServiceLifecycleManager lifecycleManager;
75
76
77
78
79 public static final String INITIAL_STATE_STOPPED = "stopped";
80 public static final String INITIAL_STATE_STARTED = "started";
81 public static final String INITIAL_STATE_PAUSED = "paused";
82
83
84
85
86 protected MessagingExceptionHandler exceptionListener;
87
88
89
90
91 protected String name;
92
93 protected MessageProcessor outboundRouter = new DefaultOutboundRouterCollection();
94
95 protected MessageSource messageSource = new ServiceCompositeMessageSource();
96 protected ServiceAsyncReplyCompositeMessageSource asyncReplyMessageSource = new ServiceAsyncReplyCompositeMessageSource();
97
98 protected MessageProcessorChain messageProcessorChain;
99 protected MessageInfoMapping messageInfoMapping = new MuleMessageInfoMapping();
100
101
102
103
104
105 protected String initialState = INITIAL_STATE_STARTED;
106
107
108
109
110
111
112
113
114
115 protected Component component = new PassThroughComponent();
116
117 public AbstractService(MuleContext muleContext)
118 {
119 this.muleContext = muleContext;
120 ((MuleContextAware) component).setMuleContext(muleContext);
121 try
122 {
123 lifecycleManager = new ServiceLifecycleManager(this, muleContext);
124 }
125 catch (MuleException e)
126 {
127 throw new MuleRuntimeException(CoreMessages.failedToCreate("Service Lifecycle Manager"), e);
128 }
129
130 }
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146 public final synchronized void initialise() throws InitialisationException
147 {
148 try
149 {
150 lifecycleManager.fireInitialisePhase(new LifecycleCallback<FlowConstruct>()
151 {
152 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
153 {
154 if (outboundRouter instanceof MuleContextAware)
155 {
156 ((MuleContextAware) outboundRouter).setMuleContext(muleContext);
157 }
158
159 if (exceptionListener == null)
160 {
161
162
163 exceptionListener = getModel().getExceptionListener();
164 }
165
166 injectFlowConstructMuleContext(messageSource);
167 injectFlowConstructMuleContext(asyncReplyMessageSource);
168 injectFlowConstructMuleContext(messageProcessorChain);
169 injectFlowConstructMuleContext(component);
170 injectFlowConstructMuleContext(exceptionListener);
171
172 doInitialise();
173 }
174 });
175 }
176 catch (InitialisationException e)
177 {
178 throw e;
179 }
180 catch (MuleException e)
181 {
182 throw new InitialisationException(e, this);
183 }
184
185 }
186
187 public void start() throws MuleException
188 {
189 if (!isStopped() && initialState.equals(AbstractService.INITIAL_STATE_STOPPED))
190 {
191
192 lifecycleManager.fireStartPhase(new EmptyLifecycleCallback<FlowConstruct>());
193 lifecycleManager.fireStopPhase(new EmptyLifecycleCallback<FlowConstruct>());
194
195 logger.info("Service " + name + " has not been started (initial state = 'stopped')");
196 return;
197 }
198
199 lifecycleManager.fireStartPhase(new LifecycleCallback<FlowConstruct>()
200 {
201 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
202 {
203 doStart();
204 }
205 });
206
207
208 if ( initialState.equals(AbstractService.INITIAL_STATE_PAUSED))
209 {
210 pause();
211 logger.info("Service " + name + " has been started and paused (initial state = 'paused')");
212 }
213
214 }
215
216
217
218
219
220
221 public final void pause() throws MuleException
222 {
223 lifecycleManager.firePausePhase(new LifecycleCallback<FlowConstruct>()
224 {
225 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
226 {
227 doPause();
228 }
229 });
230 }
231
232
233
234
235
236 public final void resume() throws MuleException
237 {
238 lifecycleManager.fireResumePhase(new LifecycleCallback<FlowConstruct>()
239 {
240 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
241 {
242 doResume();
243 }
244 });
245 }
246
247
248 public void stop() throws MuleException
249 {
250 lifecycleManager.fireStopPhase(new LifecycleCallback<FlowConstruct>()
251 {
252 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
253 {
254 doStop();
255 }
256 });
257 }
258
259 public final void dispose()
260 {
261
262 try
263 {
264 if (isStarted() || isPaused())
265 {
266 stop();
267 }
268
269 lifecycleManager.fireDisposePhase(new LifecycleCallback<FlowConstruct>()
270 {
271 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
272 {
273 doDispose();
274 }
275 });
276 }
277 catch (MuleException e)
278 {
279 logger.error("Failed to stop service: " + name, e);
280 }
281 }
282
283 public LifecycleState getLifecycleState()
284 {
285 return lifecycleManager.getState();
286 }
287
288 public boolean isStarted()
289 {
290 return lifecycleManager.getState().isStarted();
291 }
292
293
294
295
296
297
298 public boolean isPaused()
299 {
300 return lifecycleManager.getCurrentPhase().equals(Pausable.PHASE_NAME);
301 }
302
303 public boolean isStopped()
304 {
305 return lifecycleManager.getState().isStopped();
306 }
307
308 public boolean isStopping()
309 {
310 return lifecycleManager.getState().isStopping();
311 }
312
313
314
315
316
317
318
319
320 protected void doPause() throws MuleException
321 {
322
323 }
324
325
326
327
328
329
330
331
332 protected void doResume() throws MuleException
333 {
334
335 }
336
337 protected void doForceStop() throws MuleException
338 {
339
340 }
341
342 protected void doStop() throws MuleException
343 {
344 stopIfStoppable(messageSource);
345 asyncReplyMessageSource.stop();
346
347 stopIfStoppable(messageProcessorChain);
348
349 stopIfStoppable(component);
350 stopIfStoppable(exceptionListener);
351 }
352
353 protected void doStart() throws MuleException
354 {
355
356 startIfStartable(exceptionListener);
357 startIfStartable(component);
358 startIfStartable(messageProcessorChain);
359
360 startIfStartable(messageSource);
361 if (asyncReplyMessageSource.getEndpoints().size() > 0)
362 {
363 asyncReplyMessageSource.start();
364 }
365 }
366
367 protected void doDispose()
368 {
369
370 disposeIfDisposable(component);
371 disposeIfDisposable(messageProcessorChain);
372 disposeIfDisposable(messageSource);
373 disposeIfDisposable(exceptionListener);
374 muleContext.getStatistics().remove(stats);
375 }
376
377 protected void doInitialise() throws InitialisationException
378 {
379
380 stats = createStatistics();
381 stats.setEnabled(muleContext.getStatistics().isEnabled());
382 muleContext.getStatistics().add(stats);
383 RouterStatistics routerStatistics = null;
384
385
386 if (outboundRouter instanceof OutboundRouterCollection)
387 {
388 routerStatistics = ((OutboundRouterCollection)outboundRouter).getRouterStatistics();
389 }
390 if (routerStatistics == null)
391 {
392 routerStatistics = new RouterStatistics(RouterStatistics.TYPE_OUTBOUND);
393 }
394 stats.setOutboundRouterStat(routerStatistics);
395 if (outboundRouter != null && outboundRouter instanceof RouterStatisticsRecorder)
396 {
397 ((RouterStatisticsRecorder)outboundRouter).setRouterStatistics(routerStatistics);
398 }
399 RouterStatistics inboundRouterStatistics = new RouterStatistics(RouterStatistics.TYPE_INBOUND);
400 stats.setInboundRouterStat(inboundRouterStatistics);
401 if (messageSource instanceof RouterStatisticsRecorder)
402 {
403 ((RouterStatisticsRecorder) messageSource).setRouterStatistics(inboundRouterStatistics);
404 }
405 stats.setComponentStat(component.getStatistics());
406
407 try
408 {
409 buildServiceMessageProcessorChain();
410 }
411 catch (MuleException e)
412 {
413 throw new InitialisationException(e, this);
414 }
415
416
417 messageSource.setListener(new AbstractInterceptingMessageProcessor()
418 {
419 public MuleEvent process(MuleEvent event) throws MuleException
420 {
421 return messageProcessorChain.process(event);
422 }
423 });
424
425 initialiseIfInitialisable(exceptionListener);
426 initialiseIfInitialisable(component);
427 initialiseIfInitialisable(messageProcessorChain);
428 initialiseIfInitialisable(messageSource);
429
430 if (asyncReplyMessageSource.getEndpoints().size() > 0)
431 {
432 asyncReplyMessageSource.initialise();
433 }
434 }
435
436 public void forceStop() throws MuleException
437 {
438
439
440
441
442
443
444
445
446
447
448
449
450
451 doForceStop();
452 stop();
453 }
454
455
456
457
458
459
460 protected void buildServiceMessageProcessorChain() throws MuleException
461 {
462 DefaultMessageProcessorChainBuilder builder = new DefaultMessageProcessorChainBuilder(this);
463 builder.setName("Service '" + name + "' Processor Chain");
464 builder.chain(getServiceStartedAssertingMessageProcessor());
465 addMessageProcessors(builder);
466 messageProcessorChain = builder.build();
467 }
468
469 protected MessageProcessor getServiceStartedAssertingMessageProcessor()
470 {
471 return new ProcessIfStartedWaitIfPausedMessageProcessor(this, lifecycleManager.getState());
472 }
473
474 protected abstract void addMessageProcessors(MessageProcessorChainBuilder builder);
475
476 protected ServiceStatistics createStatistics()
477 {
478 return new ServiceStatistics(name);
479 }
480
481 public ServiceStatistics getStatistics()
482 {
483 return stats;
484 }
485
486 @Deprecated
487 public void dispatchEvent(MuleEvent event) throws MuleException
488 {
489 messageProcessorChain.process(event);
490 }
491
492 @Deprecated
493 public MuleEvent sendEvent(MuleEvent event) throws MuleException
494 {
495 return messageProcessorChain.process(event);
496 }
497
498
499
500
501 public String getName()
502 {
503 return name;
504 }
505
506 @Override
507 public String toString()
508 {
509 return String.format("%s{%s}", ClassUtils.getSimpleName(this.getClass()), getName());
510 }
511
512
513
514
515
516
517 public Model getModel()
518 {
519 return model;
520 }
521
522 public void setModel(Model model)
523 {
524 this.model = model;
525 }
526
527 public MessagingExceptionHandler getExceptionListener()
528 {
529 return exceptionListener;
530 }
531
532 public void setExceptionListener(MessagingExceptionHandler exceptionListener)
533 {
534 this.exceptionListener = exceptionListener;
535 }
536
537 public MessageSource getMessageSource()
538 {
539 return messageSource;
540 }
541
542 public void setMessageSource(MessageSource inboundMessageSource)
543 {
544 this.messageSource = inboundMessageSource;
545 }
546
547 public MessageProcessor getOutboundMessageProcessor()
548 {
549 return outboundRouter;
550 }
551
552
553 @Deprecated
554 public void setMessageProcessor(MessageProcessor processor)
555 {
556 setOutboundMessageProcessor(processor);
557 }
558
559 public void setOutboundMessageProcessor(MessageProcessor processor)
560 {
561 this.outboundRouter = processor;
562 }
563
564 public ServiceAsyncReplyCompositeMessageSource getAsyncReplyMessageSource()
565 {
566 return asyncReplyMessageSource;
567 }
568
569 public void setAsyncReplyMessageSource(ServiceAsyncReplyCompositeMessageSource asyncReplyMessageSource)
570 {
571 this.asyncReplyMessageSource = asyncReplyMessageSource;
572 }
573
574 public String getInitialState()
575 {
576 return initialState;
577 }
578
579 public void setInitialState(String initialState)
580 {
581 this.initialState = initialState;
582 }
583
584 public void setName(String name)
585 {
586 this.name = name;
587 }
588
589 public Component getComponent()
590 {
591 return component;
592 }
593
594 public void setComponent(Component component)
595 {
596 this.component = component;
597 this.component.setFlowConstruct(this);
598 if (component instanceof MuleContextAware)
599 {
600 ((MuleContextAware) component).setMuleContext(muleContext);
601
602 }
603 }
604
605 public MuleContext getMuleContext()
606 {
607 return muleContext;
608 }
609
610 public LifecycleManager getLifecycleManager()
611 {
612 return lifecycleManager;
613 }
614
615 public MessageInfoMapping getMessageInfoMapping()
616 {
617 return messageInfoMapping;
618 }
619
620 public void setMessageInfoMapping(MessageInfoMapping messageInfoMapping)
621 {
622 this.messageInfoMapping = messageInfoMapping;
623 }
624
625 protected long getAsyncReplyTimeout()
626 {
627 if (asyncReplyMessageSource.getTimeout() != null)
628 {
629 return asyncReplyMessageSource.getTimeout().longValue();
630 }
631 else
632 {
633 return muleContext.getConfiguration().getDefaultResponseTimeout();
634 }
635 }
636
637 protected ServiceAsyncRequestReplyRequestor createAsyncReplyProcessor()
638 {
639 ServiceAsyncRequestReplyRequestor asyncReplyMessageProcessor = new ServiceAsyncRequestReplyRequestor();
640 asyncReplyMessageProcessor.setTimeout(getAsyncReplyTimeout());
641 asyncReplyMessageProcessor.setFailOnTimeout(asyncReplyMessageSource.isFailOnTimeout());
642 asyncReplyMessageProcessor.setReplySource(asyncReplyMessageSource);
643 return asyncReplyMessageProcessor;
644 }
645
646 public MuleEvent process(MuleEvent event) throws MuleException
647 {
648 MuleSession calledSession = new DefaultMuleSession(event.getSession(), this);
649 MuleEvent newEvent = new DefaultMuleEvent(event.getMessage(), event.getEndpoint(), event,
650 calledSession);
651 RequestContext.setEvent(newEvent);
652 try
653 {
654 MuleEvent result = messageProcessorChain.process(newEvent);
655 if (result != null)
656 {
657 result.getMessage().release();
658 }
659 return result;
660 }
661 catch (Exception e)
662 {
663 return getExceptionListener().handleException(e, newEvent);
664 }
665 finally
666 {
667 RequestContext.setEvent(event);
668 event.getMessage().release();
669 }
670 }
671
672 public MessageProcessorChain getMessageProcessorChain()
673 {
674 return messageProcessorChain;
675 }
676
677 protected void injectFlowConstructMuleContext(Object candidate)
678 {
679 if (candidate instanceof FlowConstructAware)
680 {
681 ((FlowConstructAware) candidate).setFlowConstruct(this);
682 }
683 if (candidate instanceof MuleContextAware)
684 {
685 ((MuleContextAware) candidate).setMuleContext(muleContext);
686 }
687 }
688
689 protected void initialiseIfInitialisable(Object candidate) throws InitialisationException
690 {
691 if (candidate instanceof Initialisable)
692 {
693 ((Initialisable) candidate).initialise();
694 }
695 }
696
697 protected void startIfStartable(Object candidate) throws MuleException
698 {
699 if (candidate instanceof Startable)
700 {
701 ((Startable) candidate).start();
702 }
703 }
704
705 protected void stopIfStoppable(Object candidate) throws MuleException
706 {
707 if (candidate instanceof Stoppable)
708 {
709 ((Stoppable) candidate).stop();
710 }
711 }
712
713 protected void disposeIfDisposable(Object candidate)
714 {
715 if (candidate instanceof Disposable)
716 {
717 ((Disposable) candidate).dispose();
718 }
719 }
720
721 protected void pauseIfPausable(Object candidate) throws MuleException
722 {
723 if (candidate instanceof Pausable)
724 {
725 ((Pausable) candidate).pause();
726 }
727 }
728
729 protected void resumeIfResumable(Object candidate) throws MuleException
730 {
731 if (candidate instanceof Resumable)
732 {
733 ((Resumable) candidate).resume();
734 }
735 }
736 }