1
2
3
4
5
6
7
8
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
87 addDirectTransition(Startable.PHASE_NAME, Stoppable.PHASE_NAME);
88 addDirectTransition(Stoppable.PHASE_NAME, Startable.PHASE_NAME);
89
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
110 invokePhase(destinationPhase, object, callbacks.get(destinationPhase));
111 }
112 else
113 {
114
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
159
160
161
162 public void applyPhase(Object object, String fromPhase, String toPhase) throws LifecycleException
163 {
164
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
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
233 Set<Object> duplicates = new HashSet<Object>();
234
235 for (LifecycleObject lo : phase.getOrderedLifecycleObjects())
236 {
237
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 }