View Javadoc

1   /*
2    * $Id: MuleEventMulticaster.java 12294 2008-07-11 08:30:31Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.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.DefaultMuleSession;
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.InboundRouterCollection;
36  import org.mule.api.routing.filter.ObjectFilter;
37  import org.mule.api.service.Service;
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.transport.AbstractConnector;
50  import org.mule.util.ClassUtils;
51  
52  import java.beans.ExceptionListener;
53  import java.util.ArrayList;
54  import java.util.Iterator;
55  import java.util.List;
56  import java.util.Map;
57  import java.util.Set;
58  
59  import edu.emory.mathcs.backport.java.util.concurrent.CopyOnWriteArraySet;
60  import edu.emory.mathcs.backport.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      * Removes all the listeners from the multicaster
255      */
256     public void removeAllListeners()
257     {
258         listeners.clear();
259     }
260 
261     /**
262      * Method is used to dispatch events to listeners registered with the
263      * EventManager or dispatches events to Mule depending on the type and state of
264      * the event received. If the event is not a Mule event it will be dispatched to
265      * any listeners registered that are NOT MuleEventListeners. If the event is a
266      * Mule event and there is no source event attached to it, it is assumed that the
267      * event was dispatched by an object in the context using context.publishEvent()
268      * and will be dispatched by Mule. If the event does have a source event attached
269      * to it, it is assumed that the event was dispatched by Mule and will be
270      * delivered to any listeners subscribed to the event.
271      * 
272      * @param e the application event received by the context
273      */
274     public void multicastEvent(ApplicationEvent e)
275     {
276         MuleApplicationEvent muleEvent = null;
277         // if the context gets refreshed we need to reinitialise
278         if (e instanceof ContextRefreshedEvent)
279         {
280             try
281             {
282                 registerMulticasterComponent();
283             }
284             catch (MuleException ex)
285             {
286                 throw new MuleRuntimeException(SpringMessages.failedToReinitMule(), ex);
287             }
288         }
289         else if (e instanceof ContextClosedEvent)
290         {
291             muleContext.dispose();
292             return;
293         }
294         else if (e instanceof MuleApplicationEvent)
295         {
296             muleEvent = (MuleApplicationEvent) e;
297             // If there is no Mule event the event didn't originate from Mule
298             // so its an outbound event
299             if (muleEvent.getMuleEventContext() == null)
300             {
301                 try
302                 {
303                     dispatchEvent(muleEvent);
304                 }
305                 catch (ApplicationEventException e1)
306                 {
307                     exceptionListener.exceptionThrown(e1);
308                 }
309                 return;
310             }
311         }
312 
313         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
314         {
315             ApplicationListener listener = (ApplicationListener) iterator.next();
316             if (muleEvent != null)
317             {
318                 // As the asynchronous listener wraps the real listener we need
319                 // to check the type of the wrapped listener, but invoke the Async
320                 // listener
321                 if (listener instanceof AsynchronousEventListener)
322                 {
323                     AsynchronousEventListener asyncListener = (AsynchronousEventListener) listener;
324                     if (asyncListener.getListener() instanceof MuleSubscriptionEventListener)
325                     {
326                         if (isSubscriptionMatch(muleEvent.getEndpoint(),
327                             ((MuleSubscriptionEventListener) asyncListener.getListener()).getSubscriptions()))
328                         {
329                             asyncListener.onApplicationEvent(muleEvent);
330                         }
331                     }
332                     else if (asyncListener.getListener() instanceof MuleEventListener)
333                     {
334                         asyncListener.onApplicationEvent(muleEvent);
335                     }
336                     else if (!(asyncListener.getListener() instanceof MuleEventListener))
337                     {
338                         asyncListener.onApplicationEvent(e);
339                     }
340                     // Synchronous MuleEvent listener Checks
341                 }
342                 else if (listener instanceof MuleSubscriptionEventListener)
343                 {
344                     if (isSubscriptionMatch(muleEvent.getEndpoint(),
345                         ((MuleSubscriptionEventListener) listener).getSubscriptions()))
346                     {
347                         listener.onApplicationEvent(muleEvent);
348                     }
349                 }
350                 else if (listener instanceof MuleEventListener)
351                 {
352                     listener.onApplicationEvent(muleEvent);
353                 }
354             }
355             else if (listener instanceof AsynchronousEventListener
356                      && !(((AsynchronousEventListener) listener).getListener() instanceof MuleEventListener))
357             {
358                 listener.onApplicationEvent(e);
359             }
360             else if (!(listener instanceof MuleEventListener))
361             {
362                 listener.onApplicationEvent(e);
363             }
364             else
365             {
366                 // Finally only propagate the Application event if the
367                 // ApplicationEvent interface is explicitly implemented
368                 for (int i = 0; i < listener.getClass().getInterfaces().length; i++)
369                 {
370                     if (listener.getClass().getInterfaces()[i].equals(ApplicationListener.class))
371                     {
372                         listener.onApplicationEvent(e);
373                         break;
374                     }
375                 }
376 
377             }
378         }
379     }
380 
381     /**
382      * Matches a subscription to the current event endpointUri
383      * 
384      * @param endpoint endpoint
385      * @param subscriptions subscriptions
386      * @return true if there's a match
387      */
388     private boolean isSubscriptionMatch(String endpoint, String[] subscriptions)
389     {
390         for (int i = 0; i < subscriptions.length; i++)
391         {
392             String subscription = subscriptions[i];
393 
394             // Subscriptions can be full Mule Urls or resource specific such as
395             // my.queue
396             // if it is a MuleEndpointURI we need to extract the Resource
397             // specific part
398             // if (MuleEndpointURI.isMuleUri(subscription)) {
399             // EndpointURI ep = (EndpointURI) endpointsCache.get(subscription);
400             // if (ep == null) {
401             // try {
402             // ep = new MuleEndpointURI(subscription);
403             // } catch (MalformedEndpointException e) {
404             // throw new IllegalArgumentException(e.getMessage());
405             // }
406             // endpointsCache.put(subscription, ep);
407             // }
408             // subscription = ep.getAddress();
409             // }
410 
411             ObjectFilter filter = createFilter(subscription);
412             if (filter.accept(endpoint))
413             {
414                 return true;
415             }
416         }
417         return false;
418     }
419 
420     /**
421      * Determines whether events will be processed asynchronously
422      * 
423      * @return tru if asynchronous. The default is false
424      */
425     public boolean isAsynchronous()
426     {
427         return asynchronous;
428     }
429 
430     /**
431      * Determines whether events will be processed asynchronously
432      * 
433      * @param asynchronous true if aysnchronous
434      */
435     public void setAsynchronous(boolean asynchronous)
436     {
437         this.asynchronous = asynchronous;
438     }
439 
440     /**
441      * This is the callback method used by Mule to give Mule events to this
442      * Multicaster
443      * 
444      * @param context the context received by Mule
445      */
446     public Object onCall(MuleEventContext context) throws TransformerException, MalformedEndpointException
447     {
448         multicastEvent(new MuleApplicationEvent(context.transformMessage(), context, applicationContext));
449         context.setStopFurtherProcessing(true);
450         return null;
451     }
452 
453     /**
454      * Will dispatch an application event through Mule
455      * 
456      * @param applicationEvent the Spring event to be dispatched
457      * @throws ApplicationEventException if the event cannot be dispatched i.e. if
458      *             the underlying transport throws an exception
459      */
460     protected void dispatchEvent(MuleApplicationEvent applicationEvent) throws ApplicationEventException
461     {
462         OutboundEndpoint endpoint;
463         try
464         {
465             endpoint = muleContext.getRegistry().lookupEndpointFactory().getOutboundEndpoint(
466                 applicationEvent.getEndpoint());
467         }
468         catch (MuleException e)
469         {
470             throw new ApplicationEventException("Failed to get endpoint for endpointUri: "
471                                                 + applicationEvent.getEndpoint(), e);
472         }
473         if (endpoint != null)
474         {
475             try
476             {
477                 // if (applicationEvent.getEndpoint() != null) {
478                 // endpoint.setEndpointURI(applicationEvent.getEndpoint());
479                 // }
480 
481                 DefaultMuleMessage message = new DefaultMuleMessage(applicationEvent.getSource(),
482                     applicationEvent.getProperties());
483                 // has dispatch been triggered using beanFactory.publish()
484                 // without a current event
485                 if (applicationEvent.getMuleEventContext() != null)
486                 {
487                     // tell mule not to try and route this event itself
488                     applicationEvent.getMuleEventContext().setStopFurtherProcessing(true);
489                     applicationEvent.getMuleEventContext().dispatchEvent(message, endpoint);
490                 }
491                 else
492                 {
493                     MuleSession session = new DefaultMuleSession(message,
494                         ((AbstractConnector) endpoint.getConnector()).getSessionHandler(), service, muleContext);
495                     RequestContext.setEvent(new DefaultMuleEvent(message, endpoint, session, false));
496                     // transform if necessary
497                     if (endpoint.getTransformers() != null)
498                     {
499                         message = new DefaultMuleMessage(applicationEvent.getSource(),
500                             applicationEvent.getProperties());
501                         message.applyTransformers(endpoint.getTransformers());
502                     }
503                     endpoint.dispatch(new DefaultMuleEvent(message, endpoint, session, false));
504                 }
505             }
506             catch (Exception e1)
507             {
508                 throw new ApplicationEventException("Failed to dispatch event: " + e1.getMessage(), e1);
509             }
510         }
511         else
512         {
513             throw new ApplicationEventException("Failed endpoint using name: "
514                                                 + applicationEvent.getEndpoint());
515         }
516     }
517 
518     /**
519      * Set the current Spring application context
520      * 
521      * @param applicationContext application context
522      * @throws BeansException
523      */
524     public void setApplicationContext(ApplicationContext applicationContext) throws BeansException
525     {
526         this.applicationContext = applicationContext;
527     }
528 
529     protected void registerMulticasterComponent() throws MuleException
530     {
531         // A discriptor hasn't been explicitly configured, so create a default
532         if (service == null)
533         {
534             service = getDefaultService();
535             setSubscriptionsOnService(service);
536             muleContext.getRegistry().registerService(service);
537         }
538     }
539 
540     protected void setSubscriptionsOnService(Service service) throws MuleException
541     {
542         String[] subscriptions;
543         List endpoints = new ArrayList();
544         for (Iterator iterator = listeners.iterator(); iterator.hasNext();)
545         {
546             ApplicationListener listener = (ApplicationListener) iterator.next();
547             if (listener instanceof AsynchronousEventListener)
548             {
549                 listener = ((AsynchronousEventListener) listener).getListener();
550             }
551             if (listener instanceof MuleSubscriptionEventListener)
552             {
553                 subscriptions = ((MuleSubscriptionEventListener) listener).getSubscriptions();
554                 for (int i = 0; i < subscriptions.length; i++)
555                 {
556                     if (subscriptions[i].indexOf("*") == -1 && MuleEndpointURI.isMuleUri(subscriptions[i]))
557                     {
558                         boolean isSoap = registerAsSoap(subscriptions[i], listener);
559 
560                         if (!isSoap)
561                         {
562                             endpoints.add(subscriptions[i]);
563                         }
564                     }
565                 }
566             }
567         }
568         if (endpoints.size() > 0)
569         {
570             String endpoint;
571             for (Iterator iterator = endpoints.iterator(); iterator.hasNext();)
572             {
573                 endpoint = (String) iterator.next();
574 
575                 InboundEndpoint ep = muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(
576                     endpoint);
577 
578                 // check whether the endpoint has already been set on the
579                 // MuleEventMulticastor
580                 if (service.getInboundRouter().getEndpoint(ep.getName()) == null)
581                 {
582                     service.getInboundRouter().addEndpoint(ep);
583                 }
584             }
585         }
586     }
587 
588     private boolean registerAsSoap(String endpoint, Object listener) throws MuleException
589     {
590         if (endpoint.startsWith("soap") || endpoint.startsWith("axis") || endpoint.startsWith("cxf"))
591         {
592             EndpointURI ep = new MuleEndpointURI(endpoint);
593 
594             // get the service name from the URI path
595             String serviceName = null;
596             if (ep.getPath() != null)
597             {
598                 String path = ep.getPath();
599                 if (path.endsWith("/"))
600                 {
601                     path = path.substring(0, path.length() - 1);
602                 }
603                 int i = path.lastIndexOf("/");
604                 if (i > -1)
605                 {
606                     serviceName = path.substring(i + 1);
607                 }
608             }
609             else
610             {
611                 serviceName = service.getName();
612             }
613             // now strip off the service name
614             String newEndpoint = endpoint;
615             int i = newEndpoint.indexOf(serviceName);
616             newEndpoint = newEndpoint.substring(0, i - 1);
617             SedaService s = new SedaService();
618             s.setName(serviceName);
619             s.setModel(muleContext.getRegistry().lookupSystemModel());
620             s.setQueueProfile(new QueueProfile());
621             s.getInboundRouter().addEndpoint(
622                 muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint(newEndpoint));
623             s.setComponent(new DefaultJavaComponent(new SingletonObjectFactory(listener)));
624             muleContext.getRegistry().registerService(s);
625             return true;
626         }
627         else
628         {
629             return false;
630         }
631     }
632 
633     protected void registerConnectors() throws MuleException
634     {
635         if (!muleContext.isInitialised())
636         {
637             // Next see if there are any UMOConnectors to register
638             Map connectors = applicationContext.getBeansOfType(Connector.class, true, true);
639             if (connectors.size() > 0)
640             {
641                 Map.Entry entry;
642                 Connector c;
643                 for (Iterator iterator = connectors.entrySet().iterator(); iterator.hasNext();)
644                 {
645                     entry = (Map.Entry) iterator.next();
646                     c = (Connector) entry.getValue();
647                     if (c.getName() == null)
648                     {
649                         c.setName(entry.getKey().toString());
650                     }
651                     muleContext.getRegistry().registerConnector(c);
652                 }
653             }
654         }
655     }
656 
657     protected void registerTransformers() throws MuleException
658     {
659         if (!muleContext.isInitialised())
660         {
661             // Next see if there are any UMOConnectors to register
662             Map transformers = applicationContext.getBeansOfType(Transformer.class, true, true);
663             if (transformers.size() > 0)
664             {
665                 Map.Entry entry;
666                 Transformer t;
667                 for (Iterator iterator = transformers.entrySet().iterator(); iterator.hasNext();)
668                 {
669                     entry = (Map.Entry) iterator.next();
670                     t = (Transformer) entry.getValue();
671                     if (t.getName() == null)
672                     {
673                         t.setName(entry.getKey().toString());
674                     }
675                     muleContext.getRegistry().registerTransformer(t);
676                 }
677             }
678         }
679     }
680 
681     protected Service getDefaultService() throws MuleException
682     {
683         // When the the beanFactory is refreshed all the beans get
684         // reloaded so we need to unregister the service from Mule
685         Model model = muleContext.getRegistry().lookupModel(MuleProperties.OBJECT_SYSTEM_MODEL);
686         if (model == null)
687         {
688             model = new SedaModel();
689             model.setName(MuleProperties.OBJECT_SYSTEM_MODEL);
690             muleContext.getRegistry().registerModel(model);
691         }
692         Service service = muleContext.getRegistry().lookupService(EVENT_MULTICASTER_DESCRIPTOR_NAME);
693         if (service != null)
694         {
695             muleContext.getRegistry().unregisterService(service.getName());
696         }
697         service = new SedaService();
698         service.setName(EVENT_MULTICASTER_DESCRIPTOR_NAME);
699         service.setModel(model);
700         if (subscriptions == null)
701         {
702             logger.info("No receive endpoints have been set, using default '*'");
703             service.getInboundRouter().addEndpoint(
704                 muleContext.getRegistry().lookupEndpointFactory().getInboundEndpoint("vm://*"));
705         }
706         else
707         {
708             // Set multiple inbound subscriptions on the descriptor
709             InboundRouterCollection messageRouter = service.getInboundRouter();
710 
711             for (int i = 0; i < subscriptions.length; i++)
712             {
713                 String subscription = subscriptions[i];
714 
715                 EndpointFactory endpointFactory = muleContext.getRegistry().lookupEndpointFactory();
716                 EndpointBuilder endpointBuilder = endpointFactory.getEndpointBuilder(subscription);
717                 endpointBuilder.setSynchronous(!asynchronous);
718                 InboundEndpoint endpoint = endpointFactory.getInboundEndpoint(endpointBuilder);
719 
720                 messageRouter.addEndpoint(endpoint);
721             }
722         }
723         service.setComponent(new DefaultJavaComponent(new SingletonObjectFactory(this)));
724         return service;
725     }
726 
727     protected ObjectFilter createFilter(String pattern)
728     {
729         try
730         {
731             if (getSubscriptionFilter() == null)
732             {
733                 setSubscriptionFilter(WildcardFilter.class);
734             }
735             ObjectFilter filter = (ObjectFilter) ClassUtils.instanciateClass(getSubscriptionFilter(),
736                 new Object[]{pattern});
737             return filter;
738         }
739         catch (Exception e)
740         {
741             exceptionListener.exceptionThrown(e);
742             return new WildcardFilter(pattern);
743         }
744     }
745 
746     /**
747      * the type of filter used to filter subscriptions
748      * 
749      * @return the class of the filter to use. The default is WildcardFilter
750      * @see WildcardFilter
751      */
752     public Class getSubscriptionFilter()
753     {
754         return subscriptionFilter;
755     }
756 
757     /**
758      * sets the type of filter used to filter subscriptions
759      * 
760      * @param subscriptionFilter the class of the filter to use.
761      */
762     public void setSubscriptionFilter(Class subscriptionFilter)
763     {
764         this.subscriptionFilter = subscriptionFilter;
765     }
766 
767     /**
768      * A list of endpoints the eventMulticaster will receive events on Note that if
769      * this eventMulticaster has a Mule Descriptor associated with it, these
770      * endpoints are ignored and the ones on the Mule Descriptor are used. These are
771      * here for convenience, the event multicaster will use these to create a default
772      * MuleDescriptor for itself at runtime
773      * 
774      * @return endpoints List being listened on
775      */
776     public String[] getSubscriptions()
777     {
778         return subscriptions;
779     }
780 
781     /**
782      * A list of endpoints the eventMulticaster will receive events on Note that if
783      * this eventMulticaster has a Mule Descriptor associated with it, these
784      * endpoints are ignored and the ones on the Mule Descriptor are used. These are
785      * here for convenience, the event multicaster will use these to create a default
786      * MuleDescriptor for itself at runtime
787      * 
788      * @param subscriptions a list of enpoints to listen on
789      */
790     public void setSubscriptions(String[] subscriptions)
791     {
792         this.subscriptions = subscriptions;
793     }
794 
795     protected void setExceptionListener(ExceptionListener listener)
796     {
797         if (listener != null)
798         {
799             this.exceptionListener = listener;
800         }
801         else
802         {
803             throw new IllegalArgumentException("exceptionListener may not be null");
804         }
805     }
806 
807     private class LoggingExceptionListener implements ExceptionListener
808     {
809         public void exceptionThrown(Exception e)
810         {
811             logger.error(e.getMessage(), e);
812         }
813     }
814 }