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