View Javadoc

1   /*
2    * $Id: RegistryLifecycleManager.java 21528 2011-03-10 16:00:09Z dfeist $
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.lifecycle;
11  
12  import org.mule.api.MuleContext;
13  import org.mule.api.MuleException;
14  import org.mule.api.lifecycle.Disposable;
15  import org.mule.api.lifecycle.Initialisable;
16  import org.mule.api.lifecycle.LifecycleCallback;
17  import org.mule.api.lifecycle.LifecycleException;
18  import org.mule.api.lifecycle.LifecyclePhase;
19  import org.mule.api.lifecycle.RegistryLifecycleHelpers;
20  import org.mule.api.lifecycle.Startable;
21  import org.mule.api.lifecycle.Stoppable;
22  import org.mule.api.registry.Registry;
23  import org.mule.config.i18n.CoreMessages;
24  import org.mule.lifecycle.phases.ContainerManagedLifecyclePhase;
25  import org.mule.lifecycle.phases.MuleContextDisposePhase;
26  import org.mule.lifecycle.phases.MuleContextInitialisePhase;
27  import org.mule.lifecycle.phases.MuleContextStartPhase;
28  import org.mule.lifecycle.phases.MuleContextStopPhase;
29  import org.mule.lifecycle.phases.NotInLifecyclePhase;
30  import org.mule.registry.AbstractRegistryBroker;
31  
32  import java.util.Collection;
33  import java.util.HashMap;
34  import java.util.HashSet;
35  import java.util.Iterator;
36  import java.util.LinkedList;
37  import java.util.List;
38  import java.util.Map;
39  import java.util.Set;
40  import java.util.TreeMap;
41  
42  import org.apache.commons.logging.Log;
43  import org.apache.commons.logging.LogFactory;
44  
45  
46  public class RegistryLifecycleManager extends AbstractLifecycleManager<Registry> implements RegistryLifecycleHelpers
47  {
48      protected Map<String, LifecyclePhase> phases = new HashMap<String, LifecyclePhase>();
49      protected TreeMap<String, LifecycleCallback> callbacks = new TreeMap<String, LifecycleCallback>();
50      protected MuleContext muleContext;
51  
52      public RegistryLifecycleManager(String id, Registry object, MuleContext muleContext)
53      {
54          super(id, object);
55          this.muleContext = muleContext;
56  
57          registerPhases();
58      }
59  
60      protected void registerPhases()
61      {
62          RegistryLifecycleCallback callback = new RegistryLifecycleCallback();
63  
64          registerPhase(NotInLifecyclePhase.PHASE_NAME, NOT_IN_LIFECYCLE_PHASE,
65              new EmptyLifecycleCallback<AbstractRegistryBroker>());
66          registerPhase(Initialisable.PHASE_NAME, new MuleContextInitialisePhase(), callback);
67          registerPhase(Startable.PHASE_NAME, new MuleContextStartPhase(),
68              new EmptyLifecycleCallback<AbstractRegistryBroker>());
69          registerPhase(Stoppable.PHASE_NAME, new MuleContextStopPhase(),
70              new EmptyLifecycleCallback<AbstractRegistryBroker>());
71          registerPhase(Disposable.PHASE_NAME, new MuleContextDisposePhase(), callback);
72      }
73  
74      public RegistryLifecycleManager(String id, Registry object, Map<String, LifecyclePhase> phases )
75      {
76          super(id, object);
77          RegistryLifecycleCallback callback = new RegistryLifecycleCallback();
78  
79          registerPhase(NotInLifecyclePhase.PHASE_NAME, NOT_IN_LIFECYCLE_PHASE, new LifecycleCallback(){
80              public void onTransition(String phaseName, Object object) throws MuleException
81              { }});
82  
83          for (Map.Entry<String, LifecyclePhase> entry : phases.entrySet())
84          {
85              registerPhase(entry.getKey(), entry.getValue(), callback);
86          }
87      }
88  
89      @Override
90      protected void registerTransitions()
91      {
92          addDirectTransition(NotInLifecyclePhase.PHASE_NAME, Initialisable.PHASE_NAME);
93          addDirectTransition(Initialisable.PHASE_NAME, Startable.PHASE_NAME);
94  
95          //start stop
96          addDirectTransition(Startable.PHASE_NAME, Stoppable.PHASE_NAME);
97          addDirectTransition(Stoppable.PHASE_NAME, Startable.PHASE_NAME);
98          //Dispose can be called from init or stopped
99          addDirectTransition(NotInLifecyclePhase.PHASE_NAME, Disposable.PHASE_NAME);
100         addDirectTransition(Initialisable.PHASE_NAME, Disposable.PHASE_NAME);
101         addDirectTransition(Stoppable.PHASE_NAME, Disposable.PHASE_NAME);
102 
103     }
104 
105     protected void registerPhase(String phaseName, LifecyclePhase phase)
106     {
107         phaseNames.add(phaseName);
108         callbacks.put(phaseName, new RegistryLifecycleCallback());
109         phases.put(phaseName, phase);
110     }
111 
112     protected void registerPhase(String phaseName, LifecyclePhase phase, LifecycleCallback callback)
113     {
114         phaseNames.add(phaseName);
115         callbacks.put(phaseName, callback);
116         phases.put(phaseName, phase);
117     }
118 
119     public void fireLifecycle(String destinationPhase) throws LifecycleException
120     {
121         checkPhase(destinationPhase);
122         if (isDirectTransition(destinationPhase))
123         {
124 
125             // transition to phase without going through other phases first
126             invokePhase(destinationPhase, object, callbacks.get(destinationPhase));
127         }
128         else
129         {
130             //Call all phases to including the destination phase
131             boolean start = false;
132             for (String phase : phaseNames)
133             {
134                 if (start)
135                 {
136                     invokePhase(phase, object, callbacks.get(phase));
137                     if (phase.equals(destinationPhase))
138                     {
139                         break;
140                     }
141                 }
142                 if (phase.equals(getCurrentPhase()))
143                 {
144                     start = true;
145                 }
146             }
147         }
148     }
149 
150     protected void invokePhase(String phase, Object object, LifecycleCallback callback) throws LifecycleException
151     {
152         try
153         {
154             setExecutingPhase(phase);
155             callback.onTransition(phase, object);
156             setCurrentPhase(phase);
157         }
158         catch (LifecycleException e)
159         {
160             throw e;
161         }
162         catch (MuleException e)
163         {
164             throw new LifecycleException(CoreMessages.failedToInvokeLifecycle(phase, object), e);
165         }
166         finally
167         {
168             setExecutingPhase(null);
169         }
170     }
171 
172 
173     //-------------------------------------------------------------------------------------------//
174     //-                     LIFECYCLE HELPER METHODS
175     //-------------------------------------------------------------------------------------------//
176 
177 
178     public void applyPhase(Object object, String fromPhase, String toPhase) throws LifecycleException
179     {
180         //TODO i18n
181         if(fromPhase == null || toPhase==null)
182         {
183             throw new IllegalArgumentException("toPhase and fromPhase must be null");
184         }
185         if(!phaseNames.contains(fromPhase))
186         {
187             throw new IllegalArgumentException("fromPhase '" + fromPhase + "' not a valid phase.");
188         }
189         if(!phaseNames.contains(toPhase))
190         {
191             throw new IllegalArgumentException("toPhase '" + fromPhase + "' not a valid phase.");
192         }
193         boolean start = false;
194         for (String phaseName : phaseNames)
195         {
196             if(start)
197             {
198                 phases.get(phaseName).applyLifecycle(object);
199             }
200             if(toPhase.equals(phaseName))
201             {
202                 break;
203             }
204             if(phaseName.equals(fromPhase))
205             {
206                 start = true;
207             }
208 
209         }
210     }
211 
212     public void applyCompletedPhases(Object object) throws LifecycleException
213     {
214         String lastPhase = NotInLifecyclePhase.PHASE_NAME;
215         for (String phase : completedPhases)
216         {
217             if(isDirectTransition(lastPhase, phase))
218             {
219                 LifecyclePhase lp = phases.get(phase);
220                 lp.applyLifecycle(object);
221                 lastPhase = phase;
222             }
223         }
224     }
225 
226     class RegistryLifecycleCallback implements LifecycleCallback<Object>
227     {
228         /**
229          * logger used by this class
230          */
231         protected transient final Log logger = LogFactory.getLog(RegistryLifecycleCallback.class);
232 
233         public void onTransition(String phaseName, Object object) throws MuleException
234         {
235             LifecyclePhase phase = phases.get(phaseName);
236 
237             if (logger.isDebugEnabled())
238             {
239                 logger.debug("Applying lifecycle phase: " + phase + " for registry: " + object.getClass().getSimpleName());
240             }
241 
242             if (phase instanceof ContainerManagedLifecyclePhase)
243             {
244                 phase.applyLifecycle(object);
245                 return;
246             }
247 
248             // overlapping interfaces can cause duplicates
249             Set<Object> duplicates = new HashSet<Object>();
250 
251             for (LifecycleObject lo : phase.getOrderedLifecycleObjects())
252             {
253                 // TODO Collection -> List API refactoring
254                 Collection<?> targetsObj = getLifecycleObject().lookupObjectsForLifecycle(lo.getType());
255                 List<Object> targets = new LinkedList<Object>(targetsObj);
256                 if (targets.size() == 0)
257                 {
258                     continue;
259                 }
260 
261                 lo.firePreNotification(muleContext);
262 
263                 for (Iterator<Object> target = targets.iterator(); target.hasNext();)
264                 {
265                     Object o = target.next();
266                     if (duplicates.contains(o))
267                     {
268                         target.remove();
269                     }
270                     else
271                     {
272                         if (logger.isDebugEnabled())
273                         {
274                             logger.debug("lifecycle phase: " + phase.getName() + " for object: " + o);
275                         }
276                         phase.applyLifecycle(o);
277                         target.remove();
278                         duplicates.add(o);
279                     }
280                 }
281 
282                 lo.firePostNotification(muleContext);
283             }
284         }
285     }
286 }