View Javadoc

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