View Javadoc

1   /*
2    * $Id: DefaultMuleContext.java 12375 2008-07-17 15:42:50Z dfeist $
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  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.config.MuleConfiguration;
16  import org.mule.api.config.MuleProperties;
17  import org.mule.api.config.ThreadingProfile;
18  import org.mule.api.context.WorkManager;
19  import org.mule.api.context.notification.ServerNotification;
20  import org.mule.api.context.notification.ServerNotificationListener;
21  import org.mule.api.lifecycle.Disposable;
22  import org.mule.api.lifecycle.Initialisable;
23  import org.mule.api.lifecycle.InitialisationException;
24  import org.mule.api.lifecycle.LifecycleManager;
25  import org.mule.api.lifecycle.Startable;
26  import org.mule.api.lifecycle.Stoppable;
27  import org.mule.api.registry.RegistrationException;
28  import org.mule.api.registry.Registry;
29  import org.mule.api.security.SecurityManager;
30  import org.mule.api.transaction.TransactionManagerFactory;
31  import org.mule.api.transport.ConnectionStrategy;
32  import org.mule.config.DefaultMuleConfiguration;
33  import org.mule.config.i18n.CoreMessages;
34  import org.mule.context.notification.MuleContextNotification;
35  import org.mule.context.notification.NotificationException;
36  import org.mule.context.notification.ServerNotificationManager;
37  import org.mule.management.stats.AllStatistics;
38  import org.mule.util.ServerShutdownSplashScreen;
39  import org.mule.util.ServerStartupSplashScreen;
40  import org.mule.util.SplashScreen;
41  import org.mule.util.queue.QueueManager;
42  
43  import java.util.Collection;
44  
45  import javax.resource.spi.work.WorkListener;
46  import javax.transaction.TransactionManager;
47  
48  import org.apache.commons.beanutils.BeanUtils;
49  import org.apache.commons.logging.Log;
50  import org.apache.commons.logging.LogFactory;
51  
52  public class DefaultMuleContext implements MuleContext
53  {
54      /** logger used by this class */
55      private static transient Log logger = LogFactory.getLog(DefaultMuleContext.class);
56  
57      /** stats used for management */
58      private AllStatistics stats = new AllStatistics();
59  
60      private WorkManager workManager;
61  
62      private WorkListener workListener;
63  
64      /**
65       * LifecycleManager for the MuleContext.  Note: this is NOT the same lifecycle manager
66       * as the one in the Registry.
67       */
68      protected LifecycleManager lifecycleManager;
69  
70      protected ServerNotificationManager notificationManager;
71  
72      private MuleConfiguration config;
73          
74      /** the date in milliseconds from when the server was started */
75      private long startDate;
76  
77      public DefaultMuleContext(MuleConfiguration config,
78                                WorkManager workManager, 
79                                WorkListener workListener, 
80                                LifecycleManager lifecycleManager, 
81                                ServerNotificationManager notificationManager)
82      {
83          this.config = config;
84          this.workManager = workManager;
85          this.workListener = workListener;
86          this.lifecycleManager = lifecycleManager;
87          this.notificationManager = notificationManager;
88      }
89  
90      public void initialise() throws InitialisationException
91      {
92          lifecycleManager.checkPhase(Initialisable.PHASE_NAME);
93  
94          if (getNotificationManager() == null)
95          {
96              throw new MuleRuntimeException(
97                  CoreMessages.objectIsNull(MuleProperties.OBJECT_NOTIFICATION_MANAGER));
98          }
99          if (workManager == null)
100         {
101             throw new MuleRuntimeException(CoreMessages.objectIsNull("workManager"));
102         }
103 
104         try
105         {
106             //We need to start the work manager straight away since we need it to fire notifications
107             workManager.start();
108             getNotificationManager().start(workManager, workListener);
109 
110             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_INITIALISING));
111 
112             lifecycleManager.firePhase(this, Initialisable.PHASE_NAME);
113 
114             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_INITIALISED));
115         }
116         catch (Exception e)
117         {
118             throw new InitialisationException(e, this);
119         }
120     }
121 
122     public synchronized void start() throws MuleException
123     {
124         lifecycleManager.checkPhase(Startable.PHASE_NAME);
125         if (!isStarted())
126         {
127             if (getSecurityManager() == null)
128             {
129                 throw new MuleRuntimeException(CoreMessages.objectIsNull("securityManager"));
130             }
131             if (getQueueManager() == null)
132             {
133                 throw new MuleRuntimeException(CoreMessages.objectIsNull("queueManager"));
134             }
135 
136             startDate = System.currentTimeMillis();
137 
138             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STARTING));
139 
140             lifecycleManager.firePhase(this, Startable.PHASE_NAME);
141 
142             if (logger.isInfoEnabled())
143             {
144                 SplashScreen splashScreen = SplashScreen.getInstance(ServerStartupSplashScreen.class);
145                 splashScreen.setHeader(this);
146                 splashScreen.setFooter(this);
147                 logger.info(splashScreen.toString());
148             }
149             fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STARTED));
150         }
151     }
152 
153     /**
154      * Stops the <code>MuleManager</code> which stops all sessions and
155      * connectors
156      *
157      * @throws MuleException if either any of the sessions or connectors fail to
158      *                      stop
159      */
160     public synchronized void stop() throws MuleException
161     {
162         lifecycleManager.checkPhase(Stoppable.PHASE_NAME);
163         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STOPPING));
164         lifecycleManager.firePhase(this, Stoppable.PHASE_NAME);
165         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_STOPPED));
166     }
167 
168     public void dispose()
169     {        
170         if (isDisposing())
171         {
172             return;
173         }
174              
175         ServerNotificationManager notificationManager = getNotificationManager();
176         lifecycleManager.checkPhase(Disposable.PHASE_NAME);
177         fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_DISPOSING));
178 
179         try
180         {
181             if (isStarted())
182             {
183                 stop();
184             }
185         }
186         catch (MuleException e)
187         {
188             logger.error("Failed to stop manager: " + e.getMessage(), e);
189         }
190 
191         try
192         {
193             lifecycleManager.firePhase(this, Disposable.PHASE_NAME);
194         }
195         catch (MuleException e)
196         {
197             logger.debug("Failed to cleanly dispose Mule: " + e.getMessage(), e);
198         }
199 
200         notificationManager.fireNotification(new MuleContextNotification(this, MuleContextNotification.CONTEXT_DISPOSED));
201 
202         notificationManager.dispose();
203         workManager.dispose();
204 
205         if ((getStartDate() > 0) && logger.isInfoEnabled())
206         {
207             SplashScreen splashScreen = SplashScreen.getInstance(ServerShutdownSplashScreen.class);
208             splashScreen.setHeader(this);
209             logger.info(splashScreen.toString());
210         }
211 
212     }
213 
214 
215     /**
216      * Determines if the server has been initialised
217      *
218      * @return true if the server has been initialised
219      */
220     public boolean isInitialised()
221     {
222         return lifecycleManager.isPhaseComplete(Initialisable.PHASE_NAME);
223     }
224 
225     /**
226      * Determines if the server is being initialised
227      *
228      * @return true if the server is beening initialised
229      */
230     public boolean isInitialising()
231     {
232         return Disposable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
233     }
234 
235     protected boolean isStopped()
236     {
237         return lifecycleManager.isPhaseComplete(Stoppable.PHASE_NAME);
238     }
239 
240     protected boolean isStopping()
241     {
242         return Stoppable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
243     }
244 
245     /**
246      * Determines if the server has been started
247      *
248      * @return true if the server has been started
249      */
250     public boolean isStarted()
251     {
252         return lifecycleManager.isPhaseComplete(Startable.PHASE_NAME);
253     }
254 
255     protected boolean isStarting()
256     {
257         return Startable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
258     }
259 
260     public boolean isDisposed()
261     {
262         return lifecycleManager.isPhaseComplete(Disposable.PHASE_NAME);
263     }
264 
265     public boolean isDisposing()
266     {
267         return Disposable.PHASE_NAME.equals(lifecycleManager.getExecutingPhase());
268     }
269 
270     public LifecycleManager getLifecycleManager()
271     {
272         return lifecycleManager;
273     }
274 
275     /**
276      * Gets all statisitcs for this instance
277      *
278      * @return all statisitcs for this instance
279      */
280     public AllStatistics getStatistics()
281     {
282         return stats;
283     }
284 
285     public void registerListener(ServerNotificationListener l) throws NotificationException
286     {
287         registerListener(l, null);
288     }
289 
290     public void registerListener(ServerNotificationListener l, String resourceIdentifier) throws NotificationException
291     {
292         ServerNotificationManager notificationManager = getNotificationManager();
293         if (notificationManager == null)
294         {
295             throw new MuleRuntimeException(CoreMessages.serverNotificationManagerNotEnabled());
296         }
297         notificationManager.addListenerSubscription(l, resourceIdentifier);
298     }
299 
300     public void unregisterListener(ServerNotificationListener l)
301     {
302         ServerNotificationManager notificationManager = getNotificationManager();
303         if (notificationManager != null)
304         {
305             notificationManager.removeListener(l);
306         }
307     }
308 
309     /**
310      * Fires a server notification to all registered
311      * {@link org.mule.api.context.notification.listener.CustomNotificationListener} notificationManager.
312      *
313      * @param notification the notification to fire. This must be of type
314      *                     {@link org.mule.context.notification.CustomNotification} otherwise an
315      *                     exception will be thrown.
316      * @throws UnsupportedOperationException if the notification fired is not a
317      *                                       {@link org.mule.context.notification.CustomNotification}
318      */
319     public void fireNotification(ServerNotification notification)
320     {
321         ServerNotificationManager notificationManager = getNotificationManager();
322         if (notificationManager != null)
323         {
324             notificationManager.fireNotification(notification);
325         }
326         else if (logger.isDebugEnabled())
327         {
328             logger.debug("MuleEvent Manager is not enabled, ignoring notification: " + notification);
329         }
330     }
331 
332     /**
333      * Sets the security manager used by this Mule instance to authenticate and
334      * authorise incoming and outgoing event traffic and service invocations
335      *
336      * @param securityManager the security manager used by this Mule instance to
337      *                        authenticate and authorise incoming and outgoing event traffic
338      *                        and service invocations
339      */
340     public void setSecurityManager(SecurityManager securityManager) throws RegistrationException
341     {
342         checkLifecycleForPropertySet(MuleProperties.OBJECT_SECURITY_MANAGER, Initialisable.PHASE_NAME);
343         getRegistry().registerObject(MuleProperties.OBJECT_SECURITY_MANAGER, securityManager);
344     }
345 
346     /**
347      * Gets the security manager used by this Mule instance to authenticate and
348      * authorise incoming and outgoing event traffic and service invocations
349      *
350      * @return he security manager used by this Mule instance to authenticate
351      *         and authorise incoming and outgoing event traffic and service
352      *         invocations
353      */
354     public SecurityManager getSecurityManager()
355     {
356         SecurityManager securityManager = (SecurityManager) getRegistry().lookupObject(
357             MuleProperties.OBJECT_SECURITY_MANAGER);
358         if (securityManager == null)
359         {
360             Collection temp = getRegistry().lookupObjects(SecurityManager.class);
361             if (temp.size() > 0)
362             {
363                 securityManager = ((SecurityManager) temp.iterator().next());
364             }
365         }
366         return securityManager;
367     }
368 
369     /**
370      * Obtains a workManager instance that can be used to schedule work in a
371      * thread pool. This will be used primarially by UMOAgents wanting to
372      * schedule work. This work Manager must <b>never</b> be used by provider
373      * implementations as they have their own workManager accible on the
374      * connector.
375      * <p/>
376      * If a workManager has not been set by the time the
377      * <code>initialise()</code> method has been called a default
378      * <code>MuleWorkManager</code> will be created using the
379      * <i>DefaultThreadingProfile</i> on the <code>MuleConfiguration</code>
380      * object.
381      *
382      * @return a workManager instance used by the current MuleManager
383      * @see org.mule.api.config.ThreadingProfile
384      * @see DefaultMuleConfiguration
385      */
386     public WorkManager getWorkManager()
387     {
388         return workManager;
389     }
390 
391     public WorkListener getWorkListener()
392     {
393         return workListener;
394     }
395 
396     public QueueManager getQueueManager()
397     {
398         QueueManager queueManager = (QueueManager) getRegistry().lookupObject(MuleProperties.OBJECT_QUEUE_MANAGER);
399         if (queueManager == null)
400         {
401             Collection temp = getRegistry().lookupObjects(QueueManager.class);
402             if (temp.size() > 0)
403             {
404                 queueManager = ((QueueManager) temp.iterator().next());
405             }
406         }
407         return queueManager;
408     }
409 
410     public void setQueueManager(QueueManager queueManager) throws RegistrationException
411     {
412         checkLifecycleForPropertySet(MuleProperties.OBJECT_QUEUE_MANAGER, Initialisable.PHASE_NAME);
413         getRegistry().registerObject(MuleProperties.OBJECT_QUEUE_MANAGER, queueManager);
414     }
415 
416     /**
417     * @return the MuleConfiguration for this MuleContext. This object is immutable
418     *         once the context has initialised.
419     */
420     public MuleConfiguration getConfiguration()
421     {
422         return config;
423     }
424     
425     public ServerNotificationManager getNotificationManager()
426     {
427         return notificationManager;
428     }
429 
430     /**
431      * Sets the Jta Transaction Manager to use with this Mule server instance
432      *
433      * @param manager the manager to use
434      * @throws Exception
435      */
436     public void setTransactionManager(TransactionManager manager) throws RegistrationException
437     {
438         //checkLifecycleForPropertySet(MuleProperties.OBJECT_TRANSACTION_MANAGER, Initialisable.PHASE_NAME);
439         getRegistry().registerObject(MuleProperties.OBJECT_TRANSACTION_MANAGER, manager);
440     }
441 
442     /**
443      * Returns the Jta transaction manager used by this Mule server instance. or
444      * null if a transaction manager has not been set
445      *
446      * @return the Jta transaction manager used by this Mule server instance. or
447      *         null if a transaction manager has not been set
448      */
449     public TransactionManager getTransactionManager()
450     {
451         TransactionManager transactionManager = (TransactionManager) getRegistry().lookupObject(
452             MuleProperties.OBJECT_TRANSACTION_MANAGER);
453         if (transactionManager == null)
454         {
455             Collection temp = getRegistry().lookupObjects(TransactionManagerFactory.class);
456             if (temp.size() > 0)
457             {
458                 try
459                 {
460                     transactionManager = (((TransactionManagerFactory) temp.iterator().next()).create());
461                 }
462                 catch (Exception e)
463                 {
464                     throw new MuleRuntimeException(CoreMessages.failedToCreate("transaction manager"), e);
465                 }
466             }
467             else
468             {
469                 temp = getRegistry().lookupObjects(TransactionManager.class);
470                 if (temp.size() > 0)
471                 {
472                     transactionManager = (((TransactionManager) temp.iterator().next()));
473                 }
474             }
475         }
476         return transactionManager;
477     }
478 
479     protected void checkLifecycleForPropertySet(String propertyName, String phase) throws IllegalStateException
480     {
481         if (lifecycleManager.isPhaseComplete(phase))
482         {
483             throw new IllegalStateException("Cannot set property: '" + propertyName + "' once the server has been gone through the " + phase + " phase.");
484         }
485     }
486 
487     /**
488      * Resolve and return a handle to the registry.
489      * This should eventually be more intelligent (handle remote registries, clusters of Mule instances, etc.)
490      * For now the registry is just a local singleton.
491      */
492     public Registry getRegistry()
493     {
494         return RegistryContext.getRegistry();
495     }
496 
497     /**
498      * Apply current phase of the LifecycleManager.  Note: this is NOT the same lifecycle manager
499      * as the one in the Registry.
500      */
501     public void applyLifecycle(Object object) throws MuleException
502     {
503         lifecycleManager.applyLifecycle(this, object);
504     }
505 
506     public ThreadingProfile getDefaultMessageDispatcherThreadingProfile()
507     {
508         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_DISPATCHER_THREADING_PROFILE);
509     }
510 
511     public ThreadingProfile getDefaultMessageRequesterThreadingProfile()
512     {
513         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_REQUESTER_THREADING_PROFILE);
514     }
515 
516     public ThreadingProfile getDefaultMessageReceiverThreadingProfile()
517     {
518         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_MESSAGE_RECEIVER_THREADING_PROFILE);
519     }
520 
521     public ThreadingProfile getDefaultComponentThreadingProfile()
522     {
523         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_COMPONENT_THREADING_PROFILE);
524     }
525 
526     public ThreadingProfile getDefaultThreadingProfile()
527     {
528         return (ThreadingProfile) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_THREADING_PROFILE);
529     }
530 
531     /**
532      * Returns a clone of the default Connection strategy. The clone ensures that the
533      * connection strategy can be manipulated without affecting other connectors
534      * using the same strategy
535      * 
536      * @return a clone of the default Connection strategy
537      */
538     public ConnectionStrategy getDefaultConnectionStrategy()
539     {
540         ConnectionStrategy defaultConnectionStrategy = 
541             (ConnectionStrategy) getRegistry().lookupObject(MuleProperties.OBJECT_DEFAULT_CONNECTION_STRATEGY);
542         try
543         {
544             return (ConnectionStrategy) BeanUtils.cloneBean(defaultConnectionStrategy);
545         }
546         catch (Exception e)
547         {
548             throw new MuleRuntimeException(CoreMessages.failedToClone("Connection Strategy"), e);
549         }
550     }
551 
552     /**
553      * Returns the long date when the server was started
554      *
555      * @return the long date when the server was started
556      */
557     public long getStartDate()
558     {
559         return startDate;
560     }
561 }