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