View Javadoc

1   /*
2    * $Id: MuleManager.java 10660 2008-02-01 11:57:38Z 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;
12  
13  import org.mule.config.ConfigurationException;
14  import org.mule.config.MuleConfiguration;
15  import org.mule.config.MuleManifest;
16  import org.mule.config.MuleProperties;
17  import org.mule.config.ThreadingProfile;
18  import org.mule.config.i18n.CoreMessages;
19  import org.mule.impl.container.MultiContainerContext;
20  import org.mule.impl.internal.admin.MuleAdminAgent;
21  import org.mule.impl.internal.notifications.AdminNotification;
22  import org.mule.impl.internal.notifications.AdminNotificationListener;
23  import org.mule.impl.internal.notifications.ComponentNotification;
24  import org.mule.impl.internal.notifications.ComponentNotificationListener;
25  import org.mule.impl.internal.notifications.ConnectionNotification;
26  import org.mule.impl.internal.notifications.ConnectionNotificationListener;
27  import org.mule.impl.internal.notifications.CustomNotification;
28  import org.mule.impl.internal.notifications.CustomNotificationListener;
29  import org.mule.impl.internal.notifications.ExceptionNotification;
30  import org.mule.impl.internal.notifications.ExceptionNotificationListener;
31  import org.mule.impl.internal.notifications.ManagementNotification;
32  import org.mule.impl.internal.notifications.ManagementNotificationListener;
33  import org.mule.impl.internal.notifications.ManagerNotification;
34  import org.mule.impl.internal.notifications.ManagerNotificationListener;
35  import org.mule.impl.internal.notifications.MessageNotification;
36  import org.mule.impl.internal.notifications.MessageNotificationListener;
37  import org.mule.impl.internal.notifications.ModelNotification;
38  import org.mule.impl.internal.notifications.ModelNotificationListener;
39  import org.mule.impl.internal.notifications.NotificationException;
40  import org.mule.impl.internal.notifications.SecurityNotification;
41  import org.mule.impl.internal.notifications.SecurityNotificationListener;
42  import org.mule.impl.internal.notifications.ServerNotificationManager;
43  import org.mule.impl.internal.notifications.TransactionNotification;
44  import org.mule.impl.internal.notifications.TransactionNotificationListener;
45  import org.mule.impl.model.ModelFactory;
46  import org.mule.impl.model.ModelHelper;
47  import org.mule.impl.security.MuleSecurityManager;
48  import org.mule.impl.work.MuleWorkManager;
49  import org.mule.management.stats.AllStatistics;
50  import org.mule.umo.UMOException;
51  import org.mule.umo.UMOInterceptorStack;
52  import org.mule.umo.endpoint.UMOEndpoint;
53  import org.mule.umo.lifecycle.FatalException;
54  import org.mule.umo.lifecycle.InitialisationException;
55  import org.mule.umo.manager.UMOAgent;
56  import org.mule.umo.manager.UMOContainerContext;
57  import org.mule.umo.manager.UMOManager;
58  import org.mule.umo.manager.UMOServerNotification;
59  import org.mule.umo.manager.UMOServerNotificationListener;
60  import org.mule.umo.manager.UMOWorkManager;
61  import org.mule.umo.model.UMOModel;
62  import org.mule.umo.provider.UMOConnector;
63  import org.mule.umo.security.UMOSecurityManager;
64  import org.mule.umo.transformer.UMOTransformer;
65  import org.mule.util.CollectionUtils;
66  import org.mule.util.SpiUtils;
67  import org.mule.util.StringMessageUtils;
68  import org.mule.util.StringUtils;
69  import org.mule.util.UUID;
70  import org.mule.util.queue.QueueManager;
71  import org.mule.util.queue.QueuePersistenceStrategy;
72  import org.mule.util.queue.TransactionalQueueManager;
73  
74  import java.net.InetAddress;
75  import java.net.UnknownHostException;
76  import java.nio.charset.Charset;
77  import java.util.ArrayList;
78  import java.util.Collection;
79  import java.util.Collections;
80  import java.util.Date;
81  import java.util.HashMap;
82  import java.util.Iterator;
83  import java.util.LinkedHashMap;
84  import java.util.List;
85  import java.util.Map;
86  
87  import javax.transaction.TransactionManager;
88  import javax.xml.parsers.SAXParserFactory;
89  
90  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
91  
92  import org.apache.commons.collections.MapUtils;
93  import org.apache.commons.collections.list.CursorableLinkedList;
94  import org.apache.commons.logging.Log;
95  import org.apache.commons.logging.LogFactory;
96  
97  /**
98   * <code>MuleManager</code> maintains and provides services for a Mule instance.
99   */
100 public class MuleManager implements UMOManager
101 {
102     /**
103      * singleton instance
104      */
105     private static UMOManager instance = null;
106 
107     /**
108      * Default configuration
109      */
110     private static MuleConfiguration config = new MuleConfiguration();
111 
112     /**
113      * Connectors registry
114      */
115     private Map connectors = new HashMap();
116 
117     /**
118      * Endpoints registry
119      * 
120      * @deprecated endpoint-identifiers have been deprecated in favor of
121      *             global-endpoints
122      */
123     private Map endpointIdentifiers = new HashMap();
124 
125     /**
126      * Holds any application scoped environment properties set in the config
127      */
128     private Map applicationProps = new HashMap();
129 
130     /**
131      * Holds any registered agents
132      */
133     private Map agents = new LinkedHashMap();
134 
135     /**
136      * Holds a list of global endpoints accessible to any client code
137      */
138     private Map endpoints = new HashMap();
139 
140     /**
141      * The model being used
142      */
143     private Map models = new LinkedHashMap();
144 
145     /**
146      * the unique id for this manager
147      */
148     private String id = UUID.getUUID();
149 
150     /**
151      * The transaction Manager to use for global transactions
152      */
153     private TransactionManager transactionManager = null;
154 
155     /**
156      * Collection for transformers registered in this component
157      */
158     private Map transformers = new HashMap();
159 
160     /**
161      * True once the Mule Manager is initialised
162      */
163     private AtomicBoolean initialised = new AtomicBoolean(false);
164 
165     /**
166      * True while the Mule Manager is initialising
167      */
168     private AtomicBoolean initialising = new AtomicBoolean(false);
169 
170     /**
171      * Determines of the MuleManager has been started
172      */
173     private AtomicBoolean started = new AtomicBoolean(false);
174 
175     /**
176      * Determines in the manager is in the process of starting
177      */
178     private AtomicBoolean starting = new AtomicBoolean(false);
179 
180     /**
181      * Determines in the manager is in the process of stopping.
182      */
183     private AtomicBoolean stopping = new AtomicBoolean(false);
184 
185     /**
186      * Determines if the manager has been disposed
187      */
188     private AtomicBoolean disposed = new AtomicBoolean(false);
189 
190     /**
191      * Maintains a reference to any interceptor stacks configured on the manager
192      */
193     private Map interceptorsMap = new HashMap();
194 
195     /**
196      * the date in milliseconds from when the server was started
197      */
198     private long startDate = 0;
199 
200     /**
201      * stats used for management
202      */
203     private AllStatistics stats = new AllStatistics();
204 
205     /**
206      * Manages all Server event notificationManager
207      */
208     private ServerNotificationManager notificationManager = null;
209 
210     private MultiContainerContext containerContext = null;
211 
212     private UMOSecurityManager securityManager;
213 
214     /**
215      * The queue manager to use for component queues and vm connector
216      */
217     private QueueManager queueManager;
218 
219     private UMOWorkManager workManager;
220 
221     /**
222      * logger used by this class
223      */
224     private static Log logger = LogFactory.getLog(MuleManager.class);
225 
226     /**
227      * Default Constructor
228      */
229     private MuleManager()
230     {
231         if (config == null)
232         {
233             config = new MuleConfiguration();
234         }
235         containerContext = new MultiContainerContext();
236         securityManager = new MuleSecurityManager();
237 
238         // create the event manager
239         notificationManager = new ServerNotificationManager();
240         notificationManager.registerEventType(ManagerNotification.class, ManagerNotificationListener.class);
241         notificationManager.registerEventType(ModelNotification.class, ModelNotificationListener.class);
242         notificationManager.registerEventType(ComponentNotification.class,
243             ComponentNotificationListener.class);
244         notificationManager.registerEventType(SecurityNotification.class, SecurityNotificationListener.class);
245         notificationManager.registerEventType(ManagementNotification.class,
246             ManagementNotificationListener.class);
247         notificationManager.registerEventType(AdminNotification.class, AdminNotificationListener.class);
248         notificationManager.registerEventType(CustomNotification.class, CustomNotificationListener.class);
249         notificationManager.registerEventType(ConnectionNotification.class,
250             ConnectionNotificationListener.class);
251         notificationManager.registerEventType(ExceptionNotification.class,
252             ExceptionNotificationListener.class);
253         notificationManager.registerEventType(TransactionNotification.class,
254             TransactionNotificationListener.class);
255     }
256 
257     /**
258      * Getter method for the current singleton MuleManager
259      * 
260      * @return the current singleton MuleManager
261      */
262     public static synchronized UMOManager getInstance()
263     {
264         if (instance == null)
265         {
266             logger.info("Creating new MuleManager instance");
267 
268             Class clazz = SpiUtils.findService(UMOManager.class, MuleManager.class.getName(),
269                 MuleManager.class);
270             try
271             {
272                 // There should always be a defualt system model registered
273                 instance = (UMOManager) clazz.newInstance();
274                 registerSystemModel(config.getSystemModelType());
275             }
276             catch (Exception e)
277             {
278                 throw new MuleRuntimeException(CoreMessages.failedToCreateManagerInstance(clazz.getName()), e);
279             }
280         }
281 
282         return instance;
283     }
284 
285     /**
286      * A static method to determine if there is an instance of the MuleManager. This
287      * should be used instead of <code>
288      * if(MuleManager.getInstance()!=null)
289      * </code>
290      * because getInstance never returns a null. If an istance is not available one
291      * is created. This method queries the instance directly.
292      * 
293      * @return true if the manager is instanciated
294      */
295     public static synchronized boolean isInstanciated()
296     {
297         return (instance != null);
298     }
299 
300     /**
301      * Sets the current singleton MuleManager
302      * 
303      * @deprecated this will go away soon.
304      */
305     public static synchronized void setInstance(UMOManager manager)
306     {
307         instance = manager;
308         if (instance == null)
309         {
310             config = new MuleConfiguration();
311         }
312     }
313 
314     /**
315      * Gets all statisitcs for this instance
316      * 
317      * @return all statisitcs for this instance
318      */
319     public AllStatistics getStatistics()
320     {
321         return stats;
322     }
323 
324     /**
325      * Sets statistics on this instance
326      * 
327      * @param stat
328      */
329     public void setStatistics(AllStatistics stat)
330     {
331         this.stats = stat;
332     }
333 
334     /**
335      * @return the MuleConfiguration for this MuleManager. This object is immutable
336      *         once the manager has initialised.
337      */
338     public static synchronized MuleConfiguration getConfiguration()
339     {
340         return config;
341     }
342 
343     /**
344      * Sets the configuration for the <code>MuleManager</code>.
345      * 
346      * @param config the configuration object
347      * @throws IllegalAccessError if the <code>MuleManager</code> has already been
348      *             initialised.
349      * @deprecated this will go away soon.
350      */
351     public static synchronized void setConfiguration(MuleConfiguration config) throws UMOException
352     {
353         if (config == null)
354         {
355             throw new IllegalArgumentException(CoreMessages.objectIsNull("MuleConfiguration object")
356                 .getMessage());
357         }
358 
359         MuleManager.config = config;
360         // TODO this call might cause a problem, but the whole setConfiguration()
361         // method is doomed anyway
362         registerSystemModel(config.getSystemModelType());
363 
364     }
365 
366     protected static void registerSystemModel(String type) throws UMOException
367     {
368         if (instance != null)
369         {
370             // Initialise the system model
371             UMOModel model = instance.lookupModel(type);
372             if (model != null && model.getComponentNames().hasNext())
373             {
374                 throw new IllegalStateException(
375                     "System model is already registered and contains components. Cannot overwrite");
376             }
377             model = ModelFactory.createModel(config.getSystemModelType());
378             model.setName(ModelHelper.SYSTEM_MODEL);
379             instance.registerModel(model);
380         }
381     }
382 
383     // Implementation methods
384     // -------------------------------------------------------------------------
385 
386     /**
387      * Destroys the MuleManager and all resources it maintains
388      */
389     public synchronized void dispose()
390     {
391         if (disposed.get())
392         {
393             return;
394         }
395         try
396         {
397             if (started.get())
398             {
399                 stop();
400             }
401         }
402         catch (UMOException e)
403         {
404             logger.error("Failed to stop manager: " + e.getMessage(), e);
405         }
406         disposed.set(true);
407         disposeConnectors();
408 
409         for (Iterator i = models.values().iterator(); i.hasNext();)
410         {
411             UMOModel model = (UMOModel) i.next();
412             model.dispose();
413         }
414 
415         disposeAgents();
416 
417         transformers.clear();
418         endpoints.clear();
419         endpointIdentifiers.clear();
420         containerContext.dispose();
421         containerContext = null;
422         // props.clear();
423         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSED));
424 
425         transformers = null;
426         endpoints = null;
427         endpointIdentifiers = null;
428         // props = null;
429         initialised.set(false);
430         if (notificationManager != null)
431         {
432             notificationManager.dispose();
433         }
434         if (workManager != null)
435         {
436             workManager.dispose();
437         }
438 
439         if (queueManager != null)
440         {
441             queueManager.close();
442             queueManager = null;
443         }
444 
445         if ((startDate > 0) && logger.isInfoEnabled())
446         {
447             logger.info(this.getEndSplash());
448         }
449 
450         config = new MuleConfiguration();
451         instance = null;
452     }
453 
454     /**
455      * Destroys all connectors
456      */
457     private synchronized void disposeConnectors()
458     {
459         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSING_CONNECTORS));
460         for (Iterator iterator = connectors.values().iterator(); iterator.hasNext();)
461         {
462             UMOConnector c = (UMOConnector) iterator.next();
463             c.dispose();
464         }
465         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSED_CONNECTORS));
466     }
467 
468     /**
469      * {@inheritDoc}
470      */
471     public Object getProperty(Object key)
472     {
473         return applicationProps.get(key);
474     }
475 
476     /**
477      * {@inheritDoc}
478      */
479     public Map getProperties()
480     {
481         return applicationProps;
482     }
483 
484     /**
485      * {@inheritDoc}
486      */
487     public TransactionManager getTransactionManager()
488     {
489         return transactionManager;
490     }
491 
492     /**
493      * {@inheritDoc}
494      */
495     public UMOConnector lookupConnector(String name)
496     {
497         return (UMOConnector) connectors.get(name);
498     }
499 
500     /**
501      * {@inheritDoc}
502      * 
503      * @deprecated endpoint-identifiers have been deprecated in favor of
504      *             global-endpoints
505      */
506     public String lookupEndpointIdentifier(String logicalName, String defaultName)
507     {
508         String name = (String) endpointIdentifiers.get(logicalName);
509         if (name == null)
510         {
511             return defaultName;
512         }
513         return name;
514     }
515 
516     /**
517      * {@inheritDoc}
518      */
519     public UMOEndpoint lookupEndpoint(String logicalName)
520     {
521         UMOEndpoint endpoint = (UMOEndpoint) endpoints.get(logicalName);
522         if (endpoint != null)
523         {
524             return (UMOEndpoint) endpoint.clone();
525         }
526         else
527         {
528             return null;
529         }
530     }
531 
532     /**
533      * {@inheritDoc}
534      */
535     public UMOEndpoint lookupEndpointByAddress(String address)
536     {
537         UMOEndpoint endpoint = null;
538         if (address != null)
539         {
540             boolean found = false;
541             Iterator iterator = endpoints.keySet().iterator();
542             while (!found && iterator.hasNext())
543             {
544                 endpoint = (UMOEndpoint) endpoints.get(iterator.next());
545                 found = (address.equals(endpoint.getEndpointURI().toString()));
546             }
547         }
548         return endpoint;
549     }
550 
551     /**
552      * {@inheritDoc}
553      */
554     public UMOTransformer lookupTransformer(String name)
555     {
556         UMOTransformer trans = (UMOTransformer) transformers.get(name);
557         if (trans != null)
558         {
559             try
560             {
561                 return (UMOTransformer) trans.clone();
562             }
563             catch (Exception e)
564             {
565                 throw new MuleRuntimeException(CoreMessages.failedToClone("Transformer: " + trans.getName()),
566                     e);
567             }
568         }
569         return null;
570     }
571 
572     /**
573      * {@inheritDoc}
574      */
575     public void registerConnector(UMOConnector connector) throws UMOException
576     {
577         connectors.put(connector.getName(), connector);
578         if (initialised.get() || initialising.get())
579         {
580             connector.initialise();
581         }
582         if ((started.get() || starting.get()) && !connector.isStarted())
583         {
584             connector.startConnector();
585         }
586     }
587 
588     /**
589      * {@inheritDoc}
590      */
591     public void unregisterConnector(String connectorName) throws UMOException
592     {
593         UMOConnector c = (UMOConnector) connectors.remove(connectorName);
594         if (c != null)
595         {
596             c.dispose();
597         }
598     }
599 
600     /**
601      * {@inheritDoc}
602      * 
603      * @deprecated endpoint-identifiers have been deprecated in favor of
604      *             global-endpoints
605      */
606     public void registerEndpointIdentifier(String logicalName, String endpoint)
607     {
608         endpointIdentifiers.put(logicalName, endpoint);
609     }
610 
611     /**
612      * {@inheritDoc}
613      * 
614      * @deprecated endpoint-identifiers have been deprecated in favor of
615      *             global-endpoints
616      */
617     public void unregisterEndpointIdentifier(String logicalName)
618     {
619         endpointIdentifiers.remove(logicalName);
620     }
621 
622     /**
623      * {@inheritDoc}
624      */
625     public void registerEndpoint(UMOEndpoint endpoint)
626     {
627         endpoints.put(endpoint.getName(), endpoint);
628     }
629 
630     /**
631      * {@inheritDoc}
632      */
633     public void unregisterEndpoint(String endpointName)
634     {
635         UMOEndpoint p = (UMOEndpoint) endpoints.get(endpointName);
636         if (p != null)
637         {
638             endpoints.remove(p);
639         }
640     }
641 
642     /**
643      * {@inheritDoc}
644      */
645     public void registerTransformer(UMOTransformer transformer) throws InitialisationException
646     {
647         transformer.initialise();
648         transformers.put(transformer.getName(), transformer);
649         logger.info("Transformer " + transformer.getName() + " has been initialised successfully");
650     }
651 
652     /**
653      * {@inheritDoc}
654      */
655     public void unregisterTransformer(String transformerName)
656     {
657         transformers.remove(transformerName);
658     }
659 
660     /**
661      * {@inheritDoc}
662      */
663     public void setProperty(Object key, Object value)
664     {
665         applicationProps.put(key, value);
666     }
667 
668     public void addProperties(Map props)
669     {
670         applicationProps.putAll(props);
671     }
672 
673     /**
674      * {@inheritDoc}
675      */
676     public void setTransactionManager(TransactionManager newManager) throws UMOException
677     {
678         if (transactionManager != null)
679         {
680             throw new ConfigurationException(CoreMessages.transactionManagerAlreadySet());
681         }
682         transactionManager = newManager;
683     }
684 
685     /**
686      * {@inheritDoc}
687      */
688     public synchronized void initialise() throws UMOException
689     {
690         validateEncoding();
691         validateOSEncoding();
692         validateXML();
693 
694         if (!initialised.get())
695         {
696             initialising.set(true);
697             startDate = System.currentTimeMillis();
698             // if no work manager has been set create a default one
699             if (workManager == null)
700             {
701                 ThreadingProfile tp = config.getDefaultThreadingProfile();
702                 logger.debug("Creating default work manager using default threading profile: " + tp);
703                 workManager = new MuleWorkManager(tp, "UMOManager");
704                 workManager.start();
705             }
706 
707             // Start the event manager
708             notificationManager.start(workManager);
709 
710             // Fire message notifications if the option is set. This will fire
711             // inbound and outbound message events that can
712             // consume resources in high throughput systems
713             if (config.isEnableMessageEvents())
714             {
715                 notificationManager.registerEventType(MessageNotification.class,
716                     MessageNotificationListener.class);
717             }
718 
719             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_INITIALISNG));
720             if (id == null)
721             {
722                 logger.warn("No unique id has been set on this manager");
723             }
724 
725             try
726             {
727                 if (securityManager != null)
728                 {
729                     securityManager.initialise();
730                 }
731                 if (queueManager == null)
732                 {
733                     try
734                     {
735                         TransactionalQueueManager queueMgr = new TransactionalQueueManager();
736                         QueuePersistenceStrategy ps = getConfiguration().getPersistenceStrategy();
737                         queueMgr.setPersistenceStrategy(ps);
738                         queueManager = queueMgr;
739                     }
740                     catch (Exception e)
741                     {
742                         throw new InitialisationException(CoreMessages.initialisationFailure("QueueManager"),
743                             e);
744                     }
745                 }
746 
747                 initialiseConnectors();
748                 initialiseEndpoints();
749                 initialiseAgents();
750                 for (Iterator i = models.values().iterator(); i.hasNext();)
751                 {
752                     UMOModel model = (UMOModel) i.next();
753                     model.initialise();
754                 }
755 
756             }
757             finally
758             {
759                 initialised.set(true);
760                 initialising.set(false);
761                 fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_INITIALISED));
762             }
763         }
764     }
765 
766     protected void validateEncoding() throws FatalException
767     {
768         String encoding = System.getProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY);
769         if (encoding == null)
770         {
771             encoding = config.getEncoding();
772             System.setProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY, encoding);
773         }
774         else
775         {
776             config.setEncoding(encoding);
777         }
778         // Check we have a valid and supported encoding
779         if (!Charset.isSupported(config.getEncoding()))
780         {
781             throw new FatalException(CoreMessages.propertyHasInvalidValue("encoding", config.getEncoding()),
782                 this);
783         }
784     }
785 
786     protected void validateOSEncoding() throws FatalException
787     {
788         String encoding = System.getProperty(MuleProperties.MULE_OS_ENCODING_SYSTEM_PROPERTY);
789         if (encoding == null)
790         {
791             encoding = config.getOSEncoding();
792             System.setProperty(MuleProperties.MULE_OS_ENCODING_SYSTEM_PROPERTY, encoding);
793         }
794         else
795         {
796             config.setOSEncoding(encoding);
797         }
798         // Check we have a valid and supported encoding
799         if (!Charset.isSupported(config.getOSEncoding()))
800         {
801             throw new FatalException(CoreMessages.propertyHasInvalidValue("osEncoding",
802                 config.getOSEncoding()), this);
803         }
804     }
805 
806     /**
807      * Mule needs a proper JAXP implementation and will complain when run with a plain JDK
808      * 1.4. Use the supplied launcher or specify a proper JAXP implementation via
809      * <code>-Djava.endorsed.dirs</code>. See the following URLs for more information:
810      * <ul>
811      * <li> {@link http://xerces.apache.org/xerces2-j/faq-general.html#faq-4}
812      * <li> {@link http://xml.apache.org/xalan-j/faq.html#faq-N100D6}
813      * <li> {@link http://java.sun.com/j2se/1.4.2/docs/guide/standards/}
814      * </ul>
815      */
816     protected void validateXML() throws FatalException
817     {
818         SAXParserFactory f = SAXParserFactory.newInstance();
819         if (f == null || f.getClass().getName().indexOf("crimson") != -1)
820         {
821             throw new FatalException(CoreMessages.valueIsInvalidFor(f.getClass().getName(),
822                 "javax.xml.parsers.SAXParserFactory"), this);
823         }
824     }
825 
826     protected void registerAdminAgent() throws UMOException
827     {
828         // Allows users to disable all server components and connections
829         // this can be useful for testing
830         boolean disable = MapUtils.getBooleanValue(System.getProperties(),
831             MuleProperties.DISABLE_SERVER_CONNECTIONS_SYSTEM_PROPERTY, false);
832 
833         // if endpointUri is blanked out do not setup server components
834         if (StringUtils.isBlank(config.getServerUrl()))
835         {
836             logger.info("Server endpointUri is null, not registering Mule Admin agent");
837             disable = true;
838         }
839 
840         if (disable)
841         {
842             unregisterAgent(MuleAdminAgent.AGENT_NAME);
843         }
844         else
845         {
846             if (lookupAgent(MuleAdminAgent.AGENT_NAME) == null)
847             {
848                 registerAgent(new MuleAdminAgent());
849             }
850         }
851     }
852 
853     protected void initialiseEndpoints() throws InitialisationException
854     {
855         UMOEndpoint ep;
856         for (Iterator iterator = this.endpoints.values().iterator(); iterator.hasNext();)
857         {
858             ep = (UMOEndpoint) iterator.next();
859             ep.initialise();
860             // the connector has been created for this endpoint so lets
861             // set the create connector to 0 so that every time this endpoint
862             // is referenced we don't create another connector
863             ep.setCreateConnector(0);
864         }
865     }
866 
867     /**
868      * Start the <code>MuleManager</code>. This will start the connectors and
869      * sessions.
870      * 
871      * @throws UMOException if the the connectors or components fail to start
872      */
873     public synchronized void start() throws UMOException
874     {
875         initialise();
876 
877         if (!started.get())
878         {
879             starting.set(true);
880             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STARTING));
881             registerAdminAgent();
882             if (queueManager != null)
883             {
884                 queueManager.start();
885             }
886             startConnectors();
887             startAgents();
888             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STARTING_MODELS));
889             for (Iterator i = models.values().iterator(); i.hasNext();)
890             {
891                 UMOModel model = (UMOModel) i.next();
892                 model.start();
893             }
894             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STARTED_MODELS));
895 
896             started.set(true);
897             starting.set(false);
898             if (logger.isInfoEnabled())
899             {
900                 logger.info(this.getStartSplash());
901             }
902             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STARTED));
903         }
904     }
905 
906     /**
907      * Start the <code>MuleManager</code>. This will start the connectors and
908      * sessions.
909      * 
910      * @param serverUrl the server Url for this instance
911      * @throws UMOException if the the connectors or components fail to start
912      */
913     public void start(String serverUrl) throws UMOException
914     {
915         // this.createClientListener = createRequestListener;
916         config.setServerUrl(serverUrl);
917         start();
918     }
919 
920     /**
921      * Starts the connectors
922      * 
923      * @throws MuleException if the connectors fail to start
924      */
925     private void startConnectors() throws UMOException
926     {
927         for (Iterator iterator = connectors.values().iterator(); iterator.hasNext();)
928         {
929             UMOConnector c = (UMOConnector) iterator.next();
930             c.startConnector();
931         }
932         logger.info("Connectors have been started successfully");
933     }
934 
935     private void initialiseConnectors() throws InitialisationException
936     {
937         for (Iterator iterator = connectors.values().iterator(); iterator.hasNext();)
938         {
939             UMOConnector c = (UMOConnector) iterator.next();
940             c.initialise();
941         }
942         logger.info("Connectors have been initialised successfully");
943     }
944 
945     /**
946      * Stops the <code>MuleManager</code> which stops all sessions and connectors
947      * 
948      * @throws UMOException if either any of the sessions or connectors fail to stop
949      */
950     public synchronized void stop() throws UMOException
951     {
952         started.set(false);
953         stopping.set(true);
954         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STOPPING));
955 
956         stopConnectors();
957         stopAgents();
958 
959         if (queueManager != null)
960         {
961             queueManager.stop();
962         }
963 
964         logger.debug("Stopping model...");
965         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STOPPING_MODELS));
966         for (Iterator i = models.values().iterator(); i.hasNext();)
967         {
968             UMOModel model = (UMOModel) i.next();
969             model.stop();
970         }
971         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STOPPED_MODELS));
972 
973         stopping.set(false);
974         initialised.set(false);
975         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_STOPPED));
976     }
977 
978     /**
979      * Stops the connectors
980      * 
981      * @throws MuleException if any of the connectors fail to stop
982      */
983     private void stopConnectors() throws UMOException
984     {
985         logger.debug("Stopping connectors...");
986         for (Iterator iterator = connectors.values().iterator(); iterator.hasNext();)
987         {
988             UMOConnector c = (UMOConnector) iterator.next();
989             c.stopConnector();
990         }
991         logger.info("Connectors have been stopped successfully");
992     }
993 
994     public UMOModel lookupModel(String name)
995     {
996         return (UMOModel) models.get(name);
997     }
998 
999     public void registerModel(UMOModel model) throws UMOException
1000     {
1001         models.put(model.getName(), model);
1002         if (initialised.get())
1003         {
1004             model.initialise();
1005         }
1006 
1007         if (started.get())
1008         {
1009             model.start();
1010         }
1011     }
1012 
1013     public void unregisterModel(String name)
1014     {
1015         UMOModel model = lookupModel(name);
1016         if (model != null)
1017         {
1018             models.remove(model.getName());
1019             model.dispose();
1020         }
1021     }
1022 
1023     public Map getModels()
1024     {
1025         return Collections.unmodifiableMap(models);
1026     }
1027 
1028     /**
1029      * {@inheritDoc}
1030      */
1031     public void registerInterceptorStack(String name, UMOInterceptorStack stack)
1032     {
1033         interceptorsMap.put(name, stack);
1034     }
1035 
1036     /**
1037      * {@inheritDoc}
1038      */
1039     public UMOInterceptorStack lookupInterceptorStack(String name)
1040     {
1041         return (UMOInterceptorStack) interceptorsMap.get(name);
1042     }
1043 
1044     /**
1045      * {@inheritDoc}
1046      */
1047     public Map getConnectors()
1048     {
1049         return Collections.unmodifiableMap(connectors);
1050     }
1051 
1052     /**
1053      * {@inheritDoc}
1054      * 
1055      * @deprecated endpoint-identifiers have been deprecated in favor of
1056      *             global-endpoints
1057      */
1058     public Map getEndpointIdentifiers()
1059     {
1060         return Collections.unmodifiableMap(endpointIdentifiers);
1061     }
1062 
1063     /**
1064      * {@inheritDoc}
1065      */
1066     public Map getEndpoints()
1067     {
1068         return Collections.unmodifiableMap(endpoints);
1069     }
1070 
1071     /**
1072      * {@inheritDoc}
1073      */
1074     public Map getTransformers()
1075     {
1076         return Collections.unmodifiableMap(transformers);
1077     }
1078 
1079     /**
1080      * {@inheritDoc}
1081      */
1082     public boolean isStarted()
1083     {
1084         return started.get();
1085     }
1086 
1087     /**
1088      * {@inheritDoc}
1089      */
1090     public boolean isInitialised()
1091     {
1092         return initialised.get();
1093     }
1094 
1095     /**
1096      * Determines if the server is currently initialising
1097      * 
1098      * @return true if if the server is currently initialising, false otherwise
1099      */
1100     public boolean isInitialising()
1101     {
1102         return initialising.get();
1103     }
1104 
1105     /**
1106      * Determines in the manager is in the process of stopping.
1107      */
1108     public boolean isStopping()
1109     {
1110         return stopping.get();
1111     }
1112 
1113     /**
1114      * {@inheritDoc}
1115      */
1116     public long getStartDate()
1117     {
1118         return startDate;
1119     }
1120 
1121     /**
1122      * Returns a formatted string that is a summary of the configuration of the
1123      * server. This is the brock of information that gets displayed when the server
1124      * starts
1125      * 
1126      * @return a string summary of the server information
1127      */
1128     private String getStartSplash()
1129     {
1130         String notset = CoreMessages.notSet().getMessage();
1131 
1132         // Mule Version, Timestamp, and Server ID
1133         List message = new ArrayList();
1134         message.add(StringUtils.defaultString(MuleManifest.getProductDescription(), notset));
1135         message.add(CoreMessages.version().getMessage() + " "
1136                     + StringUtils.defaultString(MuleManifest.getProductVersion(), notset) + " Build: "
1137                     + StringUtils.defaultString(MuleManifest.getBuildNumber(), notset));
1138         message.add(StringUtils.defaultString(MuleManifest.getVendorName(), notset));
1139         message.add(StringUtils.defaultString(MuleManifest.getProductMoreInfo(), notset));
1140         message.add(" ");
1141         message.add(CoreMessages.serverStartedAt(this.getStartDate()));
1142         message.add("Server ID: " + id);
1143 
1144         // JDK, OS, and Host
1145         message.add("JDK: " + System.getProperty("java.version") + " (" + System.getProperty("java.vm.info")
1146                     + ")");
1147         String patch = System.getProperty("sun.os.patch.level", null);
1148         message.add("OS: " + System.getProperty("os.name")
1149                     + (patch != null && !"unknown".equalsIgnoreCase(patch) ? " - " + patch : "") + " ("
1150                     + System.getProperty("os.version") + ", " + System.getProperty("os.arch") + ")");
1151         try
1152         {
1153             InetAddress host = InetAddress.getLocalHost();
1154             message.add("Host: " + host.getHostName() + " (" + host.getHostAddress() + ")");
1155         }
1156         catch (UnknownHostException e)
1157         {
1158             // ignore
1159         }
1160 
1161         // Mule Agents
1162         message.add(" ");
1163         if (agents.size() == 0)
1164         {
1165             message.add(CoreMessages.agentsRunning().getMessage() + " " + CoreMessages.none());
1166         }
1167         else
1168         {
1169             message.add(CoreMessages.agentsRunning());
1170             UMOAgent umoAgent;
1171             for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1172             {
1173                 umoAgent = (UMOAgent) iterator.next();
1174                 message.add("  " + umoAgent.getDescription());
1175             }
1176         }
1177         return StringMessageUtils.getBoilerPlate(message, '*', 70);
1178     }
1179 
1180     private String getEndSplash()
1181     {
1182         List message = new ArrayList(2);
1183         long currentTime = System.currentTimeMillis();
1184         message.add(CoreMessages.shutdownNormally(new Date()));
1185         long duration = 10;
1186         if (startDate > 0)
1187         {
1188             duration = currentTime - startDate;
1189         }
1190         message.add(CoreMessages.serverWasUpForDuration(duration));
1191 
1192         return StringMessageUtils.getBoilerPlate(message, '*', 78);
1193     }
1194 
1195     /**
1196      * {@inheritDoc}
1197      */
1198     public void registerAgent(UMOAgent agent) throws UMOException
1199     {
1200         agents.put(agent.getName(), agent);
1201         agent.registered();
1202         // Don't allow initialisation while the server is being initalised,
1203         // only when we are done. Otherwise the agent registration
1204         // order can be corrupted.
1205         if (initialised.get())
1206         {
1207             agent.initialise();
1208         }
1209         if ((started.get() || starting.get()))
1210         {
1211             agent.start();
1212         }
1213     }
1214 
1215     public UMOAgent lookupAgent(String name)
1216     {
1217         return (UMOAgent) agents.get(name);
1218     }
1219 
1220     /**
1221      * {@inheritDoc}
1222      */
1223     public UMOAgent unregisterAgent(String name) throws UMOException
1224     {
1225         if (name == null)
1226         {
1227             return null;
1228         }
1229         UMOAgent agent = (UMOAgent) agents.remove(name);
1230         if (agent != null)
1231         {
1232             agent.dispose();
1233             agent.unregistered();
1234         }
1235         return agent;
1236     }
1237 
1238     /**
1239      * Initialises all registered agents
1240      * 
1241      * @throws InitialisationException
1242      */
1243     protected void initialiseAgents() throws InitialisationException
1244     {
1245         logger.info("Initialising agents...");
1246 
1247         // Do not iterate over the map directly, as 'complex' agents
1248         // may spawn extra agents during initialisation. This will
1249         // cause a ConcurrentModificationException.
1250         // Use a cursorable iteration, which supports on-the-fly underlying
1251         // data structure changes.
1252         Collection agentsSnapshot = agents.values();
1253         CursorableLinkedList agentRegistrationQueue = new CursorableLinkedList(agentsSnapshot);
1254         CursorableLinkedList.Cursor cursor = agentRegistrationQueue.cursor();
1255 
1256         // the actual agent object refs are the same, so we are just
1257         // providing different views of the same underlying data
1258 
1259         try
1260         {
1261             while (cursor.hasNext())
1262             {
1263                 UMOAgent umoAgent = (UMOAgent) cursor.next();
1264 
1265                 int originalSize = agentsSnapshot.size();
1266                 logger.debug("Initialising agent: " + umoAgent.getName());
1267                 umoAgent.initialise();
1268                 // thank you, we are done with you
1269                 cursor.remove();
1270 
1271                 // Direct calls to MuleManager.registerAgent() modify the original
1272                 // agents map, re-check if the above agent registered any
1273                 // 'child' agents.
1274                 int newSize = agentsSnapshot.size();
1275                 int delta = newSize - originalSize;
1276                 if (delta > 0)
1277                 {
1278                     // TODO there's some mess going on in
1279                     // http://issues.apache.org/jira/browse/COLLECTIONS-219
1280                     // watch out when upgrading the commons-collections.
1281                     Collection tail = CollectionUtils.retainAll(agentsSnapshot, agentRegistrationQueue);
1282                     Collection head = CollectionUtils.subtract(agentsSnapshot, tail);
1283 
1284                     // again, above are only refs, all going back to the original
1285                     // agents map
1286 
1287                     // re-order the queue
1288                     agentRegistrationQueue.clear();
1289                     // 'spawned' agents first
1290                     agentRegistrationQueue.addAll(head);
1291                     // and the rest
1292                     agentRegistrationQueue.addAll(tail);
1293 
1294                     // update agents map with a new order in case we want to
1295                     // re-initialise
1296                     // MuleManager on the fly
1297                     this.agents.clear();
1298                     for (Iterator it = agentRegistrationQueue.iterator(); it.hasNext();)
1299                     {
1300                         UMOAgent theAgent = (UMOAgent) it.next();
1301                         this.agents.put(theAgent.getName(), theAgent);
1302                     }
1303                 }
1304             }
1305         }
1306         finally
1307         {
1308             // close the cursor as per JavaDoc
1309             cursor.close();
1310         }
1311         logger.info("Agents Successfully Initialised");
1312     }
1313 
1314     /**
1315      * {@inheritDoc}
1316      */
1317     protected void startAgents() throws UMOException
1318     {
1319         UMOAgent umoAgent;
1320         logger.info("Starting agents...");
1321         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1322         {
1323             umoAgent = (UMOAgent) iterator.next();
1324             logger.info("Starting agent: " + umoAgent.getDescription());
1325             umoAgent.start();
1326 
1327         }
1328         logger.info("Agents Successfully Started");
1329     }
1330 
1331     /**
1332      * {@inheritDoc}
1333      */
1334     protected void stopAgents() throws UMOException
1335     {
1336         logger.info("Stopping agents...");
1337         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1338         {
1339             UMOAgent umoAgent = (UMOAgent) iterator.next();
1340             logger.debug("Stopping agent: " + umoAgent.getName());
1341             umoAgent.stop();
1342         }
1343         logger.info("Agents Successfully Stopped");
1344     }
1345 
1346     /**
1347      * {@inheritDoc}
1348      */
1349     protected void disposeAgents()
1350     {
1351         UMOAgent umoAgent;
1352         logger.info("disposing agents...");
1353         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1354         {
1355             umoAgent = (UMOAgent) iterator.next();
1356             logger.debug("Disposing agent: " + umoAgent.getName());
1357             umoAgent.dispose();
1358         }
1359         logger.info("Agents Successfully Disposed");
1360     }
1361 
1362     /**
1363      * associates a Dependency Injector container or Jndi container with Mule. This
1364      * can be used to integrate container managed resources with Mule resources
1365      * 
1366      * @param container a Container context to use. By default, there is a default
1367      *            Mule container <code>MuleContainerContext</code> that will assume
1368      *            that the reference key for an oblect is a classname and will try to
1369      *            instanciate it.
1370      */
1371     public void setContainerContext(UMOContainerContext container) throws UMOException
1372     {
1373         if (container == null)
1374         {
1375             if (containerContext != null)
1376             {
1377                 containerContext.dispose();
1378             }
1379             containerContext = new MultiContainerContext();
1380         }
1381         else
1382         {
1383             container.initialise();
1384             containerContext.addContainer(container);
1385         }
1386     }
1387 
1388     /**
1389      * associates a Dependency Injector container with Mule. This can be used to
1390      * integrate container managed resources with Mule resources
1391      * 
1392      * @return the container associated with the Manager
1393      */
1394     public UMOContainerContext getContainerContext()
1395     {
1396         return containerContext;
1397     }
1398 
1399     /**
1400      * {@inheritDoc}
1401      */
1402     public void registerListener(UMOServerNotificationListener l) throws NotificationException
1403     {
1404         registerListener(l, null);
1405     }
1406 
1407     public void registerListener(UMOServerNotificationListener l, String resourceIdentifier)
1408         throws NotificationException
1409     {
1410         if (notificationManager == null)
1411         {
1412             throw new NotificationException(CoreMessages.serverEventManagerNotEnabled());
1413         }
1414         notificationManager.registerListener(l, resourceIdentifier);
1415     }
1416 
1417     /**
1418      * {@inheritDoc}
1419      */
1420     public void unregisterListener(UMOServerNotificationListener l)
1421     {
1422         if (notificationManager != null)
1423         {
1424             notificationManager.unregisterListener(l);
1425         }
1426     }
1427 
1428     /**
1429      * Fires a mule 'system' event. These are notifications that are fired because
1430      * something within the Mule instance happened such as the Model started or the
1431      * server is being disposed.
1432      * 
1433      * @param e the event that occurred
1434      */
1435     protected void fireSystemEvent(UMOServerNotification e)
1436     {
1437         if (notificationManager != null)
1438         {
1439             notificationManager.fireEvent(e);
1440         }
1441         else if (logger.isDebugEnabled())
1442         {
1443             logger.debug("Event Manager is not enabled, ignoring event: " + e);
1444         }
1445     }
1446 
1447     /**
1448      * Fires a server notification to all registered
1449      * {@link org.mule.impl.internal.notifications.CustomNotificationListener}
1450      * notificationManager. TODO RM: This method now duplicates #fireSystemEvent()
1451      * completely
1452      * 
1453      * @param notification the notification to fire. This must be of type
1454      *            {@link org.mule.impl.internal.notifications.CustomNotification}
1455      *            otherwise an exception will be thrown.
1456      * @throws UnsupportedOperationException if the notification fired is not a
1457      *             {@link org.mule.impl.internal.notifications.CustomNotification}
1458      */
1459     public void fireNotification(UMOServerNotification notification)
1460     {
1461         // if(notification instanceof CustomNotification) {
1462         if (notificationManager != null)
1463         {
1464             notificationManager.fireEvent(notification);
1465         }
1466         else if (logger.isDebugEnabled())
1467         {
1468             logger.debug("Event Manager is not enabled, ignoring notification: " + notification);
1469         }
1470         // } else {
1471         // throw new UnsupportedOperationException(new
1472         // Message(Messages.ONLY_CUSTOM_EVENTS_CAN_BE_FIRED).getMessage());
1473         // }
1474     }
1475 
1476     public void setId(String id)
1477     {
1478         this.id = id;
1479     }
1480 
1481     public String getId()
1482     {
1483         return id;
1484     }
1485 
1486     /**
1487      * Sets the security manager used by this Mule instance to authenticate and
1488      * authorise incoming and outgoing event traffic and service invocations
1489      * 
1490      * @param securityManager the security manager used by this Mule instance to
1491      *            authenticate and authorise incoming and outgoing event traffic and
1492      *            service invocations
1493      */
1494     public void setSecurityManager(UMOSecurityManager securityManager) throws InitialisationException
1495     {
1496         this.securityManager = securityManager;
1497         if (securityManager != null && isInitialised())
1498         {
1499             this.securityManager.initialise();
1500         }
1501     }
1502 
1503     /**
1504      * Gets the security manager used by this Mule instance to authenticate and
1505      * authorise incoming and outgoing event traffic and service invocations
1506      * 
1507      * @return he security manager used by this Mule instance to authenticate and
1508      *         authorise incoming and outgoing event traffic and service invocations
1509      */
1510     public UMOSecurityManager getSecurityManager()
1511     {
1512         return securityManager;
1513     }
1514 
1515     /**
1516      * Obtains a workManager instance that can be used to schedule work in a thread
1517      * pool. This will be used primarially by UMOAgents wanting to schedule work.
1518      * This work Manager must <b>never</b> be used by provider implementations as
1519      * they have their own workManager accessible on the connector. If a workManager
1520      * has not been set by the time the <code>initialise()</code> method has been
1521      * called a default <code>MuleWorkManager</code> will be created using the
1522      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
1523      * object.
1524      * 
1525      * @return a workManager instance used by the current MuleManager
1526      * @see org.mule.config.ThreadingProfile
1527      * @see MuleConfiguration
1528      */
1529     public UMOWorkManager getWorkManager()
1530     {
1531         return workManager;
1532     }
1533 
1534     /**
1535      * Obtains a workManager instance that can be used to schedule work in a thread
1536      * pool. This will be used primarially by UMOAgents wanting to schedule work.
1537      * This work Manager must <b>never</b> be used by provider implementations as
1538      * they have their own workManager accible on the connector. If a workManager has
1539      * not been set by the time the <code>initialise()</code> method has been
1540      * called a default <code>MuleWorkManager</code> will be created using the
1541      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
1542      * object.
1543      * 
1544      * @param workManager the workManager instance used by the current MuleManager
1545      * @throws IllegalStateException if the workManager has already been set.
1546      * @see org.mule.config.ThreadingProfile
1547      * @see MuleConfiguration
1548      * @see MuleWorkManager
1549      */
1550     public void setWorkManager(UMOWorkManager workManager)
1551     {
1552         if (this.workManager != null)
1553         {
1554             throw new IllegalStateException(CoreMessages.cannotSetObjectOnceItHasBeenSet("workManager")
1555                 .getMessage());
1556         }
1557         this.workManager = workManager;
1558     }
1559 
1560     public QueueManager getQueueManager()
1561     {
1562         return queueManager;
1563     }
1564 
1565     public void setQueueManager(QueueManager queueManager)
1566     {
1567         this.queueManager = queueManager;
1568     }
1569 }