View Javadoc

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