View Javadoc

1   /*
2    * $Id: AbstractModel.java 7976 2007-08-21 14:26:13Z dirk.olmes $
3    * --------------------------------------------------------------------------------------
4    * Copyright (c) MuleSource, Inc.  All rights reserved.  http://www.mulesource.com
5    *
6    * The software in this package is published under the terms of the CPAL v1.0
7    * license, a copy of which has been included with this distribution in the
8    * LICENSE.txt file.
9    */
10  
11  package org.mule.impl.model;
12  
13  import org.mule.MuleManager;
14  import org.mule.config.i18n.CoreMessages;
15  import org.mule.impl.DefaultComponentExceptionStrategy;
16  import org.mule.impl.DefaultLifecycleAdapterFactory;
17  import org.mule.impl.ImmutableMuleDescriptor;
18  import org.mule.impl.MuleSession;
19  import org.mule.impl.internal.notifications.ModelNotification;
20  import org.mule.impl.model.resolvers.DynamicEntryPointResolver;
21  import org.mule.umo.UMOComponent;
22  import org.mule.umo.UMODescriptor;
23  import org.mule.umo.UMOException;
24  import org.mule.umo.UMOSession;
25  import org.mule.umo.lifecycle.Initialisable;
26  import org.mule.umo.lifecycle.InitialisationException;
27  import org.mule.umo.lifecycle.UMOLifecycleAdapterFactory;
28  import org.mule.umo.manager.UMOServerNotification;
29  import org.mule.umo.model.ModelException;
30  import org.mule.umo.model.UMOEntryPointResolver;
31  import org.mule.umo.model.UMOModel;
32  
33  import java.beans.ExceptionListener;
34  import java.util.Iterator;
35  import java.util.List;
36  import java.util.Map;
37  
38  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
39  import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentSkipListMap;
40  import edu.emory.mathcs.backport.java.util.concurrent.atomic.AtomicBoolean;
41  import org.apache.commons.logging.Log;
42  import org.apache.commons.logging.LogFactory;
43  
44  /**
45   * <code>MuleModel</code> is the default implementation of the UMOModel. The model
46   * encapsulates and manages the runtime behaviour of a Mule Server instance. It is
47   * responsible for maintaining the UMOs instances and their configuration.
48   */
49  public abstract class AbstractModel implements UMOModel
50  {
51      /**
52       * logger used by this class
53       */
54      protected transient Log logger = LogFactory.getLog(getClass());
55  
56      private String name;
57      private UMOEntryPointResolver entryPointResolver = new DynamicEntryPointResolver();
58      private UMOLifecycleAdapterFactory lifecycleAdapterFactory = new DefaultLifecycleAdapterFactory();
59  
60      private Map components = new ConcurrentSkipListMap();
61  
62      /**
63       * Collection for mule descriptors registered in this Manager
64       */
65      protected Map descriptors = new ConcurrentHashMap();
66  
67      private AtomicBoolean initialised = new AtomicBoolean(false);
68  
69      private AtomicBoolean started = new AtomicBoolean(false);
70  
71      private ExceptionListener exceptionListener = new DefaultComponentExceptionStrategy();
72  
73      /**
74       * Default constructor
75       */
76      public AbstractModel()
77      {
78          // Always set default entrypoint resolver, lifecycle and compoenent
79          // resolver and exceptionstrategy.
80          entryPointResolver = new DynamicEntryPointResolver();
81          lifecycleAdapterFactory = new DefaultLifecycleAdapterFactory();
82          components = new ConcurrentSkipListMap();
83          descriptors = new ConcurrentHashMap();
84          exceptionListener = new DefaultComponentExceptionStrategy();
85          name = "mule";
86      }
87  
88      /*
89       * (non-Javadoc)
90       * 
91       * @see org.mule.umo.UMOModel#getName()
92       */
93      public String getName()
94      {
95          return name;
96      }
97  
98      /*
99       * (non-Javadoc)
100      * 
101      * @see org.mule.umo.UMOModel#setName(java.lang.String)
102      */
103     public void setName(String name)
104     {
105         this.name = name;
106     }
107 
108     /*
109      * (non-Javadoc)
110      * 
111      * @see org.mule.umo.model.UMOModel#getEntryPointResolver()
112      */
113     public UMOEntryPointResolver getEntryPointResolver()
114     {
115         return entryPointResolver;
116     }
117 
118     /*
119      * (non-Javadoc)
120      * 
121      * @see org.mule.umo.model.UMOModel#setEntryPointResolver(org.mule.umo.model.UMOEntryPointResolver)
122      */
123     public void setEntryPointResolver(UMOEntryPointResolver entryPointResolver)
124     {
125         this.entryPointResolver = entryPointResolver;
126     }
127 
128     /*
129      * (non-Javadoc)
130      * 
131      * @see org.mule.umo.UMOModel#isUMORegistered(java.lang.String)
132      */
133     public boolean isComponentRegistered(String name)
134     {
135         return (components.get(name) != null);
136     }
137 
138     /*
139      * (non-Javadoc)
140      * 
141      * @see org.mule.umo.UMOModel#registerUMO(org.mule.umo.UMODescriptor)
142      */
143     public UMOComponent registerComponent(UMODescriptor descriptor) throws UMOException
144     {
145         if (descriptor == null)
146         {
147             throw new ModelException(CoreMessages.objectIsNull("UMO Descriptor"));
148         }
149 
150         // Set the es if one wasn't set in the configuration
151         if (descriptor.getExceptionListener() == null)
152         {
153             descriptor.setExceptionListener(exceptionListener);
154         }
155 
156         if (initialised.get())
157         {
158             descriptor.initialise();
159         }
160 
161         // detect duplicate descriptor declarations
162         if (descriptors.get(descriptor.getName()) != null)
163         {
164             throw new ModelException(CoreMessages.descriptorAlreadyExists(descriptor.getName()));
165         }
166 
167         UMOComponent component = (UMOComponent) components.get(descriptor.getName());
168 
169         if (component == null)
170         {
171             component = createComponent(descriptor);
172             descriptors.put(descriptor.getName(), descriptor);
173             components.put(descriptor.getName(), component);
174         }
175 
176         logger.debug("Added Mule UMO: " + descriptor.getName());
177 
178         if (initialised.get())
179         {
180             logger.info("Initialising component: " + descriptor.getName());
181             component.initialise();
182         }
183         if (started.get())
184         {
185             logger.info("Starting component: " + descriptor.getName());
186             component.start();
187         }
188         return component;
189     }
190 
191     public void unregisterComponent(UMODescriptor descriptor) throws UMOException
192     {
193         if (descriptor == null)
194         {
195             throw new ModelException(CoreMessages.objectIsNull("UMO Descriptor"));
196         }
197 
198         if (!isComponentRegistered(descriptor.getName()))
199         {
200             throw new ModelException(CoreMessages.componentNotRegistered(descriptor.getName()));
201         }
202         UMOComponent component = (UMOComponent) components.remove(descriptor.getName());
203 
204         if (component != null)
205         {
206             component.stop();
207             descriptors.remove(descriptor.getName());
208             component.dispose();
209             logger.info("The component: " + descriptor.getName() + " has been unregistered and disposing");
210         }
211     }
212 
213     /*
214      * (non-Javadoc)
215      * 
216      * @see org.mule.umo.model.UMOModel#getLifecycleAdapterFactory()
217      */
218     public UMOLifecycleAdapterFactory getLifecycleAdapterFactory()
219     {
220         return lifecycleAdapterFactory;
221     }
222 
223     /*
224      * (non-Javadoc)
225      * 
226      * @see org.mule.umo.model.UMOModel#setLifecycleAdapterFactory(org.mule.umo.lifecycle.UMOLifecycleAdapterFactory)
227      */
228     public void setLifecycleAdapterFactory(UMOLifecycleAdapterFactory lifecycleAdapterFactory)
229     {
230         this.lifecycleAdapterFactory = lifecycleAdapterFactory;
231     }
232 
233     /**
234      * Destroys any current components
235      */
236     public void dispose()
237     {
238         fireNotification(new ModelNotification(this, ModelNotification.MODEL_DISPOSING));
239 
240         for (Iterator i = components.values().iterator(); i.hasNext();)
241         {
242             UMOComponent component = (UMOComponent) i.next();
243             try
244             {
245                 component.dispose();
246                 logger.info(component + " has been destroyed successfully");
247             }
248             catch (Exception e1)
249             {
250                 // TODO MULE-863: So what do we do about this?
251                 logger.warn("Failed to dispose component: " + e1.getMessage());
252             }
253         }
254 
255         components.clear();
256         descriptors.clear();
257 
258         fireNotification(new ModelNotification(this, ModelNotification.MODEL_DISPOSED));
259     }
260 
261     /**
262      * Returns a valid component for the given Mule name
263      * 
264      * @param muleName the Name of the Mule for which the component is required
265      * @return a component for the specified name
266      */
267     public UMOSession getComponentSession(String muleName)
268     {
269         UMOComponent component = (UMOComponent) components.get(muleName);
270         if (component == null)
271         {
272             logger.warn("Component: " + muleName + " not found returning null session");
273             return null;
274         }
275         else
276         {
277             return new MuleSession(component);
278         }
279     }
280 
281     /**
282      * Stops any registered components
283      * 
284      * @throws UMOException if a Component fails tcomponent
285      */
286     public void stop() throws UMOException
287     {
288         fireNotification(new ModelNotification(this, ModelNotification.MODEL_STOPPING));
289         for (Iterator i = components.values().iterator(); i.hasNext();)
290         {
291             UMOComponent component = (UMOComponent) i.next();
292             component.stop();
293             logger.info("Component " + component + " has been stopped successfully");
294         }
295         started.set(false);
296         initialised.set(false);
297         fireNotification(new ModelNotification(this, ModelNotification.MODEL_STOPPED));
298     }
299 
300     /**
301      * Starts all registered components
302      * 
303      * @throws UMOException if any of the components fail to start
304      */
305     public void start() throws UMOException
306     {
307         if (!initialised.get())
308         {
309             initialise();
310         }
311 
312         if (!started.get())
313         {
314             fireNotification(new ModelNotification(this, ModelNotification.MODEL_STARTING));
315 
316             for (Iterator i = components.values().iterator(); i.hasNext();)
317             {
318                 AbstractComponent component = (AbstractComponent) i.next();
319 
320                 if (component.getDescriptor().getInitialState().equals(
321                     ImmutableMuleDescriptor.INITIAL_STATE_STARTED))
322                 {
323                     component.start();
324                     logger.info("Component " + component + " has been started successfully");
325                 }
326                 else if (component.getDescriptor().getInitialState().equals(
327                     ImmutableMuleDescriptor.INITIAL_STATE_PAUSED))
328                 {
329                     component.start(true);
330                     logger.info("Component " + component
331                                 + " has been started and paused (initial state = 'paused')");
332                 }
333                 else
334                 {
335                     logger.info("Component " + component
336                                 + " has not been started (initial state = 'stopped')");
337                 }
338             }
339             started.set(true);
340             fireNotification(new ModelNotification(this, ModelNotification.MODEL_STARTED));
341         }
342         else
343         {
344             logger.debug("Model already started");
345         }
346     }
347 
348     /**
349      * Starts a single Mule Component. This can be useful when stopping and starting
350      * some Mule UMOs while letting others continue
351      * 
352      * @param name the name of the Mule UMO to start
353      * @throws UMOException if the MuleUMO is not registered or the component failed
354      *             to start
355      */
356     public void startComponent(String name) throws UMOException
357     {
358         UMOComponent component = (UMOComponent) components.get(name);
359         if (component == null)
360         {
361             throw new ModelException(CoreMessages.componentNotRegistered(name));
362         }
363         else
364         {
365             component.start();
366             logger.info("Mule " + component.toString() + " has been started successfully");
367         }
368     }
369 
370     /**
371      * Stops a single Mule Component. This can be useful when stopping and starting
372      * some Mule UMOs while letting others continue.
373      * 
374      * @param name the name of the Mule UMO to stop
375      * @throws UMOException if the MuleUMO is not registered
376      */
377     public void stopComponent(String name) throws UMOException
378     {
379         UMOComponent component = (UMOComponent) components.get(name);
380         if (component == null)
381         {
382             throw new ModelException(CoreMessages.componentNotRegistered(name));
383         }
384         else
385         {
386             component.stop();
387             logger.info("mule " + name + " has been stopped successfully");
388         }
389     }
390 
391     /**
392      * Pauses event processing for a single Mule Component. Unlike stopComponent(), a
393      * paused component will still consume messages from the underlying transport,
394      * but those messages will be queued until the component is resumed. <p/> In
395      * order to persist these queued messages you can set the 'recoverableMode'
396      * property on the Muleconfiguration to true. this causes all internal queues to
397      * store their state.
398      * 
399      * @param name the name of the Mule UMO to stop
400      * @throws org.mule.umo.UMOException if the MuleUMO is not registered or the
401      *             component failed to pause.
402      * @see org.mule.config.MuleConfiguration
403      */
404     public void pauseComponent(String name) throws UMOException
405     {
406         UMOComponent component = (UMOComponent) components.get(name);
407 
408         if (component != null)
409         {
410             component.pause();
411             logger.info("Mule Component " + name + " has been paused successfully");
412         }
413         else
414         {
415             throw new ModelException(CoreMessages.componentNotRegistered(name));
416         }
417     }
418 
419     /**
420      * Resumes a single Mule Component that has been paused. If the component is not
421      * paused nothing is executed.
422      * 
423      * @param name the name of the Mule UMO to resume
424      * @throws org.mule.umo.UMOException if the MuleUMO is not registered or the
425      *             component failed to resume
426      */
427     public void resumeComponent(String name) throws UMOException
428     {
429         UMOComponent component = (UMOComponent) components.get(name);
430 
431         if (component != null)
432         {
433             component.resume();
434             logger.info("Mule Component " + name + " has been resumed successfully");
435         }
436         else
437         {
438             throw new ModelException(CoreMessages.componentNotRegistered(name));
439         }
440     }
441 
442     public void setComponents(List descriptors) throws UMOException
443     {
444         for (Iterator iterator = descriptors.iterator(); iterator.hasNext();)
445         {
446             registerComponent((UMODescriptor) iterator.next());
447         }
448     }
449 
450     public void initialise() throws InitialisationException
451     {
452         if (!initialised.get())
453         {
454             fireNotification(new ModelNotification(this, ModelNotification.MODEL_INITIALISING));
455 
456             if (exceptionListener instanceof Initialisable)
457             {
458                 ((Initialisable) exceptionListener).initialise();
459             }
460             UMOComponent component = null;
461             for (Iterator i = components.values().iterator(); i.hasNext();)
462             {
463                 component = (UMOComponent) i.next();
464                 component.initialise();
465 
466                 logger.info("Component " + component.getDescriptor().getName()
467                             + " has been started successfully");
468             }
469             initialised.set(true);
470             fireNotification(new ModelNotification(this, ModelNotification.MODEL_INITIALISED));
471         }
472         else
473         {
474             logger.debug("Model already initialised");
475         }
476     }
477 
478     public ExceptionListener getExceptionListener()
479     {
480         return exceptionListener;
481     }
482 
483     public void setExceptionListener(ExceptionListener exceptionListener)
484     {
485         this.exceptionListener = exceptionListener;
486     }
487 
488     public UMODescriptor getDescriptor(String name)
489     {
490         return (UMODescriptor) descriptors.get(name);
491     }
492 
493     public UMOComponent getComponent(String name)
494     {
495         return (UMOComponent) components.get(name);
496     }
497 
498     /**
499      * Gets an iterator of all component names registered in the model
500      * 
501      * @return an iterator of all component names
502      */
503     public Iterator getComponentNames()
504     {
505         return components.keySet().iterator();
506     }
507 
508     void fireNotification(UMOServerNotification notification)
509     {
510         MuleManager.getInstance().fireNotification(notification);
511     }
512 
513     protected abstract UMOComponent createComponent(UMODescriptor descriptor);
514 }