View Javadoc

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