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.component.Component;
20 import org.mule.api.construct.FlowConstruct;
21 import org.mule.api.construct.FlowConstructAware;
22 import org.mule.api.context.MuleContextAware;
23 import org.mule.api.exception.MessagingExceptionHandler;
24 import org.mule.api.lifecycle.Disposable;
25 import org.mule.api.lifecycle.Initialisable;
26 import org.mule.api.lifecycle.InitialisationException;
27 import org.mule.api.lifecycle.LifecycleCallback;
28 import org.mule.api.lifecycle.LifecycleManager;
29 import org.mule.api.lifecycle.LifecycleState;
30 import org.mule.api.lifecycle.Startable;
31 import org.mule.api.lifecycle.Stoppable;
32 import org.mule.api.model.Model;
33 import org.mule.api.processor.MessageProcessor;
34 import org.mule.api.routing.MessageInfoMapping;
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.builder.InterceptingChainMessageProcessorBuilder;
46 import org.mule.routing.MuleMessageInfoMapping;
47 import org.mule.routing.outbound.DefaultOutboundRouterCollection;
48 import org.mule.service.processor.ServiceAsyncRequestReplyRequestor;
49 import org.mule.util.ClassUtils;
50
51 import org.apache.commons.logging.Log;
52 import org.apache.commons.logging.LogFactory;
53
54
55
56
57 public abstract class AbstractService implements Service, MessageProcessor
58 {
59
60
61
62
63 protected transient Log logger = LogFactory.getLog(getClass());
64
65 protected ServiceStatistics stats;
66
67
68
69 protected Model model;
70
71 protected MuleContext muleContext;
72
73 protected ServiceLifecycleManager lifecycleManager;
74
75
76
77
78 public static final String INITIAL_STATE_STOPPED = "stopped";
79 public static final String INITIAL_STATE_STARTED = "started";
80 public static final String INITIAL_STATE_PAUSED = "paused";
81
82
83
84
85 protected MessagingExceptionHandler exceptionListener;
86
87
88
89
90 protected String name;
91
92 protected MessageProcessor outboundRouter = new DefaultOutboundRouterCollection();
93
94 protected MessageSource messageSource = new ServiceCompositeMessageSource();
95 protected ServiceAsyncReplyCompositeMessageSource asyncReplyMessageSource = new ServiceAsyncReplyCompositeMessageSource();
96
97 protected MessageProcessor messageProcessorChain;
98 protected MessageInfoMapping messageInfoMapping = new MuleMessageInfoMapping();
99
100
101
102
103
104 protected String initialState = INITIAL_STATE_STARTED;
105
106
107
108
109
110
111
112
113
114 protected Component component = new PassThroughComponent();
115
116 public AbstractService(MuleContext muleContext)
117 {
118 this.muleContext = muleContext;
119 try
120 {
121 lifecycleManager = new ServiceLifecycleManager(this);
122 }
123 catch (MuleException e)
124 {
125 throw new MuleRuntimeException(CoreMessages.failedToCreate("Service Lifecycle Manager"), e);
126 }
127
128 }
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144 public final synchronized void initialise() throws InitialisationException
145 {
146 try
147 {
148 lifecycleManager.fireInitialisePhase(new LifecycleCallback<FlowConstruct>()
149 {
150 public void onTransition(String phaseName, FlowConstruct object) throws MuleException
151 {
152 if (outboundRouter instanceof MuleContextAware)
153 {
154 ((MuleContextAware) outboundRouter).setMuleContext(muleContext);
155 }
156
157 if (exceptionListener == null)
158 {
159
160
161 exceptionListener = getModel().getExceptionListener();
162 }
163
164 if (messageSource instanceof FlowConstructAware)
165 {
166 ((FlowConstructAware) messageSource).setFlowConstruct(object);
167 }
168 asyncReplyMessageSource.setFlowConstruct(object);
169
170
171
172
173 component.setFlowConstruct(object);
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 if (messageSource instanceof Stoppable)
348 {
349 ((Stoppable) messageSource).stop();
350 }
351 asyncReplyMessageSource.stop();
352
353
354 if (component instanceof Stoppable)
355 {
356 ((Stoppable) component).stop();
357 }
358 if (messageProcessorChain instanceof Stoppable)
359 {
360 ((Stoppable) messageProcessorChain).stop();
361 }
362 }
363
364 protected void doStart() throws MuleException
365 {
366
367 if (component instanceof Startable)
368 {
369 ((Startable) component).start();
370 }
371 if (messageProcessorChain instanceof Startable)
372 {
373 ((Startable) messageProcessorChain).start();
374 }
375
376 if (messageSource instanceof Startable)
377 {
378 ((Startable) messageSource).start();
379 }
380 if (asyncReplyMessageSource.getEndpoints().size() > 0)
381 {
382 asyncReplyMessageSource.start();
383 }
384 }
385
386 protected void doDispose()
387 {
388
389 if (component instanceof Disposable)
390 {
391 ((Disposable) component).dispose();
392 }
393 if (messageProcessorChain instanceof Disposable)
394 {
395 ((Disposable) messageProcessorChain).dispose();
396 }
397 if (messageSource instanceof Disposable)
398 {
399 ((Disposable) messageSource).dispose();
400 }
401 muleContext.getStatistics().remove(stats);
402 }
403
404 protected void doInitialise() throws InitialisationException
405 {
406
407 stats = createStatistics();
408 stats.setEnabled(muleContext.getStatistics().isEnabled());
409 muleContext.getStatistics().add(stats);
410 RouterStatistics routerStatistics = new RouterStatistics(RouterStatistics.TYPE_OUTBOUND);
411 stats.setOutboundRouterStat(routerStatistics);
412 if (outboundRouter != null && outboundRouter instanceof RouterStatisticsRecorder)
413 {
414 ((RouterStatisticsRecorder)outboundRouter).setRouterStatistics(routerStatistics);
415 }
416 RouterStatistics inboundRouterStatistics = new RouterStatistics(RouterStatistics.TYPE_INBOUND);
417 stats.setInboundRouterStat(inboundRouterStatistics);
418 if (messageSource instanceof RouterStatisticsRecorder)
419 {
420 ((RouterStatisticsRecorder) messageSource).setRouterStatistics(inboundRouterStatistics);
421 }
422 stats.setComponentStat(component.getStatistics());
423
424 try
425 {
426 buildServiceMessageProcessorChain();
427 }
428 catch (MuleException e)
429 {
430 throw new InitialisationException(e, this);
431 }
432
433
434 messageSource.setListener(new AbstractInterceptingMessageProcessor()
435 {
436 public MuleEvent process(MuleEvent event) throws MuleException
437 {
438 return messageProcessorChain.process(event);
439 }
440 });
441
442
443 if (component instanceof Initialisable)
444 {
445 ((Initialisable) component).initialise();
446 }
447 if (messageProcessorChain instanceof Initialisable)
448 {
449 ((Initialisable) messageProcessorChain).initialise();
450 }
451 if (messageSource instanceof Initialisable)
452 {
453 ((Initialisable) messageSource).initialise();
454 }
455 if (asyncReplyMessageSource.getEndpoints().size() > 0)
456 {
457 asyncReplyMessageSource.initialise();
458 }
459
460 }
461
462 public void forceStop() throws MuleException
463 {
464
465
466
467
468
469
470
471
472
473
474
475
476
477 doForceStop();
478 stop();
479 }
480
481
482
483
484
485
486 protected void buildServiceMessageProcessorChain() throws MuleException
487 {
488 InterceptingChainMessageProcessorBuilder builder = new InterceptingChainMessageProcessorBuilder(this);
489 builder.setName("Service '" + name + "' Processor Chain");
490 builder.chain(getServiceStartedAssertingMessageProcessor());
491 addMessageProcessors(builder);
492 messageProcessorChain = builder.build();
493 }
494
495 protected MessageProcessor getServiceStartedAssertingMessageProcessor()
496 {
497 return new ProcessIfStartedWaitIfPausedMessageProcessor(this, lifecycleManager.getState());
498 }
499
500 protected abstract void addMessageProcessors(InterceptingChainMessageProcessorBuilder builder);
501
502 protected ServiceStatistics createStatistics()
503 {
504 return new ServiceStatistics(name);
505 }
506
507 public ServiceStatistics getStatistics()
508 {
509 return stats;
510 }
511
512 @Deprecated
513 public void dispatchEvent(MuleEvent event) throws MuleException
514 {
515 messageProcessorChain.process(event);
516 }
517
518 @Deprecated
519 public MuleEvent sendEvent(MuleEvent event) throws MuleException
520 {
521 return messageProcessorChain.process(event);
522 }
523
524
525
526
527 public String getName()
528 {
529 return name;
530 }
531
532 @Override
533 public String toString()
534 {
535 return String.format("%s{%s}", ClassUtils.getSimpleName(this.getClass()), getName());
536 }
537
538
539
540
541
542
543 public Model getModel()
544 {
545 return model;
546 }
547
548 public void setModel(Model model)
549 {
550 this.model = model;
551 }
552
553 public MessagingExceptionHandler getExceptionListener()
554 {
555 return exceptionListener;
556 }
557
558 public void setExceptionListener(MessagingExceptionHandler exceptionListener)
559 {
560 this.exceptionListener = exceptionListener;
561 }
562
563 public MessageSource getMessageSource()
564 {
565 return messageSource;
566 }
567
568 public void setMessageSource(MessageSource inboundMessageSource)
569 {
570 this.messageSource = inboundMessageSource;
571 }
572
573 public MessageProcessor getOutboundMessageProcessor()
574 {
575 return outboundRouter;
576 }
577
578
579 @Deprecated
580 public void setMessageProcessor(MessageProcessor processor)
581 {
582 setOutboundMessageProcessor(processor);
583 }
584
585 public void setOutboundMessageProcessor(MessageProcessor processor)
586 {
587 this.outboundRouter = processor;
588 }
589
590 public ServiceAsyncReplyCompositeMessageSource getAsyncReplyMessageSource()
591 {
592 return asyncReplyMessageSource;
593 }
594
595 public void setAsyncReplyMessageSource(ServiceAsyncReplyCompositeMessageSource asyncReplyMessageSource)
596 {
597 this.asyncReplyMessageSource = asyncReplyMessageSource;
598 }
599
600 public String getInitialState()
601 {
602 return initialState;
603 }
604
605 public void setInitialState(String initialState)
606 {
607 this.initialState = initialState;
608 }
609
610 public void setName(String name)
611 {
612 this.name = name;
613 }
614
615 public Component getComponent()
616 {
617 return component;
618 }
619
620 public void setComponent(Component component)
621 {
622 this.component = component;
623 this.component.setFlowConstruct(this);
624 }
625
626 public MuleContext getMuleContext()
627 {
628 return muleContext;
629 }
630
631 public LifecycleManager getLifecycleManager()
632 {
633 return lifecycleManager;
634 }
635
636 public MessageInfoMapping getMessageInfoMapping()
637 {
638 return messageInfoMapping;
639 }
640
641 public void setMessageInfoMapping(MessageInfoMapping messageInfoMapping)
642 {
643 this.messageInfoMapping = messageInfoMapping;
644 }
645
646 protected long getAsyncReplyTimeout()
647 {
648 if (asyncReplyMessageSource.getTimeout() != null)
649 {
650 return asyncReplyMessageSource.getTimeout().longValue();
651 }
652 else
653 {
654 return muleContext.getConfiguration().getDefaultResponseTimeout();
655 }
656 }
657
658 protected ServiceAsyncRequestReplyRequestor createAsyncReplyProcessor()
659 {
660 ServiceAsyncRequestReplyRequestor asyncReplyMessageProcessor = new ServiceAsyncRequestReplyRequestor();
661 asyncReplyMessageProcessor.setTimeout(getAsyncReplyTimeout());
662 asyncReplyMessageProcessor.setFailOnTimeout(asyncReplyMessageSource.isFailOnTimeout());
663 asyncReplyMessageProcessor.setReplySource(asyncReplyMessageSource);
664 return asyncReplyMessageProcessor;
665 }
666
667 public MuleEvent process(MuleEvent event) throws MuleException
668 {
669 MuleEvent newEvent = new DefaultMuleEvent(event.getMessage(), event.getEndpoint(), this, event);
670 RequestContext.setEvent(newEvent);
671 return messageProcessorChain.process(newEvent);
672 }
673
674 }