View Javadoc

1   /*
2    * $Id: MuleEventMulticaster.java 22175 2011-06-14 13:54:58Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.module.spring.events;
12  
13  import org.mule.DefaultMuleEvent;
14  import org.mule.DefaultMuleMessage;
15  import org.mule.MessageExchangePattern;
16  import org.mule.RequestContext;
17  import org.mule.api.MuleContext;
18  import org.mule.api.MuleEventContext;
19  import org.mule.api.MuleException;
20  import org.mule.api.MuleRuntimeException;
21  import org.mule.api.MuleSession;
22  import org.mule.api.config.MuleProperties;
23  import org.mule.api.config.ThreadingProfile;
24  import org.mule.api.context.MuleContextAware;
25  import org.mule.api.endpoint.EndpointBuilder;
26  import org.mule.api.endpoint.EndpointFactory;
27  import org.mule.api.endpoint.EndpointURI;
28  import org.mule.api.endpoint.InboundEndpoint;
29  import org.mule.api.endpoint.MalformedEndpointException;
30  import org.mule.api.endpoint.OutboundEndpoint;
31  import org.mule.api.lifecycle.Callable;
32  import org.mule.api.lifecycle.Initialisable;
33  import org.mule.api.lifecycle.InitialisationException;
34  import org.mule.api.model.Model;
35  import org.mule.api.routing.filter.ObjectFilter;
36  import org.mule.api.service.Service;
37  import org.mule.api.source.CompositeMessageSource;
38  import org.mule.api.transformer.Transformer;
39  import org.mule.api.transformer.TransformerException;
40  import org.mule.api.transport.Connector;
41  import org.mule.component.DefaultJavaComponent;
42  import org.mule.config.QueueProfile;
43  import org.mule.endpoint.MuleEndpointURI;
44  import org.mule.model.seda.SedaModel;
45  import org.mule.model.seda.SedaService;
46  import org.mule.module.spring.i18n.SpringMessages;
47  import org.mule.object.SingletonObjectFactory;
48  import org.mule.routing.filters.WildcardFilter;
49  import org.mule.service.ServiceCompositeMessageSource;
50  import org.mule.session.DefaultMuleSession;
51  import org.mule.util.ClassUtils;
52  
53  import java.beans.ExceptionListener;
54  import java.util.ArrayList;
55  import java.util.Iterator;
56  import java.util.List;
57  import java.util.Map;
58  import java.util.Set;
59  import java.util.concurrent.CopyOnWriteArraySet;
60  import java.util.concurrent.ExecutorService;
61  
62  import org.apache.commons.logging.Log;
63  import org.apache.commons.logging.LogFactory;
64  import org.springframework.beans.BeansException;
65  import org.springframework.context.ApplicationContext;
66  import org.springframework.context.ApplicationContextAware;
67  import org.springframework.context.ApplicationEvent;
68  import org.springframework.context.ApplicationListener;
69  import org.springframework.context.event.ApplicationEventMulticaster;
70  import org.springframework.context.event.ContextClosedEvent;
71  import org.springframework.context.event.ContextRefreshedEvent;
72  
73  /**
74   * <code>MuleEventMulticaster</code> is an implementation of a Spring
75   * ApplicationeventMulticaster. This implementation allows Mule event to be sent and
76   * received through the Spring ApplicationContext. This allows any Spring bean to
77   * receive and send events from any transport that Mule supports such as Jms, Http,
78   * Tcp, Pop3, Smtp, File, etc. All a bean needs to do to receive and send events is
79   * to implement MuleEventListener. Beans can also have subscriptions to certain
80   * events by implementing MuleSubscriptionEventListener, where the bean can provide a
81   * list of endpoints on which to receive events i.e. <code>
82   * &lt;bean id="myListener" class="com.foo.MyListener"&gt;
83   * &lt;property name="subscriptions"&gt;
84   * &lt;list&gt;
85   * &lt;value&gt;jms://customer.support&lt;/value&gt;
86   * &lt;value&gt;pop3://support:123456@mail.mycompany.com&lt;/value&gt;
87   * &lt;/list&gt;
88   * &lt;/property&gt;
89   * &lt;/bean&gt;
90   * </code>
91   * <p/> Endpoints are specified as a Mule Url which is used to register a listener
92   * for the subscription In the previous version of the MuleEventMulticaster it was
93   * possible to specify wildcard endpoints. This is still possible but you need to
94   * tell the multicaster which specific endpoints to listen on and then your
95   * subscription listeners can use wildcards. To register the specific endpoints on
96   * the MuleEvent Multicaster you use the <i>subscriptions</i> property. <p/> <code>
97   * &lt;bean id="applicationEventMulticaster" class="org.mule.module.spring.events.MuleEventMulticaster"&gt;
98   * &lt;property name="subscriptions"&gt;
99   * &lt;list&gt;
100  * &lt;value&gt;jms://orders.queue&lt;/value&gt;
101  * &lt;value&gt;jms://another.orders.queue&lt;/value&gt;
102  * &lt;/list&gt;
103  * &lt;/property&gt;
104  * &lt;/bean&gt;
105  * <p/>
106  * &lt;bean id="myListener" class="com.foo.MyListener"&gt;
107  * &lt;property name="subscriptions"&gt;
108  * &lt;list&gt;
109  * &lt;value&gt;jms://*.orders.*.&lt;/value&gt;
110  * &lt;/list&gt;
111  * &lt;/property&gt;
112  * &lt;/bean&gt;
113  * <p/>
114  * </code>
115  *
116  * @see MuleEventListener
117  * @see MuleSubscriptionEventListener
118  * @see ApplicationEventMulticaster
119  */
120 public class MuleEventMulticaster
121     implements ApplicationEventMulticaster, ApplicationContextAware, MuleContextAware, Callable, Initialisable
122 {
123     public static final String EVENT_MULTICASTER_DESCRIPTOR_NAME = "muleEventMulticasterDescriptor";
124 
125     /**
126      * logger used by this class
127      */
128     protected static final Log logger = LogFactory.getLog(MuleEventMulticaster.class);
129 
130     /**
131      * The set of listeners for this Multicaster
132      */
133     protected final Set listeners = new CopyOnWriteArraySet();
134 
135     /**
136      * Determines whether events will be processed asynchronously
137      */
138     protected boolean asynchronous = false;
139 
140     /**
141      * An ExecutorService for handling asynchronous events
142      */
143     protected ExecutorService asyncPool = null;
144 
145     /**
146      * A list of endpoints the eventMulticaster will receive events on Note that if
147      * this eventMulticaster has a Mule Descriptor associated with it, these
148      * endpoints are ignored and the ones on the Mule Descriptor are used. These are
149      * here for convenience, the event multicaster will use these to create a default
150      * MuleDescriptor for itself at runtime
151      */
152     protected String[] subscriptions = null;
153 
154     /**
155      * The Spring acpplication context
156      */
157     protected ApplicationContext applicationContext;
158 
159     /**
160      * The mule instance compoennt for the Multicaster
161      */
162     protected Service service;
163 
164     /**
165      * The filter used to match subscriptions
166      */
167     protected Class subscriptionFilter = WildcardFilter.class;
168 
169     /**
170      * Used to store parsed endpoints
171      */
172     protected ExceptionListener exceptionListener = new LoggingExceptionListener();
173 
174     protected MuleContext muleContext;
175 
176     public void setMuleContext(MuleContext context)
177     {
178         this.muleContext = context;
179     }
180 
181     public void initialise() throws InitialisationException
182     {
183         if (asynchronous)
184         {
185             if (asyncPool == null)
186             {
187                 asyncPool = muleContext.getDefaultThreadingProfile().createPool("spring-events");
188             }
189         }
190         else
191         {
192             if (asyncPool != null)
193             {
194                 asyncPool.shutdown();
195                 asyncPool = null;
196             }
197         }
198     }
199 
200     /**
201      * Adds a listener to the the Multicaster. If asynchronous is set to true, an
202      * <code>AsynchronousMessageListener</code> is used to wrap the listener. This
203      * listener will be initialised with a threadpool. The configuration for the
204      * threadpool can be set on this multicaster or inherited from the MuleManager
205      * configuration, which is good for most cases.
206      *
207      * @param listener the ApplicationListener to register with this Multicaster
208      * @see AsynchronousEventListener
209      * @see ThreadingProfile
210      */
211     public void addApplicationListener(ApplicationListener listener)
212     {
213         Object listenerToAdd = listener;
214 
215         if (asynchronous)
216         {
217             listenerToAdd = new AsynchronousEventListener(asyncPool, listener);
218         }
219 
220         listeners.add(listenerToAdd);
221     }
222 
223     /**
224      * Removes a listener from the multicaster
225      *
226      * @param listener the listener to remove
227      */
228     public void removeApplicationListener(ApplicationListener listener)
229     {
230         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
231         {
232             ApplicationListener applicationListener = (ApplicationListener) iterator.next();
233             if (applicationListener instanceof AsynchronousEventListener)
234             {
235                 if (((AsynchronousEventListener) applicationListener).getListener().equals(listener))
236                 {
237                     listeners.remove(applicationListener);
238                     return;
239                 }
240             }
241             else
242             {
243                 if (applicationListener.equals(listener))
244                 {
245                     listeners.remove(applicationListener);
246                     return;
247                 }
248             }
249         }
250         listeners.remove(listener);
251     }
252 
253 
254     public void addApplicationListenerBean(String s)
255        {
256            Object listener = applicationContext.getBean(s);
257            if(listener instanceof ApplicationListener)
258            {
259                addApplicationListener((ApplicationListener)listener);
260            }
261            else
262            {
263                throw new IllegalArgumentException(SpringMessages.beanNotInstanceOfApplicationListener(s).getMessage());
264            }
265        }
266 
267        public void removeApplicationListenerBean(String s)
268        {
269            Object listener = applicationContext.getBean(s);
270            if(listener instanceof ApplicationListener)
271            {
272                removeApplicationListener((ApplicationListener)listener);
273            }
274            else
275            {
276                throw new IllegalArgumentException(SpringMessages.beanNotInstanceOfApplicationListener(s).getMessage());
277            }
278        }
279 
280     /**
281      * Removes all the listeners from the multicaster
282      */
283     public void removeAllListeners()
284     {
285         listeners.clear();
286     }
287 
288     /**
289      * Method is used to dispatch events to listeners registered with the
290      * EventManager or dispatches events to Mule depending on the type and state of
291      * the event received. If the event is not a Mule event it will be dispatched to
292      * any listeners registered that are NOT MuleEventListeners. If the event is a
293      * Mule event and there is no source event attached to it, it is assumed that the
294      * event was dispatched by an object in the context using context.publishEvent()
295      * and will be dispatched by Mule. If the event does have a source event attached
296      * to it, it is assumed that the event was dispatched by Mule and will be
297      * delivered to any listeners subscribed to the event.
298      *
299      * @param e the application event received by the context
300      */
301     public void multicastEvent(ApplicationEvent e)
302     {
303         MuleApplicationEvent muleEvent = null;
304         // if the context gets refreshed we need to reinitialise
305         if (e instanceof ContextRefreshedEvent)
306         {
307             try
308             {
309                 registerMulticasterComponent();
310             }
311             catch (MuleException ex)
312             {
313                 throw new MuleRuntimeException(SpringMessages.failedToReinitMule(), ex);
314             }
315         }
316         else if (e instanceof ContextClosedEvent)
317         {
318             if (!muleContext.isDisposing() && !muleContext.isDisposed())
319             {
320                 muleContext.dispose();
321             }
322             return;
323         }
324         else if (e instanceof MuleApplicationEvent)
325         {
326             muleEvent = (MuleApplicationEvent) e;
327             // If there is no Mule event the event didn't originate from Mule
328             // so its an outbound event
329             if (muleEvent.getMuleEventContext() == null)
330             {
331                 try
332                 {
333                     dispatchEvent(muleEvent);
334                 }
335                 catch (ApplicationEventException e1)
336                 {
337                     exceptionListener.exceptionThrown(e1);
338                 }
339                 return;
340             }
341         }
342 
343         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
344         {
345             ApplicationListener listener = (ApplicationListener) iterator.next();
346             if (muleEvent != null)
347             {
348                 // As the asynchronous listener wraps the real listener we need
349                 // to check the type of the wrapped listener, but invoke the Async
350                 // listener
351                 if (listener instanceof AsynchronousEventListener)
352                 {
353                     AsynchronousEventListener asyncListener = (AsynchronousEventListener) listener;
354                     if (asyncListener.getListener() instanceof MuleSubscriptionEventListener)
355                     {
356                         if (isSubscriptionMatch(muleEvent.getEndpoint(),
357                             ((MuleSubscriptionEventListener) asyncListener.getListener()).getSubscriptions()))
358                         {
359                             asyncListener.onApplicationEvent(muleEvent);
360                         }
361                     }
362                     else if (asyncListener.getListener() instanceof MuleEventListener)
363                     {
364                         asyncListener.onApplicationEvent(muleEvent);
365                     }
366                     else if (!(asyncListener.getListener() instanceof MuleEventListener))
367                     {
368                         asyncListener.onApplicationEvent(e);
369                     }
370                     // Synchronous MuleEvent listener Checks
371                 }
372                 else if (listener instanceof MuleSubscriptionEventListener)
373                 {
374                     if (isSubscriptionMatch(muleEvent.getEndpoint(),
375                         ((MuleSubscriptionEventListener) listener).getSubscriptions()))
376                     {
377                         listener.onApplicationEvent(muleEvent);
378                     }
379                 }
380                 else if (listener instanceof MuleEventListener)
381                 {
382                     listener.onApplicationEvent(muleEvent);
383                 }
384             }
385             else if (listener instanceof AsynchronousEventListener
386                      && !(((AsynchronousEventListener) listener).getListener() instanceof MuleEventListener))
387             {
388                 listener.onApplicationEvent(e);
389             }
390             else if (!(listener instanceof MuleEventListener))
391             {
392                 listener.onApplicationEvent(e);
393             }
394             else
395             {
396                 // Finally only propagate the Application event if the
397                 // ApplicationEvent interface is explicitly implemented
398                 for (int i = 0; i < listener.getClass().getInterfaces().length; i++)
399                 {
400                     if (listener.getClass().getInterfaces()[i].equals(ApplicationListener.class))
401                     {
402                         listener.onApplicationEvent(e);
403                         break;
404                     }
405                 }
406 
407             }
408         }
409     }
410 
411     /**
412      * Matches a subscription to the current event endpointUri
413      *
414      * @param endpoint endpoint
415      * @param subscriptions subscriptions
416      * @return true if there's a match
417      */
418     private boolean isSubscriptionMatch(String endpoint, String[] subscriptions)
419     {
420         for (int i = 0; i < subscriptions.length; i++)
421         {
422             String subscription = subscriptions[i];
423 
424             // Subscriptions can be full Mule Urls or resource specific such as
425             // my.queue
426             // if it is a MuleEndpointURI we need to extract the Resource
427             // specific part
428             // if (MuleEndpointURI.isMuleUri(subscription)) {
429             // EndpointURI ep = (EndpointURI) endpointsCache.get(subscription);
430             // if (ep == null) {
431             // try {
432             // ep = new MuleEndpointURI(subscription);
433             // } catch (MalformedEndpointException e) {
434             // throw new IllegalArgumentException(e.getMessage());
435             // }
436             // endpointsCache.put(subscription, ep);
437             // }
438             // subscription = ep.getAddress();
439             // }
440 
441             ObjectFilter filter = createFilter(subscription);
442             if (filter.accept(endpoint))
443             {
444                 return true;
445             }
446         }
447         return false;
448     }
449 
450     /**
451      * Determines whether events will be processed asynchronously
452      *
453      * @return tru if asynchronous. The default is false
454      */
455     public boolean isAsynchronous()
456     {
457         return asynchronous;
458     }
459 
460     /**
461      * Determines whether events will be processed asynchronously
462      *
463      * @param asynchronous true if aysnchronous
464      */
465     public void setAsynchronous(boolean asynchronous)
466     {
467         this.asynchronous = asynchronous;
468     }
469 
470     /**
471      * This is the callback method used by Mule to give Mule events to this
472      * Multicaster
473      *
474      * @param context the context received by Mule
475      */
476     public Object onCall(MuleEventContext context) throws TransformerException, MalformedEndpointException
477     {
478         multicastEvent(new MuleApplicationEvent(context.getMessage().getPayload(), context, applicationContext));
479         context.setStopFurtherProcessing(true);
480         return null;
481     }
482 
483     /**
484      * Will dispatch an application event through Mule
485      *
486      * @param applicationEvent the Spring event to be dispatched
487      * @throws ApplicationEventException if the event cannot be dispatched i.e. if
488      *             the underlying transport throws an exception
489      */
490     protected void dispatchEvent(MuleApplicationEvent applicationEvent) throws ApplicationEventException
491     {
492         OutboundEndpoint endpoint;
493         try
494         {
495             endpoint = muleContext.getEndpointFactory().getOutboundEndpoint(
496                 applicationEvent.getEndpoint());
497         }
498         catch (MuleException e)
499         {
500             throw new ApplicationEventException("Failed to get endpoint for endpointUri: "
501                                                 + applicationEvent.getEndpoint(), e);
502         }
503         if (endpoint != null)
504         {
505             try
506             {
507                 // if (applicationEvent.getEndpoint() != null) {
508                 // endpoint.setEndpointURI(applicationEvent.getEndpoint());
509                 // }
510 
511                 DefaultMuleMessage message = new DefaultMuleMessage(applicationEvent.getSource(),
512                     applicationEvent.getProperties(), muleContext);
513                 // has dispatch been triggered using beanFactory.publish()
514                 // without a current event
515                 if (applicationEvent.getMuleEventContext() != null)
516                 {
517                     // tell mule not to try and route this event itself
518                     applicationEvent.getMuleEventContext().setStopFurtherProcessing(true);
519                     applicationEvent.getMuleEventContext().dispatchEvent(message, endpoint);
520                 }
521                 else
522                 {
523                     MuleSession session = new DefaultMuleSession(service, muleContext);
524                     DefaultMuleEvent event = new DefaultMuleEvent(message, endpoint.getExchangePattern(),
525                         session);
526                     RequestContext.setEvent(event);
527                     // transform if necessary
528                     if (endpoint.getTransformers() != null)
529                     {
530                         message = new DefaultMuleMessage(applicationEvent.getSource(),
531                             applicationEvent.getProperties(), muleContext);
532                         message.applyTransformers(event, endpoint.getTransformers());
533                     }
534                     endpoint.process(new DefaultMuleEvent(message, endpoint.getExchangePattern(), session));
535                 }
536             }
537             catch (Exception e1)
538             {
539                 throw new ApplicationEventException("Failed to dispatch event: " + e1.getMessage(), e1);
540             }
541         }
542         else
543         {
544             throw new ApplicationEventException("Failed endpoint using name: "
545                                                 + applicationEvent.getEndpoint());
546         }
547     }
548 
549     /**
550      * Set the current Spring application context
551      *
552      * @param applicationContext application context
553      * @throws BeansException
554      */
555     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
556     {
557         this.applicationContext = applicationContext;
558     }
559 
560     protected void registerMulticasterComponent() throws MuleException
561     {
562         // A discriptor hasn't been explicitly configured, so create a default
563         if (service == null)
564         {
565             service = getDefaultService();
566             setSubscriptionsOnService(service);
567             muleContext.getRegistry().registerService(service);
568         }
569     }
570 
571     protected void setSubscriptionsOnService(Service service) throws MuleException
572     {
573         String[] subscriptions;
574         List endpoints = new ArrayList();
575         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
576         {
577             ApplicationListener listener = (ApplicationListener) iterator.next();
578             if (listener instanceof AsynchronousEventListener)
579             {
580                 listener = ((AsynchronousEventListener) listener).getListener();
581             }
582             if (listener instanceof MuleSubscriptionEventListener)
583             {
584                 subscriptions = ((MuleSubscriptionEventListener) listener).getSubscriptions();
585                 for (int i = 0; i < subscriptions.length; i++)
586                 {
587                     if (subscriptions[i].indexOf("*") == -1 && MuleEndpointURI.isMuleUri(subscriptions[i]))
588                     {
589                         boolean isSoap = registerAsSoap(subscriptions[i], listener);
590 
591                         if (!isSoap)
592                         {
593                             endpoints.add(subscriptions[i]);
594                         }
595                     }
596                 }
597             }
598         }
599         if (endpoints.size() > 0)
600         {
601             String endpoint;
602             for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
603             {
604                 endpoint = (String) iterator.next();
605 
606                 InboundEndpoint ep = muleContext.getEndpointFactory().getInboundEndpoint(
607                     endpoint);
608 
609                 // check whether the endpoint has already been set on the
610                 // MuleEventMulticastor
611                 if (((ServiceCompositeMessageSource) service.getMessageSource()).getEndpoint(ep.getName()) == null)
612                 {
613                     ((ServiceCompositeMessageSource) service.getMessageSource()).addSource(ep);
614                 }
615             }
616         }
617     }
618 
619     private boolean registerAsSoap(String endpoint, Object listener) throws MuleException
620     {
621         if (endpoint.startsWith("soap") || endpoint.startsWith("axis") || endpoint.startsWith("cxf"))
622         {
623             EndpointURI ep = new MuleEndpointURI(endpoint, muleContext);
624 
625             // get the service name from the URI path
626             String serviceName = null;
627             if (ep.getPath() != null)
628             {
629                 String path = ep.getPath();
630                 if (path.endsWith("/"))
631                 {
632                     path = path.substring(0, path.length() - 1);
633                 }
634                 int i = path.lastIndexOf("/");
635                 if (i > -1)
636                 {
637                     serviceName = path.substring(i + 1);
638                 }
639             }
640             else
641             {
642                 serviceName = service.getName();
643             }
644             // now strip off the service name
645             String newEndpoint = endpoint;
646             int i = newEndpoint.indexOf(serviceName);
647             newEndpoint = newEndpoint.substring(0, i - 1);
648             SedaService s = new SedaService(muleContext);
649             s.setName(serviceName);
650             s.setModel(muleContext.getRegistry().lookupSystemModel());
651             
652             QueueProfile queueProfile = QueueProfile.newInstancePersistingToDefaultMemoryQueueStore(muleContext);
653             s.setQueueProfile(queueProfile);
654             
655             ((CompositeMessageSource) s.getMessageSource()).addSource(
656                 muleContext.getEndpointFactory().getInboundEndpoint(newEndpoint));
657             final DefaultJavaComponent component = new DefaultJavaComponent(new SingletonObjectFactory(listener));
658             component.setMuleContext(muleContext);
659             s.setComponent(component);
660             muleContext.getRegistry().registerService(s);
661             return true;
662         }
663         else
664         {
665             return false;
666         }
667     }
668 
669     protected void registerConnectors() throws MuleException
670     {
671         if (!muleContext.isInitialised())
672         {
673             // Next see if there are any Connectors to register
674             Map connectors = applicationContext.getBeansOfType(Connector.class, true, true);
675             if (connectors.size() > 0)
676             {
677                 Map.Entry entry;
678                 Connector c;
679                 for (Iterator iterator = connectors.entrySet().iterator(); iterator.hasNext();)
680                 {
681                     entry = (Map.Entry) iterator.next();
682                     c = (Connector) entry.getValue();
683                     if (c.getName() == null)
684                     {
685                         c.setName(entry.getKey().toString());
686                     }
687                     muleContext.getRegistry().registerConnector(c);
688                 }
689             }
690         }
691     }
692 
693     protected void registerTransformers() throws MuleException
694     {
695         if (!muleContext.isInitialised())
696         {
697             // Next see if there are any Connectors to register
698             Map transformers = applicationContext.getBeansOfType(Transformer.class, true, true);
699             if (transformers.size() > 0)
700             {
701                 Map.Entry entry;
702                 Transformer t;
703                 for (Iterator iterator = transformers.entrySet().iterator(); iterator.hasNext();)
704                 {
705                     entry = (Map.Entry) iterator.next();
706                     t = (Transformer) entry.getValue();
707                     if (t.getName() == null)
708                     {
709                         t.setName(entry.getKey().toString());
710                     }
711                     muleContext.getRegistry().registerTransformer(t);
712                 }
713             }
714         }
715     }
716 
717     protected Service getDefaultService() throws MuleException
718     {
719         // When the the beanFactory is refreshed all the beans get
720         // reloaded so we need to unregister the service from Mule
721         Model model = muleContext.getRegistry().lookupModel(MuleProperties.OBJECT_SYSTEM_MODEL);
722         if (model == null)
723         {
724             model = new SedaModel();
725             model.setName(MuleProperties.OBJECT_SYSTEM_MODEL);
726             muleContext.getRegistry().registerModel(model);
727         }
728         Service service = muleContext.getRegistry().lookupService(EVENT_MULTICASTER_DESCRIPTOR_NAME);
729         if (service != null)
730         {
731             muleContext.getRegistry().unregisterService(service.getName());
732         }
733         service = new SedaService(muleContext);
734         service.setName(EVENT_MULTICASTER_DESCRIPTOR_NAME);
735         service.setModel(model);
736         if (subscriptions == null)
737         {
738             logger.info("No receive endpoints have been set, using default '*'");
739             ((CompositeMessageSource) service.getMessageSource()).addSource(
740                 muleContext.getEndpointFactory().getInboundEndpoint("vm://*"));
741         }
742         else
743         {
744             // Set multiple inbound subscriptions on the descriptor
745             ServiceCompositeMessageSource messageRouter = (ServiceCompositeMessageSource) service.getMessageSource();
746 
747             for (int i = 0; i < subscriptions.length; i++)
748             {
749                 String subscription = subscriptions[i];
750 
751                 EndpointFactory endpointFactory = muleContext.getEndpointFactory();
752                 EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(subscription);
753                 endpointBuilder.setExchangePattern(MessageExchangePattern.fromSyncFlag(!asynchronous));
754                 InboundEndpoint endpoint = endpointFactory.getInboundEndpoint(endpointBuilder);
755 
756                 messageRouter.addSource(endpoint);
757             }
758         }
759         DefaultJavaComponent component = new DefaultJavaComponent(new SingletonObjectFactory(this));
760         component.setMuleContext(muleContext);
761         service.setComponent(component);
762         return service;
763     }
764 
765     protected ObjectFilter createFilter(String pattern)
766     {
767         try
768         {
769             if (getSubscriptionFilter() == null)
770             {
771                 setSubscriptionFilter(WildcardFilter.class);
772             }
773             return (ObjectFilter) ClassUtils.instanciateClass(getSubscriptionFilter(), pattern);
774         }
775         catch (Exception e)
776         {
777             exceptionListener.exceptionThrown(e);
778             return new WildcardFilter(pattern);
779         }
780     }
781 
782     /**
783      * the type of filter used to filter subscriptions
784      *
785      * @return the class of the filter to use. The default is WildcardFilter
786      * @see WildcardFilter
787      */
788     public Class getSubscriptionFilter()
789     {
790         return subscriptionFilter;
791     }
792 
793     /**
794      * sets the type of filter used to filter subscriptions
795      *
796      * @param subscriptionFilter the class of the filter to use.
797      */
798     public void setSubscriptionFilter(Class subscriptionFilter)
799     {
800         this.subscriptionFilter = subscriptionFilter;
801     }
802 
803     /**
804      * A list of endpoints the eventMulticaster will receive events on Note that if
805      * this eventMulticaster has a Mule Descriptor associated with it, these
806      * endpoints are ignored and the ones on the Mule Descriptor are used. These are
807      * here for convenience, the event multicaster will use these to create a default
808      * MuleDescriptor for itself at runtime
809      *
810      * @return endpoints List being listened on
811      */
812     public String[] getSubscriptions()
813     {
814         return subscriptions;
815     }
816 
817     /**
818      * A list of endpoints the eventMulticaster will receive events on Note that if
819      * this eventMulticaster has a Mule Descriptor associated with it, these
820      * endpoints are ignored and the ones on the Mule Descriptor are used. These are
821      * here for convenience, the event multicaster will use these to create a default
822      * MuleDescriptor for itself at runtime
823      *
824      * @param subscriptions a list of enpoints to listen on
825      */
826     public void setSubscriptions(String[] subscriptions)
827     {
828         this.subscriptions = subscriptions;
829     }
830 
831     protected void setExceptionListener(ExceptionListener listener)
832     {
833         if (listener != null)
834         {
835             this.exceptionListener = listener;
836         }
837         else
838         {
839             throw new IllegalArgumentException("exceptionListener may not be null");
840         }
841     }
842 
843     private static class LoggingExceptionListener implements ExceptionListener
844     {
845         public LoggingExceptionListener()
846         {
847             super();
848         }
849 
850         public void exceptionThrown(Exception e)
851         {
852             logger.error(e.getMessage(), e);
853         }
854     }
855 }