View Javadoc

1   /*
2    * $Id: MuleManager.java 7976 2007-08-21 14:26:13Z 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  
14  import org.mule.config.ConfigurationException;
15  import org.mule.config.MuleConfiguration;
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.ClassUtils;
66  import org.mule.util.CollectionUtils;
67  import org.mule.util.SpiUtils;
68  import org.mule.util.StringMessageUtils;
69  import org.mule.util.StringUtils;
70  import org.mule.util.UUID;
71  import org.mule.util.queue.CachingPersistenceStrategy;
72  import org.mule.util.queue.QueueManager;
73  import org.mule.util.queue.QueuePersistenceStrategy;
74  import org.mule.util.queue.TransactionalQueueManager;
75  
76  import java.net.InetAddress;
77  import java.net.UnknownHostException;
78  import java.nio.charset.Charset;
79  import java.util.ArrayList;
80  import java.util.Collection;
81  import java.util.Collections;
82  import java.util.Date;
83  import java.util.HashMap;
84  import java.util.Iterator;
85  import java.util.LinkedHashMap;
86  import java.util.List;
87  import java.util.Map;
88  import java.util.jar.Manifest;
89  
90  import javax.transaction.TransactionManager;
91  
92  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
93  import org.apache.commons.collections.MapUtils;
94  import org.apache.commons.collections.list.CursorableLinkedList;
95  import org.apache.commons.logging.Log;
96  import org.apache.commons.logging.LogFactory;
97  
98  /**
99   * <code>MuleManager</code> maintains and provides services for a Mule instance.
100  */
101 public class MuleManager implements UMOManager
102 {
103     /**
104      * singleton instance
105      */
106     private static UMOManager instance = null;
107 
108     /**
109      * Default configuration
110      */
111     private static MuleConfiguration config = new MuleConfiguration();
112 
113     /**
114      * Connectors registry
115      */
116     private Map connectors = new HashMap();
117 
118     /**
119      * Endpoints registry
120      *
121      * @deprecated endpoint-identifiers have been deprecated in favor of 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      * Holds a reference to the deamon running the Manager if any
192      */
193     private static MuleServer server = null;
194 
195     /**
196      * Maintains a reference to any interceptor stacks configured on the manager
197      */
198     private Map interceptorsMap = new HashMap();
199 
200     /**
201      * the date in milliseconds from when the server was started
202      */
203     private long startDate = 0;
204 
205     /**
206      * stats used for management
207      */
208     private AllStatistics stats = new AllStatistics();
209 
210     /**
211      * Manages all Server event notificationManager
212      */
213     private ServerNotificationManager notificationManager = null;
214 
215     private MultiContainerContext containerContext = null;
216 
217     private UMOSecurityManager securityManager;
218 
219     /**
220      * The queue manager to use for component queues and vm connector
221      */
222     private QueueManager queueManager;
223 
224     private UMOWorkManager workManager;
225 
226     /**
227      * logger used by this class
228      */
229     private static Log logger = LogFactory.getLog(MuleManager.class);
230 
231     private ShutdownContext shutdownContext = new ShutdownContext(true, null);
232 
233     /**
234      * Default Constructor
235      */
236     private MuleManager()
237     {
238         if (config == null)
239         {
240             config = new MuleConfiguration();
241         }
242         containerContext = new MultiContainerContext();
243         securityManager = new MuleSecurityManager();
244         Runtime.getRuntime().addShutdownHook(new ShutdownThread());
245 
246         // create the event manager
247         notificationManager = new ServerNotificationManager();
248         notificationManager.registerEventType(ManagerNotification.class, ManagerNotificationListener.class);
249         notificationManager.registerEventType(ModelNotification.class, ModelNotificationListener.class);
250         notificationManager.registerEventType(ComponentNotification.class,
251             ComponentNotificationListener.class);
252         notificationManager.registerEventType(SecurityNotification.class, SecurityNotificationListener.class);
253         notificationManager.registerEventType(ManagementNotification.class,
254             ManagementNotificationListener.class);
255         notificationManager.registerEventType(AdminNotification.class, AdminNotificationListener.class);
256         notificationManager.registerEventType(CustomNotification.class, CustomNotificationListener.class);
257         notificationManager.registerEventType(ConnectionNotification.class,
258             ConnectionNotificationListener.class);
259         notificationManager.registerEventType(ExceptionNotification.class, ExceptionNotificationListener.class);
260         notificationManager.registerEventType(TransactionNotification.class, TransactionNotificationListener.class);
261 
262         // TODO RM*: This is obviously just a workaround until extension modules can register
263         // their own classes for notifications. Need to revisit this when the
264         // ManagementContext is implemented properly.
265         try
266         {
267             Class spaceNotificationClass = ClassUtils.loadClass(
268                 "org.mule.impl.space.SpaceMonitorNotification", this.getClass());
269             Class spaceListenerClass = ClassUtils.loadClass(
270                 "org.mule.impl.space.SpaceMonitorNotificationListener", this.getClass());
271             notificationManager.registerEventType(spaceNotificationClass, spaceListenerClass);
272         }
273         catch (ClassNotFoundException cnf)
274         {
275             // ignore - apparently not available
276         }
277     }
278 
279     /**
280      * Getter method for the current singleton MuleManager
281      *
282      * @return the current singleton MuleManager
283      */
284     public static synchronized UMOManager getInstance()
285     {
286         if (instance == null)
287         {
288             logger.info("Creating new MuleManager instance");
289 
290             Class clazz = SpiUtils.findService(UMOManager.class, MuleManager.class.getName(),
291                 MuleManager.class);
292             try
293             {
294                 //There should always be a defualt system model registered
295                 instance = (UMOManager) clazz.newInstance();
296                 registerSystemModel(config.getSystemModelType());
297             }
298             catch (Exception e)
299             {
300                 throw new MuleRuntimeException(
301                     CoreMessages.failedToCreateManagerInstance(clazz.getName()), e);
302             }
303         }
304 
305         return instance;
306     }
307 
308     /**
309      * A static method to determine if there is an instance of the MuleManager. This
310      * should be used instead of <code>
311      * if(MuleManager.getInstance()!=null)
312      * </code>
313      * because getInstance never returns a null. If an istance is not available one
314      * is created. This method queries the instance directly.
315      *
316      * @return true if the manager is instanciated
317      */
318     public static synchronized boolean isInstanciated()
319     {
320         return (instance != null);
321     }
322 
323     /**
324      * Sets the current singleton MuleManager
325      *
326      * @deprecated this will go away soon.
327      */
328     public static synchronized void setInstance(UMOManager manager)
329     {
330         instance = manager;
331         if (instance == null)
332         {
333             config = new MuleConfiguration();
334         }
335     }
336 
337     /**
338      * Gets all statisitcs for this instance
339      *
340      * @return all statisitcs for this instance
341      */
342     public AllStatistics getStatistics()
343     {
344         return stats;
345     }
346 
347     /**
348      * Sets statistics on this instance
349      *
350      * @param stat
351      */
352     public void setStatistics(AllStatistics stat)
353     {
354         this.stats = stat;
355     }
356 
357     /**
358      * @return the MuleConfiguration for this MuleManager. This object is immutable
359      *         once the manager has initialised.
360      */
361     public static synchronized MuleConfiguration getConfiguration()
362     {
363         return config;
364     }
365 
366     /**
367      * Sets the configuration for the <code>MuleManager</code>.
368      *
369      * @param config the configuration object
370      * @throws IllegalAccessError if the <code>MuleManager</code> has already been
371      *             initialised.
372      * @deprecated this will go away soon.
373      */
374     public static synchronized void setConfiguration(MuleConfiguration config) throws UMOException
375     {
376         if (config == null)
377         {
378             throw new IllegalArgumentException(
379                 CoreMessages.objectIsNull("MuleConfiguration object").getMessage());
380         }
381 
382         MuleManager.config = config;
383         // TODO this call might cause a problem, but the whole setConfiguration() method is doomed anyway
384         registerSystemModel(config.getSystemModelType());
385 
386     }
387 
388     protected static void registerSystemModel(String type) throws UMOException
389     {
390         if (instance != null)
391         {
392             //Initialise the system model
393             UMOModel model = instance.lookupModel(type);
394             if (model != null && model.getComponentNames().hasNext())
395             {
396                 throw new IllegalStateException("System model is already registered and contains components. Cannot overwrite");
397             }
398             model = ModelFactory.createModel(config.getSystemModelType());
399             model.setName(ModelHelper.SYSTEM_MODEL);
400             instance.registerModel(model);
401         }
402     }
403 
404     // Implementation methods
405     // -------------------------------------------------------------------------
406 
407     /**
408      * Destroys the MuleManager and all resources it maintains
409      */
410     public synchronized void dispose()
411     {
412         if (disposed.get())
413         {
414             return;
415         }
416         try
417         {
418             if (started.get())
419             {
420                 stop();
421             }
422         }
423         catch (UMOException e)
424         {
425             // TODO MULE-863: What should we really do?
426             logger.error("Failed to stop manager: " + e.getMessage(), e);
427         }
428         disposed.set(true);
429         disposeConnectors();
430 
431         for (Iterator i = models.values().iterator(); i.hasNext();)
432         {
433             UMOModel model = (UMOModel) i.next();
434             model.dispose();
435         }
436 
437         disposeAgents();
438 
439         transformers.clear();
440         endpoints.clear();
441         endpointIdentifiers.clear();
442         containerContext.dispose();
443         containerContext = null;
444         // props.clear();
445         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSED));
446 
447         transformers = null;
448         endpoints = null;
449         endpointIdentifiers = null;
450         // props = null;
451         initialised.set(false);
452         if (notificationManager != null)
453         {
454             notificationManager.dispose();
455         }
456         if (workManager != null)
457         {
458             workManager.dispose();
459         }
460 
461         if (queueManager != null)
462         {
463             queueManager.close();
464             queueManager = null;
465         }
466 
467         if ((startDate > 0) && logger.isInfoEnabled())
468         {
469             logger.info(this.getEndSplash());
470         }
471 
472         config = new MuleConfiguration();
473         instance = null;
474     }
475 
476     /**
477      * Destroys all connectors
478      */
479     private synchronized void disposeConnectors()
480     {
481         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSING_CONNECTORS));
482         for (Iterator iterator = connectors.values().iterator(); iterator.hasNext();)
483         {
484             UMOConnector c = (UMOConnector) iterator.next();
485             c.dispose();
486         }
487         fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_DISPOSED_CONNECTORS));
488     }
489 
490     /**
491      * {@inheritDoc}
492      */
493     public Object getProperty(Object key)
494     {
495         return applicationProps.get(key);
496     }
497 
498     /**
499      * {@inheritDoc}
500      */
501     public Map getProperties()
502     {
503         return applicationProps;
504     }
505 
506     /**
507      * {@inheritDoc}
508      */
509     public TransactionManager getTransactionManager()
510     {
511         return transactionManager;
512     }
513 
514     /**
515      * {@inheritDoc}
516      */
517     public UMOConnector lookupConnector(String name)
518     {
519         return (UMOConnector) connectors.get(name);
520     }
521 
522     /**
523      * {@inheritDoc}
524      *
525      * @deprecated endpoint-identifiers have been deprecated in favor of global-endpoints
526      */
527     public String lookupEndpointIdentifier(String logicalName, String defaultName)
528     {
529         String name = (String) endpointIdentifiers.get(logicalName);
530         if (name == null)
531         {
532             return defaultName;
533         }
534         return name;
535     }
536 
537     /**
538      * {@inheritDoc}
539      */
540     public UMOEndpoint lookupEndpoint(String logicalName)
541     {
542         UMOEndpoint endpoint = (UMOEndpoint) endpoints.get(logicalName);
543         if (endpoint != null)
544         {
545             return (UMOEndpoint) endpoint.clone();
546         }
547         else
548         {
549             return null;
550         }
551     }
552 
553     /**
554      * {@inheritDoc}
555      */
556     public UMOEndpoint lookupEndpointByAddress(String address)
557     {
558         UMOEndpoint endpoint = null;
559         if (address != null)
560         {
561             boolean found = false;
562             Iterator iterator = endpoints.keySet().iterator();
563             while (!found && iterator.hasNext())
564             {
565                 endpoint = (UMOEndpoint) endpoints.get(iterator.next());
566                 found = (address.equals(endpoint.getEndpointURI().toString()));
567             }
568         }
569         return endpoint;
570     }
571 
572     /**
573      * {@inheritDoc}
574      */
575     public UMOTransformer lookupTransformer(String name)
576     {
577         UMOTransformer trans = (UMOTransformer) transformers.get(name);
578         if (trans != null)
579         {
580             try
581             {
582                 return (UMOTransformer) trans.clone();
583             }
584             catch (Exception e)
585             {
586                 throw new MuleRuntimeException(
587                         CoreMessages.failedToClone("Transformer: " + trans.getName()), e);
588             }
589         }
590         return null;
591     }
592 
593     /**
594      * {@inheritDoc}
595      */
596     public void registerConnector(UMOConnector connector) throws UMOException
597     {
598         connectors.put(connector.getName(), connector);
599         if (initialised.get() || initialising.get())
600         {
601             connector.initialise();
602         }
603         if ((started.get() || starting.get()) && !connector.isStarted())
604         {
605             connector.startConnector();
606         }
607     }
608 
609     /**
610      * {@inheritDoc}
611      */
612     public void unregisterConnector(String connectorName) throws UMOException
613     {
614         UMOConnector c = (UMOConnector) connectors.remove(connectorName);
615         if (c != null)
616         {
617             c.dispose();
618         }
619     }
620 
621     /**
622      * {@inheritDoc}
623      *
624      * @deprecated endpoint-identifiers have been deprecated in favor of global-endpoints
625      */
626     public void registerEndpointIdentifier(String logicalName, String endpoint)
627     {
628         endpointIdentifiers.put(logicalName, endpoint);
629     }
630 
631     /**
632      * {@inheritDoc}
633      *
634      * @deprecated endpoint-identifiers have been deprecated in favor of global-endpoints
635      */
636     public void unregisterEndpointIdentifier(String logicalName)
637     {
638         endpointIdentifiers.remove(logicalName);
639     }
640 
641     /**
642      * {@inheritDoc}
643      */
644     public void registerEndpoint(UMOEndpoint endpoint)
645     {
646         endpoints.put(endpoint.getName(), endpoint);
647     }
648 
649     /**
650      * {@inheritDoc}
651      */
652     public void unregisterEndpoint(String endpointName)
653     {
654         UMOEndpoint p = (UMOEndpoint) endpoints.get(endpointName);
655         if (p != null)
656         {
657             endpoints.remove(p);
658         }
659     }
660 
661     /**
662      * {@inheritDoc}
663      */
664     public void registerTransformer(UMOTransformer transformer) throws InitialisationException
665     {
666         transformer.initialise();
667         transformers.put(transformer.getName(), transformer);
668         logger.info("Transformer " + transformer.getName() + " has been initialised successfully");
669     }
670 
671     /**
672      * {@inheritDoc}
673      */
674     public void unregisterTransformer(String transformerName)
675     {
676         transformers.remove(transformerName);
677     }
678 
679     /**
680      * {@inheritDoc}
681      */
682     public void setProperty(Object key, Object value)
683     {
684         applicationProps.put(key, value);
685     }
686 
687     public void addProperties(Map props)
688     {
689         applicationProps.putAll(props);
690     }
691 
692     /**
693      * {@inheritDoc}
694      */
695     public void setTransactionManager(TransactionManager newManager) throws UMOException
696     {
697         if (transactionManager != null)
698         {
699             throw new ConfigurationException(CoreMessages.transactionManagerAlreadySet());
700         }
701         transactionManager = newManager;
702     }
703 
704     /**
705      * {@inheritDoc}
706      */
707     public synchronized void initialise() throws UMOException
708     {
709         validateEncoding();
710         validateOSEncoding();
711 
712         if (!initialised.get())
713         {
714             initialising.set(true);
715             startDate = System.currentTimeMillis();
716             // if no work manager has been set create a default one
717             if (workManager == null)
718             {
719                 ThreadingProfile tp = config.getDefaultThreadingProfile();
720                 logger.debug("Creating default work manager using default threading profile: " + tp);
721                 workManager = new MuleWorkManager(tp, "UMOManager");
722                 workManager.start();
723             }
724 
725             // Start the event manager
726             notificationManager.start(workManager);
727 
728             // Fire message notifications if the option is set. This will fire
729             // inbound and outbound message events that can
730             // consume resources in high throughput systems
731             if (config.isEnableMessageEvents())
732             {
733                 notificationManager.registerEventType(MessageNotification.class,
734                     MessageNotificationListener.class);
735             }
736 
737             fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_INITIALISNG));
738             if (id == null)
739             {
740                 logger.warn("No unique id has been set on this manager");
741             }
742 
743 
744             try
745             {
746                 if (securityManager != null)
747                 {
748                     securityManager.initialise();
749                 }
750                 if (queueManager == null)
751                 {
752                     try
753                     {
754                         TransactionalQueueManager queueMgr = new TransactionalQueueManager();
755                         QueuePersistenceStrategy ps = new CachingPersistenceStrategy(
756                             getConfiguration().getPersistenceStrategy());
757                         queueMgr.setPersistenceStrategy(ps);
758                         queueManager = queueMgr;
759                     }
760                     catch (Exception e)
761                     {
762                         throw new InitialisationException(
763                             CoreMessages.initialisationFailure("QueueManager"), e);
764                     }
765                 }
766 
767                 initialiseConnectors();
768                 initialiseEndpoints();
769                 initialiseAgents();
770                 for (Iterator i = models.values().iterator(); i.hasNext();)
771                 {
772                     UMOModel model = (UMOModel) i.next();
773                     model.initialise();
774                 }
775 
776             }
777             finally
778             {
779                 initialised.set(true);
780                 initialising.set(false);
781                 fireSystemEvent(new ManagerNotification(this, ManagerNotification.MANAGER_INITIALISED));
782             }
783         }
784     }
785 
786     protected void validateEncoding() throws FatalException
787     {
788         String encoding = System.getProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY);
789         if (encoding == null)
790         {
791             encoding = config.getEncoding();
792             System.setProperty(MuleProperties.MULE_ENCODING_SYSTEM_PROPERTY, encoding);
793         }
794         else
795         {
796             config.setEncoding(encoding);
797         }
798         // Check we have a valid and supported encoding
799         if (!Charset.isSupported(config.getEncoding()))
800         {
801             throw new FatalException(
802                 CoreMessages.propertyHasInvalidValue("encoding", config.getEncoding()), this);
803         }
804     }
805 
806     protected void validateOSEncoding() throws FatalException
807     {
808         String encoding = System.getProperty(MuleProperties.MULE_OS_ENCODING_SYSTEM_PROPERTY);
809         if (encoding == null)
810         {
811             encoding = config.getOSEncoding();
812             System.setProperty(MuleProperties.MULE_OS_ENCODING_SYSTEM_PROPERTY, encoding);
813         }
814         else
815         {
816             config.setOSEncoding(encoding);
817         }
818         // Check we have a valid and supported encoding
819         if (!Charset.isSupported(config.getOSEncoding()))
820         {
821             throw new FatalException(
822                 CoreMessages.propertyHasInvalidValue("osEncoding", config.getOSEncoding()), 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     /**
995      * If the <code>MuleManager</code> was started from the <code>MuleServer</code>
996      * daemon then this will be called by the Server
997      *
998      * @param server a reference to the <code>MuleServer</code>.
999      */
1000     void setServer(MuleServer server)
1001     {
1002         MuleManager.server = server;
1003     }
1004 
1005     /**
1006      * Shuts down the whole server tring to shut down all resources cleanly on the
1007      * way
1008      *
1009      * @param e an exception that caused the <code>shutdown()</code> method to be
1010      *            called. If e is null the shutdown message will just display a time
1011      *            when the server was shutdown. Otherwise the exception information
1012      *            will also be displayed.
1013      */
1014     public void shutdown(Throwable e, boolean aggressive)
1015     {
1016         shutdownContext = new ShutdownContext(aggressive, e);
1017         System.exit(0);
1018     }
1019 
1020     public UMOModel lookupModel(String name)
1021     {
1022         return (UMOModel) models.get(name);
1023     }
1024 
1025     public void registerModel(UMOModel model) throws UMOException
1026     {
1027         models.put(model.getName(), model);
1028         if (initialised.get())
1029         {
1030             model.initialise();
1031         }
1032 
1033         if (started.get())
1034         {
1035             model.start();
1036         }
1037     }
1038 
1039     public void unregisterModel(String name)
1040     {
1041         UMOModel model = lookupModel(name);
1042         if (model != null)
1043         {
1044             models.remove(model);
1045             model.dispose();
1046         }
1047     }
1048 
1049     public Map getModels()
1050     {
1051         return Collections.unmodifiableMap(models);
1052     }
1053 
1054     /**
1055      * {@inheritDoc}
1056      */
1057     public void registerInterceptorStack(String name, UMOInterceptorStack stack)
1058     {
1059         interceptorsMap.put(name, stack);
1060     }
1061 
1062     /**
1063      * {@inheritDoc}
1064      */
1065     public UMOInterceptorStack lookupInterceptorStack(String name)
1066     {
1067         return (UMOInterceptorStack) interceptorsMap.get(name);
1068     }
1069 
1070     /**
1071      * {@inheritDoc}
1072      */
1073     public Map getConnectors()
1074     {
1075         return Collections.unmodifiableMap(connectors);
1076     }
1077 
1078     /**
1079      * {@inheritDoc}
1080      *
1081      * @deprecated endpoint-identifiers have been deprecated in favor of global-endpoints
1082      */
1083     public Map getEndpointIdentifiers()
1084     {
1085         return Collections.unmodifiableMap(endpointIdentifiers);
1086     }
1087 
1088     /**
1089      * {@inheritDoc}
1090      */
1091     public Map getEndpoints()
1092     {
1093         return Collections.unmodifiableMap(endpoints);
1094     }
1095 
1096     /**
1097      * {@inheritDoc}
1098      */
1099     public Map getTransformers()
1100     {
1101         return Collections.unmodifiableMap(transformers);
1102     }
1103 
1104     /**
1105      * {@inheritDoc}
1106      */
1107     public boolean isStarted()
1108     {
1109         return started.get();
1110     }
1111 
1112     /**
1113      * {@inheritDoc}
1114      */
1115     public boolean isInitialised()
1116     {
1117         return initialised.get();
1118     }
1119 
1120     /**
1121      * Determines if the server is currently initialising
1122      *
1123      * @return true if if the server is currently initialising, false otherwise
1124      */
1125     public boolean isInitialising()
1126     {
1127         return initialising.get();
1128     }
1129 
1130     /**
1131      * Determines in the manager is in the process of stopping.
1132      */
1133     public boolean isStopping()
1134     {
1135         return stopping.get();
1136     }
1137 
1138     /**
1139      * {@inheritDoc}
1140      */
1141     public long getStartDate()
1142     {
1143         return startDate;
1144     }
1145 
1146     /**
1147      * Returns a formatted string that is a summary of the configuration of the
1148      * server. This is the brock of information that gets displayed when the server
1149      * starts
1150      *
1151      * @return a string summary of the server information
1152      */
1153     private String getStartSplash()
1154     {
1155         String notset = CoreMessages.notSet().getMessage();
1156 
1157         // Mule Version, Timestamp, and Server ID
1158         List message = new ArrayList();
1159         Manifest mf = config.getManifest();
1160         Map att = mf.getMainAttributes();
1161         if (att.values().size() > 0)
1162         {
1163             message.add(StringUtils.defaultString(config.getProductDescription(), notset) + " "
1164                         + CoreMessages.version().getMessage() + " "
1165                         + StringUtils.defaultString(config.getProductVersion(), notset));
1166 
1167             message.add(StringUtils.defaultString(config.getVendorName(), notset));
1168             message.add(StringUtils.defaultString(config.getProductMoreInfo(), notset));
1169         }
1170         else
1171         {
1172             message.add(CoreMessages.versionNotSet().getMessage());
1173         }
1174         message.add(" ");
1175         message.add(CoreMessages.serverStartedAt(this.getStartDate()));
1176         message.add("Server ID: " + id);
1177 
1178         // JDK, OS, and Host
1179         message.add("JDK: " + System.getProperty("java.version") + " (" + System.getProperty("java.vm.info")
1180                     + ")");
1181         String patch = System.getProperty("sun.os.patch.level", null);
1182         message.add("OS: " + System.getProperty("os.name")
1183                     + (patch != null && !"unknown".equalsIgnoreCase(patch) ? " - " + patch : "") + " ("
1184                     + System.getProperty("os.version") + ", " + System.getProperty("os.arch") + ")");
1185         try
1186         {
1187             InetAddress host = InetAddress.getLocalHost();
1188             message.add("Host: " + host.getHostName() + " (" + host.getHostAddress() + ")");
1189         }
1190         catch (UnknownHostException e)
1191         {
1192             // ignore
1193         }
1194 
1195         // Mule Agents
1196         message.add(" ");
1197         if (agents.size() == 0)
1198         {
1199             message.add(CoreMessages.agentsRunning().getMessage() + " "
1200                 + CoreMessages.none());
1201         }
1202         else
1203         {
1204             message.add(CoreMessages.agentsRunning());
1205             UMOAgent umoAgent;
1206             for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1207             {
1208                 umoAgent = (UMOAgent) iterator.next();
1209                 message.add("  " + umoAgent.getDescription());
1210             }
1211         }
1212         return StringMessageUtils.getBoilerPlate(message, '*', 70);
1213     }
1214 
1215     private String getEndSplash()
1216     {
1217         List message = new ArrayList(2);
1218         long currentTime = System.currentTimeMillis();
1219         message.add(CoreMessages.shutdownNormally(new Date()));
1220         long duration = 10;
1221         if (startDate > 0)
1222         {
1223             duration = currentTime - startDate;
1224         }
1225         message.add(CoreMessages.serverWasUpForDuration(duration));
1226 
1227         return StringMessageUtils.getBoilerPlate(message, '*', 78);
1228     }
1229 
1230     /**
1231      * {@inheritDoc}
1232      */
1233     public void registerAgent(UMOAgent agent) throws UMOException
1234     {
1235         agents.put(agent.getName(), agent);
1236         agent.registered();
1237         // Don't allow initialisation while the server is being initalised,
1238         // only when we are done. Otherwise the agent registration
1239         // order can be corrupted.
1240         if (initialised.get())
1241         {
1242             agent.initialise();
1243         }
1244         if ((started.get() || starting.get()))
1245         {
1246             agent.start();
1247         }
1248     }
1249 
1250     public UMOAgent lookupAgent(String name)
1251     {
1252         return (UMOAgent) agents.get(name);
1253     }
1254 
1255     /**
1256      * {@inheritDoc}
1257      */
1258     public UMOAgent unregisterAgent(String name) throws UMOException
1259     {
1260         if (name == null)
1261         {
1262             return null;
1263         }
1264         UMOAgent agent = (UMOAgent) agents.remove(name);
1265         if (agent != null)
1266         {
1267             agent.dispose();
1268             agent.unregistered();
1269         }
1270         return agent;
1271     }
1272 
1273     /**
1274      * Initialises all registered agents
1275      *
1276      * @throws InitialisationException
1277      */
1278     protected void initialiseAgents() throws InitialisationException
1279     {
1280         logger.info("Initialising agents...");
1281 
1282         // Do not iterate over the map directly, as 'complex' agents
1283         // may spawn extra agents during initialisation. This will
1284         // cause a ConcurrentModificationException.
1285         // Use a cursorable iteration, which supports on-the-fly underlying
1286         // data structure changes.
1287         Collection agentsSnapshot = agents.values();
1288         CursorableLinkedList agentRegistrationQueue = new CursorableLinkedList(agentsSnapshot);
1289         CursorableLinkedList.Cursor cursor = agentRegistrationQueue.cursor();
1290 
1291         // the actual agent object refs are the same, so we are just
1292         // providing different views of the same underlying data
1293 
1294         try
1295         {
1296             while (cursor.hasNext())
1297             {
1298                 UMOAgent umoAgent = (UMOAgent) cursor.next();
1299 
1300                 int originalSize = agentsSnapshot.size();
1301                 logger.debug("Initialising agent: " + umoAgent.getName());
1302                 umoAgent.initialise();
1303                 // thank you, we are done with you
1304                 cursor.remove();
1305 
1306                 // Direct calls to MuleManager.registerAgent() modify the original
1307                 // agents map, re-check if the above agent registered any
1308                 // 'child' agents.
1309                 int newSize = agentsSnapshot.size();
1310                 int delta = newSize - originalSize;
1311                 if (delta > 0)
1312                 {
1313                     // TODO there's some mess going on in
1314                     // http://issues.apache.org/jira/browse/COLLECTIONS-219
1315                     // watch out when upgrading the commons-collections.
1316                     Collection tail = CollectionUtils.retainAll(agentsSnapshot, agentRegistrationQueue);
1317                     Collection head = CollectionUtils.subtract(agentsSnapshot, tail);
1318 
1319                     // again, above are only refs, all going back to the original agents map
1320 
1321                     // re-order the queue
1322                     agentRegistrationQueue.clear();
1323                     // 'spawned' agents first
1324                     agentRegistrationQueue.addAll(head);
1325                     // and the rest
1326                     agentRegistrationQueue.addAll(tail);
1327 
1328                     // update agents map with a new order in case we want to re-initialise
1329                     // MuleManager on the fly
1330                     this.agents.clear();
1331                     for (Iterator it = agentRegistrationQueue.iterator(); it.hasNext();)
1332                     {
1333                         UMOAgent theAgent = (UMOAgent) it.next();
1334                         this.agents.put(theAgent.getName(), theAgent);
1335                     }
1336                 }
1337             }
1338         }
1339         finally
1340         {
1341             // close the cursor as per JavaDoc
1342             cursor.close();
1343         }
1344         logger.info("Agents Successfully Initialised");
1345     }
1346 
1347     /**
1348      * {@inheritDoc}
1349      */
1350     protected void startAgents() throws UMOException
1351     {
1352         UMOAgent umoAgent;
1353         logger.info("Starting agents...");
1354         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1355         {
1356             umoAgent = (UMOAgent) iterator.next();
1357             logger.info("Starting agent: " + umoAgent.getDescription());
1358             umoAgent.start();
1359 
1360         }
1361         logger.info("Agents Successfully Started");
1362     }
1363 
1364     /**
1365      * {@inheritDoc}
1366      */
1367     protected void stopAgents() throws UMOException
1368     {
1369         logger.info("Stopping agents...");
1370         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1371         {
1372             UMOAgent umoAgent = (UMOAgent) iterator.next();
1373             logger.debug("Stopping agent: " + umoAgent.getName());
1374             umoAgent.stop();
1375         }
1376         logger.info("Agents Successfully Stopped");
1377     }
1378 
1379     /**
1380      * {@inheritDoc}
1381      */
1382     protected void disposeAgents()
1383     {
1384         UMOAgent umoAgent;
1385         logger.info("disposing agents...");
1386         for (Iterator iterator = agents.values().iterator(); iterator.hasNext();)
1387         {
1388             umoAgent = (UMOAgent) iterator.next();
1389             logger.debug("Disposing agent: " + umoAgent.getName());
1390             umoAgent.dispose();
1391         }
1392         logger.info("Agents Successfully Disposed");
1393     }
1394 
1395     /**
1396      * associates a Dependency Injector container or Jndi container with Mule. This
1397      * can be used to integrate container managed resources with Mule resources
1398      *
1399      * @param container a Container context to use. By default, there is a default
1400      *            Mule container <code>MuleContainerContext</code> that will assume
1401      *            that the reference key for an oblect is a classname and will try to
1402      *            instanciate it.
1403      */
1404     public void setContainerContext(UMOContainerContext container) throws UMOException
1405     {
1406         if (container == null)
1407         {
1408             if (containerContext != null)
1409             {
1410                 containerContext.dispose();
1411             }
1412             containerContext = new MultiContainerContext();
1413         }
1414         else
1415         {
1416             container.initialise();
1417             containerContext.addContainer(container);
1418         }
1419     }
1420 
1421     /**
1422      * associates a Dependency Injector container with Mule. This can be used to
1423      * integrate container managed resources with Mule resources
1424      *
1425      * @return the container associated with the Manager
1426      */
1427     public UMOContainerContext getContainerContext()
1428     {
1429         return containerContext;
1430     }
1431 
1432     /**
1433      * {@inheritDoc}
1434      */
1435     public void registerListener(UMOServerNotificationListener l) throws NotificationException
1436     {
1437         registerListener(l, null);
1438     }
1439 
1440     public void registerListener(UMOServerNotificationListener l, String resourceIdentifier)
1441         throws NotificationException
1442     {
1443         if (notificationManager == null)
1444         {
1445             throw new NotificationException(CoreMessages.serverEventManagerNotEnabled());
1446         }
1447         notificationManager.registerListener(l, resourceIdentifier);
1448     }
1449 
1450     /**
1451      * {@inheritDoc}
1452      */
1453     public void unregisterListener(UMOServerNotificationListener l)
1454     {
1455         if (notificationManager != null)
1456         {
1457             notificationManager.unregisterListener(l);
1458         }
1459     }
1460 
1461     /**
1462      * Fires a mule 'system' event. These are notifications that are fired because
1463      * something within the Mule instance happened such as the Model started or the
1464      * server is being disposed.
1465      *
1466      * @param e the event that occurred
1467      */
1468     protected void fireSystemEvent(UMOServerNotification e)
1469     {
1470         if (notificationManager != null)
1471         {
1472             notificationManager.fireEvent(e);
1473         }
1474         else if (logger.isDebugEnabled())
1475         {
1476             logger.debug("Event Manager is not enabled, ignoring event: " + e);
1477         }
1478     }
1479 
1480     /**
1481      * Fires a server notification to all registered
1482      * {@link org.mule.impl.internal.notifications.CustomNotificationListener}
1483      * notificationManager.
1484      *
1485      * TODO RM: This method now duplicates #fireSystemEvent() completely
1486      *
1487      * @param notification the notification to fire. This must be of type
1488      *            {@link org.mule.impl.internal.notifications.CustomNotification}
1489      *            otherwise an exception will be thrown.
1490      * @throws UnsupportedOperationException if the notification fired is not a
1491      *             {@link org.mule.impl.internal.notifications.CustomNotification}
1492      */
1493     public void fireNotification(UMOServerNotification notification)
1494     {
1495         // if(notification instanceof CustomNotification) {
1496         if (notificationManager != null)
1497         {
1498             notificationManager.fireEvent(notification);
1499         }
1500         else if (logger.isDebugEnabled())
1501         {
1502             logger.debug("Event Manager is not enabled, ignoring notification: " + notification);
1503         }
1504         // } else {
1505         // throw new UnsupportedOperationException(new
1506         // Message(Messages.ONLY_CUSTOM_EVENTS_CAN_BE_FIRED).getMessage());
1507         // }
1508     }
1509 
1510     public void setId(String id)
1511     {
1512         this.id = id;
1513     }
1514 
1515     public String getId()
1516     {
1517         return id;
1518     }
1519 
1520     /**
1521      * Sets the security manager used by this Mule instance to authenticate and
1522      * authorise incoming and outgoing event traffic and service invocations
1523      *
1524      * @param securityManager the security manager used by this Mule instance to
1525      *            authenticate and authorise incoming and outgoing event traffic and
1526      *            service invocations
1527      */
1528     public void setSecurityManager(UMOSecurityManager securityManager) throws InitialisationException
1529     {
1530         this.securityManager = securityManager;
1531         if (securityManager != null && isInitialised())
1532         {
1533             this.securityManager.initialise();
1534         }
1535     }
1536 
1537     /**
1538      * Gets the security manager used by this Mule instance to authenticate and
1539      * authorise incoming and outgoing event traffic and service invocations
1540      *
1541      * @return he security manager used by this Mule instance to authenticate and
1542      *         authorise incoming and outgoing event traffic and service invocations
1543      */
1544     public UMOSecurityManager getSecurityManager()
1545     {
1546         return securityManager;
1547     }
1548 
1549     /**
1550      * Obtains a workManager instance that can be used to schedule work in a thread
1551      * pool. This will be used primarially by UMOAgents wanting to schedule work.
1552      * This work Manager must <b>never</b> be used by provider implementations as
1553      * they have their own workManager accessible on the connector. If a workManager has
1554      * not been set by the time the <code>initialise()</code> method has been
1555      * called a default <code>MuleWorkManager</code> will be created using the
1556      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
1557      * object.
1558      *
1559      * @return a workManager instance used by the current MuleManager
1560      * @see org.mule.config.ThreadingProfile
1561      * @see MuleConfiguration
1562      */
1563     public UMOWorkManager getWorkManager()
1564     {
1565         return workManager;
1566     }
1567 
1568     /**
1569      * Obtains a workManager instance that can be used to schedule work in a thread
1570      * pool. This will be used primarially by UMOAgents wanting to schedule work.
1571      * This work Manager must <b>never</b> be used by provider implementations as
1572      * they have their own workManager accible on the connector. If a workManager has
1573      * not been set by the time the <code>initialise()</code> method has been
1574      * called a default <code>MuleWorkManager</code> will be created using the
1575      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
1576      * object.
1577      *
1578      * @param workManager the workManager instance used by the current MuleManager
1579      * @throws IllegalStateException if the workManager has already been set.
1580      * @see org.mule.config.ThreadingProfile
1581      * @see MuleConfiguration
1582      * @see MuleWorkManager
1583      */
1584     public void setWorkManager(UMOWorkManager workManager)
1585     {
1586         if (this.workManager != null)
1587         {
1588             throw new IllegalStateException(
1589                 CoreMessages.cannotSetObjectOnceItHasBeenSet("workManager").getMessage());
1590         }
1591         this.workManager = workManager;
1592     }
1593 
1594     public QueueManager getQueueManager()
1595     {
1596         return queueManager;
1597     }
1598 
1599     public void setQueueManager(QueueManager queueManager)
1600     {
1601         this.queueManager = queueManager;
1602     }
1603 
1604     /**
1605      * The shutdown thread used by the server when its main thread is terminated
1606      */
1607     private class ShutdownThread extends Thread
1608     {
1609         Throwable t;
1610         boolean aggressive = true;
1611 
1612         public ShutdownThread()
1613         {
1614             super();
1615             this.t = shutdownContext.getException();
1616             this.aggressive = shutdownContext.isAggressive();
1617         }
1618 
1619         /*
1620          * (non-Javadoc)
1621          *
1622          * @see java.lang.Runnable#run()
1623          */
1624         public void run()
1625         {
1626             dispose();
1627             if (!aggressive)
1628             {
1629                 // FIX need to check if there are any outstanding
1630                 // operations to be done?
1631             }
1632 
1633             if (server != null)
1634             {
1635                 if (t != null)
1636                 {
1637                     server.shutdown(t);
1638                 }
1639                 else
1640                 {
1641                     server.shutdown();
1642                 }
1643             }
1644         }
1645     }
1646 
1647     private class ShutdownContext
1648     {
1649         private boolean aggressive = false;
1650         private Throwable exception = null;
1651 
1652         public ShutdownContext(boolean aggressive, Throwable exception)
1653         {
1654             this.aggressive = aggressive;
1655             this.exception = exception;
1656         }
1657 
1658         public boolean isAggressive()
1659         {
1660             return aggressive;
1661         }
1662 
1663         public Throwable getException()
1664         {
1665             return exception;
1666         }
1667     }
1668 }