View Javadoc

1   /*
2    * $Id: DefaultMuleContext.java 20088 2010-11-05 16:51:41Z aperepel $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSoft, Inc.  All rights reserved.  http://www.mulesoft.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  package org.mule;
11  
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleException;
14  import org.mule.api.MuleRuntimeException;
15  import org.mule.api.client.LocalMuleClient;
16  import org.mule.api.config.MuleConfiguration;
17  import org.mule.api.config.MuleProperties;
18  import org.mule.api.config.ThreadingProfile;
19  import org.mule.api.context.MuleContextAware;
20  import org.mule.api.context.WorkManager;
21  import org.mule.api.context.notification.ServerNotification;
22  import org.mule.api.context.notification.ServerNotificationListener;
23  import org.mule.api.exception.SystemExceptionHandler;
24  import org.mule.api.expression.ExpressionManager;
25  import org.mule.api.lifecycle.Disposable;
26  import org.mule.api.lifecycle.Initialisable;
27  import org.mule.api.lifecycle.InitialisationException;
28  import org.mule.api.lifecycle.LifecycleManager;
29  import org.mule.api.lifecycle.Startable;
30  import org.mule.api.lifecycle.Stoppable;
31  import org.mule.api.registry.MuleRegistry;
32  import org.mule.api.registry.RegistrationException;
33  import org.mule.api.registry.Registry;
34  import org.mule.api.security.SecurityManager;
35  import org.mule.api.transaction.TransactionManagerFactory;
36  import org.mule.client.DefaultLocalMuleClient;
37  import org.mule.config.DefaultMuleConfiguration;
38  import org.mule.config.i18n.CoreMessages;
39  import org.mule.context.notification.MuleContextNotification;
40  import org.mule.context.notification.NotificationException;
41  import org.mule.context.notification.ServerNotificationManager;
42  import org.mule.exception.DefaultSystemExceptionStrategy;
43  import org.mule.expression.DefaultExpressionManager;
44  import org.mule.lifecycle.MuleContextLifecycleManager;
45  import org.mule.management.stats.AllStatistics;
46  import org.mule.registry.DefaultRegistryBroker;
47  import org.mule.registry.MuleRegistryHelper;
48  import org.mule.util.ApplicationShutdownSplashScreen;
49  import org.mule.util.ApplicationStartupSplashScreen;
50  import org.mule.util.ServerShutdownSplashScreen;
51  import org.mule.util.ServerStartupSplashScreen;
52  import org.mule.util.SplashScreen;
53  import org.mule.util.queue.QueueManager;
54  
55  import java.util.Collection;
56  
57  import javax.resource.spi.work.WorkListener;
58  import javax.transaction.TransactionManager;
59  
60  import org.apache.commons.logging.Log;
61  import org.apache.commons.logging.LogFactory;
62  
63  public class DefaultMuleContext implements MuleContext
64  {
65      /**
66       * logger used by this class
67       */
68      private transient Log logger = LogFactory.getLog(DefaultMuleContext.class);
69  
70      /**
71       * Internal registry facade which delegates to other registries.
72       */
73      private DefaultRegistryBroker registryBroker;
74  
75      /**
76       * Simplified Mule configuration interface
77       */
78      private MuleRegistry muleRegistryHelper;
79  
80      /**
81       * stats used for management
82       */
83      private AllStatistics stats = new AllStatistics();
84  
85      private WorkManager workManager;
86  
87      private WorkListener workListener;
88  
89      /**
90       * LifecycleManager for the MuleContext.  Note: this is NOT the same lifecycle manager
91       * as the one in the Registry.
92       */
93      protected MuleContextLifecycleManager lifecycleManager;
94  
95      protected ServerNotificationManager notificationManager;
96  
97      private MuleConfiguration config;
98  
99      /**
100      * the date in milliseconds from when the server was started
101      */
102     private long startDate;
103 
104     private ExpressionManager expressionManager;
105 
106     private ClassLoader executionClassLoader;
107     
108     protected LocalMuleClient localMuleClient;
109     
110     /** Global exception handler which handles "system" exceptions (i.e., when no message is involved). */
111     protected SystemExceptionHandler exceptionListener;
112 
113     public DefaultMuleContext(MuleConfiguration config,
114                               WorkManager workManager,
115                               WorkListener workListener,
116                               MuleContextLifecycleManager lifecycleManager,
117                               ServerNotificationManager notificationManager)
118     {
119         this.config = config;
120         ((MuleContextAware) config).setMuleContext(this);
121         this.workManager = workManager;
122         this.workListener = workListener;
123         this.lifecycleManager = lifecycleManager;
124         this.notificationManager = notificationManager;
125         this.notificationManager.setMuleContext(this);
126         //there is no point having this object configurable
127         this.expressionManager = new DefaultExpressionManager();
128         ((MuleContextAware) this.expressionManager).setMuleContext(this);
129         registryBroker = createRegistryBroker();
130         muleRegistryHelper = createRegistryHelper(registryBroker);
131         localMuleClient = new DefaultLocalMuleClient(this);
132         exceptionListener = new DefaultSystemExceptionStrategy(this);
133     }
134 
135     protected DefaultRegistryBroker createRegistryBroker()
136     {
137         return new DefaultRegistryBroker(this);
138     }
139 
140     protected MuleRegistry createRegistryHelper(DefaultRegistryBroker registry)
141     {
142         return new MuleRegistryHelper(registry, this);
143     }
144 
145     public synchronized void initialise() throws InitialisationException
146     {
147         lifecycleManager.checkPhase(Initialisable.PHASE_NAME);
148 
149         if (getNotificationManager() == null)
150         {
151             throw new MuleRuntimeException(
152                     CoreMessages.objectIsNull(MuleProperties.OBJECT_NOTIFICATION_MANAGER));
153         }
154         if (workManager == null)
155         {
156             throw new MuleRuntimeException(CoreMessages.objectIsNull("workManager"));
157         }
158 
159         try
160         {
161             // Initialize the helper, this only initialises the helper class and does not call the registry lifecycle manager
162             //The registry lifecycle is called below using 'getLifecycleManager().fireLifecycle(Initialisable.PHASE_NAME);'
163             muleRegistryHelper.initialise();
164 
165             //We need to start the work manager straight away since we need it to fire notifications
166             if (workManager instanceof MuleContextAware)
167             {
168                 MuleContextAware contextAware = (MuleContextAware) workManager;
169                 contextAware.setMuleContext(this);
170             }
171 
172             workManager.start();
173             getNotificationManager().start(workManager, workListener);
174             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_INITIALISING));
175             getLifecycleManager().fireLifecycle(Initialisable.PHASE_NAME);
176 
177             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_INITIALISED));
178         }
179         catch (Exception e)
180         {
181             throw new InitialisationException(e, this);
182         }
183     }
184 
185     public synchronized void start() throws MuleException
186     {
187         getLifecycleManager().checkPhase(Startable.PHASE_NAME);
188 
189         if (getSecurityManager() == null)
190         {
191             throw new MuleRuntimeException(CoreMessages.objectIsNull("securityManager"));
192         }
193         if (getQueueManager() == null)
194         {
195             throw new MuleRuntimeException(CoreMessages.objectIsNull("queueManager"));
196         }
197 
198         startDate = System.currentTimeMillis();
199 
200         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STARTING));
201         getLifecycleManager().fireLifecycle(Startable.PHASE_NAME);
202 
203 
204         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STARTED));
205 
206         if (logger.isInfoEnabled())
207         {
208             SplashScreen startupScreen = buildStartupSplash();
209             logger.info(startupScreen.toString());
210         }
211     }
212 
213     /**
214      * Stops the <code>MuleContext</code> which stops all sessions and
215      * connectors
216      *
217      * @throws MuleException if either any of the sessions or connectors fail to stop
218      */
219     public synchronized void stop() throws MuleException
220     {
221         getLifecycleManager().checkPhase(Stoppable.PHASE_NAME);
222         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STOPPING));
223         getLifecycleManager().fireLifecycle(Stoppable.PHASE_NAME);
224         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STOPPED));
225     }
226 
227     public synchronized void dispose()
228     {
229         if (isStarted())
230         {
231             try
232             {
233                 stop();
234             }
235             catch (MuleException e)
236             {
237                 logger.error("Failed to stop Mule context", e);
238             }
239         }
240 
241         getLifecycleManager().checkPhase(Disposable.PHASE_NAME);
242 
243         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_DISPOSING));
244 
245         try
246         {
247             getLifecycleManager().fireLifecycle(Disposable.PHASE_NAME);
248 
249             // THis is a little odd. I find the relationship between the MuleRegistry Helper and the registry broker, too much abstraction?
250             muleRegistryHelper.dispose();
251         }
252         catch (Exception e)
253         {
254             logger.debug("Failed to cleanly dispose Mule: " + e.getMessage(), e);
255         }
256 
257         notificationManager.fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_DISPOSED));
258 
259         notificationManager.dispose();
260         workManager.dispose();
261 
262         if ((getStartDate() > 0) && logger.isInfoEnabled())
263         {
264             SplashScreen shutdownScreen = buildShutdownSplash();
265             logger.info(shutdownScreen.toString());
266         }
267 
268         //registryBroker.dispose();
269 
270         setExecutionClassLoader(null);
271     }
272 
273     /**
274      * Determines if the server has been initialised
275      *
276      * @return true if the server has been initialised
277      */
278     public boolean isInitialised()
279     {
280         return getLifecycleManager().getState().isInitialised();
281     }
282 
283     /**
284      * Determines if the server is being initialised
285      *
286      * @return true if the server is beening initialised
287      */
288     public boolean isInitialising()
289     {
290         return getLifecycleManager().getState().isInitialising();
291     }
292 
293     public boolean isStopped()
294     {
295         return getLifecycleManager().getState().isStopped();
296     }
297 
298     public boolean isStopping()
299     {
300         return getLifecycleManager().getState().isStopping();
301     }
302 
303     /**
304      * Determines if the server has been started
305      *
306      * @return true if the server has been started
307      */
308     public boolean isStarted()
309     {
310         return getLifecycleManager().isPhaseComplete(Startable.PHASE_NAME);
311     }
312 
313     public boolean isStarting()
314     {
315         return getLifecycleManager().getState().isStarting();
316     }
317 
318     public boolean isDisposed()
319     {
320         return getLifecycleManager().getState().isDisposed();
321     }
322 
323     public boolean isDisposing()
324     {
325         return getLifecycleManager().getState().isDisposing();
326     }
327 
328     public LifecycleManager getLifecycleManager()
329     {
330         return lifecycleManager;
331     }
332 
333     /**
334      * Gets all statistics for this instance
335      *
336      * @return all statistics for this instance
337      */
338     public AllStatistics getStatistics()
339     {
340         return stats;
341     }
342 
343     public void registerListener(ServerNotificationListener l) throws NotificationException
344     {
345         registerListener(l, null);
346     }
347 
348     public void registerListener(ServerNotificationListener l, String resourceIdentifier) throws NotificationException
349     {
350         ServerNotificationManager notificationManager = getNotificationManager();
351         if (notificationManager == null)
352         {
353             throw new MuleRuntimeException(CoreMessages.serverNotificationManagerNotEnabled());
354         }
355         notificationManager.addListenerSubscription(l, resourceIdentifier);
356     }
357 
358     public void unregisterListener(ServerNotificationListener l)
359     {
360         ServerNotificationManager notificationManager = getNotificationManager();
361         if (notificationManager != null)
362         {
363             notificationManager.removeListener(l);
364         }
365     }
366 
367     /**
368      * Fires a server notification to all registered
369      * {@link org.mule.api.context.notification.CustomNotificationListener} notificationManager.
370      *
371      * @param notification the notification to fire. This must be of type
372      *                     {@link org.mule.context.notification.CustomNotification} otherwise an
373      *                     exception will be thrown.
374      * @throws UnsupportedOperationException if the notification fired is not a
375      *                                       {@link org.mule.context.notification.CustomNotification}
376      */
377     public void fireNotification(ServerNotification notification)
378     {
379         ServerNotificationManager notificationManager = getNotificationManager();
380         if (notificationManager != null)
381         {
382             notificationManager.fireNotification(notification);
383         }
384         else if (logger.isDebugEnabled())
385         {
386             logger.debug("MuleEvent Manager is not enabled, ignoring notification: " + notification);
387         }
388     }
389 
390     /**
391      * Sets the security manager used by this Mule instance to authenticate and
392      * authorise incoming and outgoing event traffic and service invocations
393      *
394      * @param securityManager the security manager used by this Mule instance to
395      *                        authenticate and authorise incoming and outgoing event traffic
396      *                        and service invocations
397      */
398     public void setSecurityManager(SecurityManager securityManager) throws RegistrationException
399     {
400         checkLifecycleForPropertySet(MuleProperties.OBJECT_SECURITY_MANAGER, Initialisable.PHASE_NAME);
401         registryBroker.registerObject(MuleProperties.OBJECT_SECURITY_MANAGER, securityManager);
402     }
403 
404     /**
405      * Gets the security manager used by this Mule instance to authenticate and
406      * authorise incoming and outgoing event traffic and service invocations
407      *
408      * @return he security manager used by this Mule instance to authenticate
409      *         and authorise incoming and outgoing event traffic and service
410      *         invocations
411      */
412     public SecurityManager getSecurityManager()
413     {
414         SecurityManager securityManager = (SecurityManager) registryBroker.lookupObject(MuleProperties.OBJECT_SECURITY_MANAGER);
415         if (securityManager == null)
416         {
417             Collection temp = registryBroker.lookupObjects(SecurityManager.class);
418             if (temp.size() > 0)
419             {
420                 securityManager = ((SecurityManager) temp.iterator().next());
421             }
422         }
423         return securityManager;
424     }
425 
426     /**
427      * Obtains a workManager instance that can be used to schedule work in a
428      * thread pool. This will be used primarially by Agents wanting to
429      * schedule work. This work Manager must <b>never</b> be used by provider
430      * implementations as they have their own workManager accible on the
431      * connector.
432      * <p/>
433      * If a workManager has not been set by the time the
434      * <code>initialise()</code> method has been called a default
435      * <code>MuleWorkManager</code> will be created using the
436      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
437      * object.
438      *
439      * @return a workManager instance used by the current MuleManager
440      * @see org.mule.api.config.ThreadingProfile
441      * @see DefaultMuleConfiguration
442      */
443     public WorkManager getWorkManager()
444     {
445         return workManager;
446     }
447 
448     public WorkListener getWorkListener()
449     {
450         return workListener;
451     }
452 
453     public QueueManager getQueueManager()
454     {
455         QueueManager queueManager = (QueueManager) registryBroker.lookupObject(MuleProperties.OBJECT_QUEUE_MANAGER);
456         if (queueManager == null)
457         {
458             Collection temp = registryBroker.lookupObjects(QueueManager.class);
459             if (temp.size() > 0)
460             {
461                 queueManager = ((QueueManager) temp.iterator().next());
462             }
463         }
464         return queueManager;
465     }
466 
467     public void setQueueManager(QueueManager queueManager) throws RegistrationException
468     {
469         checkLifecycleForPropertySet(MuleProperties.OBJECT_QUEUE_MANAGER, Initialisable.PHASE_NAME);
470         registryBroker.registerObject(MuleProperties.OBJECT_QUEUE_MANAGER, queueManager);
471     }
472 
473     /**
474      * @return the MuleConfiguration for this MuleManager. This object is immutable
475      *         once the manager has initialised.
476      */
477     public MuleConfiguration getConfiguration()
478     {
479 
480         return config;
481         //return (MuleConfiguration) getRegistry().lookupObject(MuleProperties.OBJECT_MULE_CONFIGURATION);
482     }
483 
484     public ServerNotificationManager getNotificationManager()
485     {
486         return notificationManager;
487     }
488 
489     /**
490      * Sets the JTA Transaction Manager to use with this Mule server instance
491      *
492      * @param manager the manager to use
493      * @throws RegistrationException if a transaction manager has already been set
494      */
495     public void setTransactionManager(TransactionManager manager) throws RegistrationException
496     {
497         //checkLifecycleForPropertySet(MuleProperties.OBJECT_TRANSACTION_MANAGER, Initialisable.PHASE_NAME);
498         registryBroker.registerObject(MuleProperties.OBJECT_TRANSACTION_MANAGER, manager);
499     }
500 
501     /**
502      * Returns the Jta transaction manager used by this Mule server instance. or
503      * null if a transaction manager has not been set
504      *
505      * @return the Jta transaction manager used by this Mule server instance. or
506      *         null if a transaction manager has not been set
507      */
508     public TransactionManager getTransactionManager()
509     {
510         TransactionManager transactionManager = (TransactionManager) registryBroker.lookupObject(MuleProperties.OBJECT_TRANSACTION_MANAGER);
511         if (transactionManager == null)
512         {
513             Collection temp = registryBroker.lookupObjects(TransactionManagerFactory.class);
514             if (temp.size() > 0)
515             {
516                 try
517                 {
518                     transactionManager = (((TransactionManagerFactory) temp.iterator().next()).create(config));
519                 }
520                 catch (Exception e)
521                 {
522                     throw new MuleRuntimeException(CoreMessages.failedToCreate("transaction manager"), e);
523                 }
524             }
525             else
526             {
527                 temp = registryBroker.lookupObjects(TransactionManager.class);
528                 if (temp.size() > 0)
529                 {
530                     transactionManager = (((TransactionManager) temp.iterator().next()));
531                 }
532             }
533         }
534         return transactionManager;
535     }
536 
537     protected void checkLifecycleForPropertySet(String propertyName, String phase) throws IllegalStateException
538     {
539         if (lifecycleManager.isPhaseComplete(phase))
540         {
541             throw new IllegalStateException("Cannot set property: '" + propertyName + "' once the server has been gone through the " + phase + " phase.");
542         }
543     }
544 
545     public MuleRegistry getRegistry()
546     {
547         return muleRegistryHelper;
548     }
549 
550     public ThreadingProfile getDefaultMessageDispatcherThreadingProfile()
551     {
552         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_DISPATCHER_THREADING_PROFILE);
553     }
554 
555     public ThreadingProfile getDefaultMessageRequesterThreadingProfile()
556     {
557         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_REQUESTER_THREADING_PROFILE);
558     }
559 
560     public ThreadingProfile getDefaultMessageReceiverThreadingProfile()
561     {
562         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_RECEIVER_THREADING_PROFILE);
563     }
564 
565     public ThreadingProfile getDefaultServiceThreadingProfile()
566     {
567         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_SERVICE_THREADING_PROFILE);
568     }
569 
570     public ThreadingProfile getDefaultThreadingProfile()
571     {
572         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_THREADING_PROFILE);
573     }
574 
575     /**
576      * Returns the long date when the server was started
577      *
578      * @return the long date when the server was started
579      */
580     public long getStartDate()
581     {
582         return startDate;
583     }
584 
585     /**
586      * Returns the Expression Manager configured for this instance of Mule
587      *
588      * @return the Expression Manager configured for this instance of Mule
589      * @see org.mule.api.expression.ExpressionManager
590      */
591     public ExpressionManager getExpressionManager()
592     {
593         return expressionManager;
594     }
595 
596     public void setExecutionClassLoader(ClassLoader cl)
597     {
598         this.executionClassLoader = cl;
599     }
600 
601     public ClassLoader getExecutionClassLoader()
602     {
603         return executionClassLoader;
604     }
605 
606     public void addRegistry(Registry registry)
607     {
608         registryBroker.addRegistry(registry);
609     }
610 
611     public void removeRegistry(Registry registry)
612     {
613         registryBroker.removeRegistry(registry);
614     }
615 
616     protected SplashScreen buildStartupSplash()
617     {
618         SplashScreen startupScreen = config.isContainerMode()
619                                          ? new ApplicationStartupSplashScreen()
620                                          : new ServerStartupSplashScreen();
621         startupScreen.setHeader(this);
622         startupScreen.setFooter(this);
623         return startupScreen;
624     }
625 
626     protected SplashScreen buildShutdownSplash()
627     {
628         SplashScreen shutdownScreen = config.isContainerMode()
629                                          ? new ApplicationShutdownSplashScreen()
630                                          : new ServerShutdownSplashScreen();
631         shutdownScreen.setHeader(this);
632         return shutdownScreen;
633     }
634 
635     public LocalMuleClient getClient()
636     {
637         return localMuleClient;
638     }
639 
640     public SystemExceptionHandler getExceptionListener()
641     {
642         return exceptionListener;
643     }
644 
645     public void setExceptionListener(SystemExceptionHandler exceptionListener)
646     {
647         this.exceptionListener = exceptionListener;
648     }
649 }