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