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