1
2
3
4
5
6
7
8
9
10
11 package org.mule.service;
12
13 import org.mule.DefaultMuleMessage;
14 import org.mule.OptimizedRequestContext;
15 import org.mule.api.MessagingException;
16 import org.mule.api.MuleContext;
17 import org.mule.api.MuleEvent;
18 import org.mule.api.MuleException;
19 import org.mule.api.MuleMessage;
20 import org.mule.api.component.Component;
21 import org.mule.api.config.MuleProperties;
22 import org.mule.api.endpoint.ImmutableEndpoint;
23 import org.mule.api.endpoint.InboundEndpoint;
24 import org.mule.api.endpoint.OutboundEndpoint;
25 import org.mule.api.lifecycle.InitialisationException;
26 import org.mule.api.model.Model;
27 import org.mule.api.model.ModelException;
28 import org.mule.api.routing.InboundRouterCollection;
29 import org.mule.api.routing.NestedRouterCollection;
30 import org.mule.api.routing.OutboundRouterCollection;
31 import org.mule.api.routing.ResponseRouterCollection;
32 import org.mule.api.service.Service;
33 import org.mule.api.service.ServiceException;
34 import org.mule.api.transport.DispatchException;
35 import org.mule.api.transport.MessageReceiver;
36 import org.mule.api.transport.ReplyToHandler;
37 import org.mule.component.simple.PassThroughComponent;
38 import org.mule.config.i18n.CoreMessages;
39 import org.mule.config.i18n.MessageFactory;
40 import org.mule.context.notification.ServiceNotification;
41 import org.mule.management.stats.ServiceStatistics;
42 import org.mule.routing.inbound.DefaultInboundRouterCollection;
43 import org.mule.routing.inbound.InboundPassThroughRouter;
44 import org.mule.routing.nested.DefaultNestedRouterCollection;
45 import org.mule.routing.outbound.DefaultOutboundRouterCollection;
46 import org.mule.routing.outbound.OutboundPassThroughRouter;
47 import org.mule.routing.response.DefaultResponseRouterCollection;
48 import org.mule.transport.AbstractConnector;
49 import org.mule.util.concurrent.WaitableBoolean;
50
51 import java.beans.ExceptionListener;
52 import java.util.ArrayList;
53 import java.util.Iterator;
54 import java.util.List;
55
56 import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
57
58 import org.apache.commons.logging.Log;
59 import org.apache.commons.logging.LogFactory;
60
61
62
63
64 public abstract class AbstractService implements Service
65 {
66
67
68
69
70 protected transient Log logger = LogFactory.getLog(getClass());
71
72 protected ServiceStatistics stats = null;
73
74
75
76
77 protected AtomicBoolean stopped = new AtomicBoolean(true);
78
79
80
81
82 protected WaitableBoolean stopping = new WaitableBoolean(false);
83
84
85
86
87 protected AtomicBoolean initialised = new AtomicBoolean(false);
88
89
90
91
92 protected Model model;
93
94
95
96
97 protected WaitableBoolean paused = new WaitableBoolean(false);
98
99 protected MuleContext muleContext;
100
101
102
103
104 public static final String INITIAL_STATE_STOPPED = "stopped";
105 public static final String INITIAL_STATE_STARTED = "started";
106 public static final String INITIAL_STATE_PAUSED = "paused";
107
108
109
110
111 protected ExceptionListener exceptionListener;
112
113
114
115
116 protected String name;
117
118 protected InboundRouterCollection inboundRouter = new DefaultInboundRouterCollection();
119
120 protected OutboundRouterCollection outboundRouter = new DefaultOutboundRouterCollection();
121
122 protected NestedRouterCollection nestedRouter = new DefaultNestedRouterCollection();
123
124 protected ResponseRouterCollection responseRouter = new DefaultResponseRouterCollection();
125
126
127
128
129
130 protected String initialState = INITIAL_STATE_STARTED;
131
132
133
134
135 private AtomicBoolean beyondInitialState = new AtomicBoolean(false);
136
137
138
139
140
141
142
143
144 protected Component component = new PassThroughComponent();
145
146
147
148
149 public AbstractService()
150 {
151
152 }
153
154
155
156
157
158
159
160
161
162
163 public final synchronized void initialise() throws InitialisationException
164 {
165 if (initialised.get())
166 {
167 throw new InitialisationException(CoreMessages.objectAlreadyInitialised("Service '" + name + "'"), this);
168 }
169
170
171
172
173 component.setService(this);
174 component.initialise();
175
176 if (inboundRouter == null)
177 {
178
179
180 inboundRouter = new DefaultInboundRouterCollection();
181
182 inboundRouter.addRouter(new InboundPassThroughRouter());
183 }
184 if (outboundRouter == null)
185 {
186 outboundRouter = new DefaultOutboundRouterCollection();
187
188 outboundRouter.addRouter(new OutboundPassThroughRouter());
189 }
190 if (responseRouter == null)
191 {
192 responseRouter = new DefaultResponseRouterCollection();
193 }
194
195 if (exceptionListener == null)
196 {
197
198 exceptionListener = getModel().getExceptionListener();
199
200
201
202
203 }
204
205 doInitialise();
206
207
208 stats = createStatistics();
209
210 stats.setEnabled(muleContext.getStatistics().isEnabled());
211 muleContext.getStatistics().add(stats);
212 stats.setOutboundRouterStat(outboundRouter.getStatistics());
213 stats.setInboundRouterStat(inboundRouter.getStatistics());
214 stats.setComponentStat(component.getStatistics());
215
216 initialised.set(true);
217 fireServiceNotification(ServiceNotification.SERVICE_INITIALISED);
218 }
219
220 protected ServiceStatistics createStatistics()
221 {
222 return new ServiceStatistics(name);
223 }
224
225 protected void fireServiceNotification(int action)
226 {
227 muleContext.fireNotification(new ServiceNotification(this, action));
228 }
229
230 public void forceStop() throws MuleException
231 {
232 if (!stopped.get())
233 {
234 logger.debug("Stopping Service");
235 stopping.set(true);
236 fireServiceNotification(ServiceNotification.SERVICE_STOPPING);
237 doForceStop();
238 stopped.set(true);
239 stopping.set(false);
240 fireServiceNotification(ServiceNotification.SERVICE_STOPPED);
241 }
242 }
243
244 public void stop() throws MuleException
245 {
246 if (!stopped.get())
247 {
248 logger.debug("Stopping Service");
249 stopping.set(true);
250 fireServiceNotification(ServiceNotification.SERVICE_STOPPING);
251
252
253 unregisterListeners();
254
255 component.stop();
256
257 doStop();
258 stopped.set(true);
259 fireServiceNotification(ServiceNotification.SERVICE_STOPPED);
260 logger.info("Mule Service " + name + " has been stopped successfully");
261 }
262 }
263
264 public void start() throws MuleException
265 {
266
267
268 if (!initialised.get())
269 {
270 throw new IllegalStateException("Cannot start an unitialised service.");
271 }
272 if (isStarted())
273 {
274 logger.info("Service is already started: " + name);
275 }
276 else
277 {
278 if (initialState.equals(AbstractService.INITIAL_STATE_STOPPED))
279 {
280 logger.info("stopped");
281 }
282 if (!beyondInitialState.get() && initialState.equals(AbstractService.INITIAL_STATE_STOPPED))
283 {
284 logger.info("Service " + name + " has not been started (initial state = 'stopped')");
285 }
286 else if (!beyondInitialState.get() && initialState.equals(AbstractService.INITIAL_STATE_PAUSED))
287 {
288 start(
289 logger.info("Service " + name + " has been started and paused (initial state = 'paused')");
290 }
291 else
292 {
293 start(
294 logger.info("Service " + name + " has been started successfully");
295 }
296 beyondInitialState.set(true);
297 }
298 }
299
300
301
302
303
304
305
306 protected void start(boolean startPaused) throws MuleException
307 {
308
309
310
311
312
313 component.start();
314
315
316 registerListeners();
317
318
319
320
321
322
323
324 connectListeners();
325
326
327 if (stopped.get())
328 {
329 stopped.set(false);
330 paused.set(false);
331 doStart();
332 }
333 fireServiceNotification(ServiceNotification.SERVICE_STARTED);
334 if (startPaused)
335 {
336 pause();
337 }
338
339
340
341
342
343 startListeners();
344 }
345
346
347
348
349
350
351 public final void pause() throws MuleException
352 {
353 doPause();
354 paused.set(true);
355 fireServiceNotification(ServiceNotification.SERVICE_PAUSED);
356 logger.info("Mule Service " + name + " has been paused successfully");
357 }
358
359
360
361
362
363 public final void resume() throws MuleException
364 {
365 doResume();
366 paused.set(false);
367 fireServiceNotification(ServiceNotification.SERVICE_RESUMED);
368 logger.info("Mule Service " + name + " has been resumed successfully");
369 }
370
371
372
373
374
375
376 public boolean isPaused()
377 {
378 return paused.get();
379 }
380
381
382
383
384
385
386
387
388 protected void doPause() throws MuleException
389 {
390
391 }
392
393
394
395
396
397
398
399
400 protected void doResume() throws MuleException
401 {
402
403 }
404
405 public final void dispose()
406 {
407 try
408 {
409 if (!stopped.get())
410 {
411 stop();
412 }
413 }
414 catch (MuleException e)
415 {
416
417 logger.error("Failed to stop service: " + name, e);
418 }
419 doDispose();
420 component.dispose();
421 initialised.set(false);
422 fireServiceNotification(ServiceNotification.SERVICE_DISPOSED);
423 muleContext.getStatistics().remove(stats);
424 }
425
426 public ServiceStatistics getStatistics()
427 {
428 return stats;
429 }
430
431 public void dispatchEvent(MuleEvent event) throws MuleException
432 {
433 if (stopping.get() || stopped.get())
434 {
435 throw new ServiceException(
436 CoreMessages.componentIsStopped(name),
437 event.getMessage(), this);
438 }
439
440 try
441 {
442 waitIfPaused(event);
443 }
444 catch (InterruptedException e)
445 {
446 throw new ServiceException(event.getMessage(), this, e);
447 }
448
449
450
451 ImmutableEndpoint endpoint = event.getEndpoint();
452
453 if (endpoint instanceof OutboundEndpoint)
454 {
455 try
456 {
457 ((OutboundEndpoint) endpoint).dispatch(event);
458 }
459 catch (Exception e)
460 {
461 throw new DispatchException(event.getMessage(), event.getEndpoint(), e);
462 }
463
464 return;
465 }
466
467
468 if (stats.isEnabled())
469 {
470 stats.incReceivedEventASync();
471 }
472
473 if (logger.isDebugEnabled())
474 {
475 logger.debug("Service: " + name + " has received asynchronous event on: "
476 + event.getEndpoint().getEndpointURI());
477 }
478
479 doDispatch(event);
480 }
481
482 public MuleMessage sendEvent(MuleEvent event) throws MuleException
483 {
484 if (stopping.get() || stopped.get())
485 {
486 throw new ServiceException(
487 CoreMessages.componentIsStopped(name),
488 event.getMessage(), this);
489 }
490
491 try
492 {
493 waitIfPaused(event);
494 }
495 catch (InterruptedException e)
496 {
497 throw new ServiceException(event.getMessage(), this, e);
498 }
499
500 if (stats.isEnabled())
501 {
502 stats.incReceivedEventSync();
503 }
504 if (logger.isDebugEnabled())
505 {
506 logger.debug("Service: " + name + " has received synchronous event on: "
507 + event.getEndpoint().getEndpointURI());
508 }
509 event = OptimizedRequestContext.unsafeSetEvent(event);
510 return doSend(event);
511 }
512
513
514
515
516
517
518
519
520
521 protected void waitIfPaused(MuleEvent event) throws InterruptedException
522 {
523 if (logger.isDebugEnabled() && paused.get())
524 {
525 logger.debug("Service: " + name
526 + " is paused. Blocking call until resume is called");
527 }
528 paused.whenFalse(null);
529 }
530
531
532
533
534 public String getName()
535 {
536 return name;
537 }
538
539
540
541
542
543
544 public String toString()
545 {
546 return getName();
547 }
548
549 public boolean isStopped()
550 {
551 return stopped.get();
552 }
553
554 public boolean isStopping()
555 {
556 return stopping.get();
557 }
558
559 protected void handleException(Exception e)
560 {
561 exceptionListener.exceptionThrown(e);
562 }
563
564 protected void doForceStop() throws MuleException
565 {
566
567 }
568
569 protected void doStop() throws MuleException
570 {
571
572 }
573
574 protected void doStart() throws MuleException
575 {
576
577 }
578
579 protected void doDispose()
580 {
581
582 }
583
584 protected void doInitialise() throws InitialisationException
585 {
586
587 }
588
589 public boolean isStarted()
590 {
591 return !stopped.get();
592 }
593
594 protected abstract MuleMessage doSend(MuleEvent event) throws MuleException;
595
596 protected abstract void doDispatch(MuleEvent event) throws MuleException;
597
598 protected void registerListeners() throws MuleException
599 {
600 InboundEndpoint endpoint;
601 List endpoints = getIncomingEndpoints();
602
603 for (Iterator it = endpoints.iterator(); it.hasNext();)
604 {
605 endpoint = (InboundEndpoint) it.next();
606 try
607 {
608 endpoint.getConnector().registerListener(this, endpoint);
609 }
610 catch (MuleException e)
611 {
612 throw e;
613 }
614 catch (Exception e)
615 {
616 throw new ModelException(
617 CoreMessages.failedtoRegisterOnEndpoint(name, endpoint.getEndpointURI()), e);
618 }
619 }
620 }
621
622 protected void unregisterListeners() throws MuleException
623 {
624 InboundEndpoint endpoint;
625 List endpoints = getIncomingEndpoints();
626
627 for (Iterator it = endpoints.iterator(); it.hasNext();)
628 {
629 endpoint = (InboundEndpoint) it.next();
630 try
631 {
632 endpoint.getConnector().unregisterListener(this, endpoint);
633 }
634 catch (MuleException e)
635 {
636 throw e;
637 }
638 catch (Exception e)
639 {
640 throw new ModelException(
641 CoreMessages.failedToUnregister(name, endpoint.getEndpointURI()), e);
642 }
643 }
644 }
645
646 protected void startListeners() throws MuleException
647 {
648 InboundEndpoint endpoint;
649 List endpoints = getIncomingEndpoints();
650
651 for (Iterator it = endpoints.iterator(); it.hasNext();)
652 {
653 endpoint = (InboundEndpoint) it.next();
654 MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
655 endpoint);
656 if (receiver != null && endpoint.getConnector().isStarted()
657 && endpoint.getInitialState().equals(ImmutableEndpoint.INITIAL_STATE_STARTED))
658 {
659 receiver.start();
660 }
661 }
662 }
663
664
665 protected void stopListeners() throws MuleException
666 {
667 InboundEndpoint endpoint;
668 List endpoints = getIncomingEndpoints();
669
670 for (Iterator it = endpoints.iterator(); it.hasNext();)
671 {
672 endpoint = (InboundEndpoint) it.next();
673 MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
674 endpoint);
675 if (receiver != null)
676 {
677 receiver.stop();
678 }
679 }
680 }
681
682 protected void connectListeners() throws MuleException
683 {
684 InboundEndpoint endpoint;
685 List endpoints = getIncomingEndpoints();
686
687 for (Iterator it = endpoints.iterator(); it.hasNext();)
688 {
689 endpoint = (InboundEndpoint) it.next();
690 MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
691 endpoint);
692 if (receiver != null)
693 {
694 try
695 {
696 receiver.connect();
697 }
698 catch (Exception e)
699 {
700 throw new ModelException(
701 MessageFactory.createStaticMessage("Failed to connect listener "
702 + receiver + " for endpoint " + endpoint.getName()),
703 e);
704 }
705 }
706 }
707 }
708
709 protected void disconnectListeners() throws MuleException
710 {
711 InboundEndpoint endpoint;
712 List endpoints = getIncomingEndpoints();
713
714 for (Iterator it = endpoints.iterator(); it.hasNext();)
715 {
716 endpoint = (InboundEndpoint) it.next();
717 MessageReceiver receiver = ((AbstractConnector) endpoint.getConnector()).getReceiver(this,
718 endpoint);
719 if (receiver != null)
720 {
721 try
722 {
723 receiver.disconnect();
724 }
725 catch (Exception e)
726 {
727 throw new ModelException(
728 MessageFactory.createStaticMessage("Failed to disconnect listener "
729 + receiver + " for endpoint " + endpoint.getName()),
730 e);
731 }
732 }
733 }
734 }
735
736
737
738
739 protected List getIncomingEndpoints()
740 {
741 List endpoints = new ArrayList();
742
743
744 endpoints.addAll(inboundRouter.getEndpoints());
745
746
747 if (responseRouter != null
748 && responseRouter.getEndpoints() != null)
749 {
750 endpoints.addAll(responseRouter.getEndpoints());
751 }
752 return endpoints;
753 }
754
755 public void setMuleContext(MuleContext context)
756 {
757 this.muleContext = context;
758 }
759
760
761
762
763
764 public Model getModel()
765 {
766 return model;
767 }
768
769 public void setModel(Model model)
770 {
771 this.model = model;
772 }
773
774 public ExceptionListener getExceptionListener()
775 {
776 return exceptionListener;
777 }
778
779 public void setExceptionListener(ExceptionListener exceptionListener)
780 {
781 this.exceptionListener = exceptionListener;
782 }
783
784 public InboundRouterCollection getInboundRouter()
785 {
786 return inboundRouter;
787 }
788
789 public void setInboundRouter(InboundRouterCollection inboundRouter)
790 {
791 this.inboundRouter = inboundRouter;
792 }
793
794 public OutboundRouterCollection getOutboundRouter()
795 {
796 return outboundRouter;
797 }
798
799 public void setOutboundRouter(OutboundRouterCollection outboundRouter)
800 {
801 this.outboundRouter = outboundRouter;
802 }
803
804 public ResponseRouterCollection getResponseRouter()
805 {
806 return responseRouter;
807 }
808
809 public void setResponseRouter(ResponseRouterCollection responseRouter)
810 {
811 this.responseRouter = responseRouter;
812 }
813
814 public String getInitialState()
815 {
816 return initialState;
817 }
818
819 public void setInitialState(String initialState)
820 {
821 this.initialState = initialState;
822 }
823
824 public void setName(String name)
825 {
826 this.name = name;
827 }
828
829 public Component getComponent()
830 {
831 return component;
832 }
833
834 public void setComponent(Component component)
835 {
836 this.component = component;
837 this.component.setService(this);
838 }
839
840 protected void processReplyTo(MuleEvent event, MuleMessage result, ReplyToHandler replyToHandler, Object replyTo)
841 throws MuleException
842 {
843 if (result != null && replyToHandler != null)
844 {
845 String requestor = (String) result.getProperty(MuleProperties.MULE_REPLY_TO_REQUESTOR_PROPERTY);
846 if ((requestor != null && !requestor.equals(getName())) || requestor == null)
847 {
848 replyToHandler.processReplyTo(event, result, replyTo);
849 }
850 }
851 }
852
853 protected ReplyToHandler getReplyToHandler(MuleMessage message, InboundEndpoint endpoint)
854 {
855 Object replyTo = message.getReplyTo();
856 ReplyToHandler replyToHandler = null;
857 if (replyTo != null)
858 {
859 replyToHandler = ((AbstractConnector) endpoint.getConnector()).getReplyToHandler();
860
861 if (endpoint.getResponseTransformers() != null)
862 {
863 replyToHandler.setTransformers(endpoint.getResponseTransformers());
864 }
865 }
866 return replyToHandler;
867 }
868
869
870
871
872 protected void dispatchToOutboundRouter(MuleEvent event, MuleMessage result) throws MessagingException
873 {
874 if (event.isStopFurtherProcessing())
875 {
876 logger.debug("MuleEvent stop further processing has been set, no outbound routing will be performed.");
877 }
878 if (result != null && !event.isStopFurtherProcessing())
879 {
880 if (getOutboundRouter().hasEndpoints())
881 {
882
883 getOutboundRouter().route(result, event.getSession(), event.isSynchronous());
884 }
885 }
886 }
887
888
889
890
891 protected MuleMessage sendToOutboundRouter(MuleEvent event, MuleMessage result) throws MessagingException
892 {
893 if (event.isStopFurtherProcessing())
894 {
895 logger.debug("MuleEvent stop further processing has been set, no outbound routing will be performed.");
896 }
897 if (result != null && !event.isStopFurtherProcessing())
898 {
899 if (getOutboundRouter().hasEndpoints())
900 {
901
902
903
904 MuleMessage outboundReturnMessage = getOutboundRouter().route(new DefaultMuleMessage(result), event.getSession(),
905 event.isSynchronous());
906 if (outboundReturnMessage != null)
907 {
908 result = outboundReturnMessage;
909 }
910 }
911 else
912 {
913 logger.debug("Outbound router on service '" + getName() + "' doesn't have any endpoints configured.");
914 }
915 }
916 return result;
917 }
918
919 protected MuleMessage processAsyncReplyRouter(MuleMessage result) throws MuleException
920 {
921 if (result != null && getResponseRouter() != null)
922 {
923 logger.debug("Waiting for response router message");
924 result = getResponseRouter().getResponse(result);
925 }
926 return result;
927 }
928
929 public MuleContext getMuleContext()
930 {
931 return muleContext;
932 }
933
934 }