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 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
96 addDirectTransition(Startable.PHASE_NAME, Stoppable.PHASE_NAME);
97 addDirectTransition(Stoppable.PHASE_NAME, Startable.PHASE_NAME);
98
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
126 invokePhase(destinationPhase, object, callbacks.get(destinationPhase));
127 }
128 else
129 {
130
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
175
176
177
178 public void applyPhase(Object object, String fromPhase, String toPhase) throws LifecycleException
179 {
180
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
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
249 Set<Object> duplicates = new HashSet<Object>();
250
251 for (LifecycleObject lo : phase.getOrderedLifecycleObjects())
252 {
253
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 }