1
2
3
4
5
6
7 package org.mule.lifecycle;
8
9 import org.mule.api.MuleContext;
10 import org.mule.api.lifecycle.Disposable;
11 import org.mule.api.lifecycle.Initialisable;
12 import org.mule.api.lifecycle.LifecycleCallback;
13 import org.mule.api.lifecycle.LifecycleException;
14 import org.mule.api.lifecycle.LifecycleManager;
15 import org.mule.api.lifecycle.LifecycleState;
16 import org.mule.api.lifecycle.Startable;
17 import org.mule.api.lifecycle.Stoppable;
18 import org.mule.lifecycle.phases.NotInLifecyclePhase;
19 import org.mule.transport.AbstractConnector;
20 import org.mule.transport.ConnectException;
21
22 import java.util.HashSet;
23 import java.util.LinkedHashSet;
24 import java.util.Set;
25 import java.util.TreeMap;
26
27 import org.apache.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29
30
31
32
33
34
35
36
37
38
39 public abstract class AbstractLifecycleManager<O> implements LifecycleManager
40 {
41
42
43
44 protected transient final Log logger = LogFactory.getLog(AbstractLifecycleManager.class);
45
46 protected String lifecycleManagerId;
47 protected String currentPhase = NotInLifecyclePhase.PHASE_NAME;
48 protected String executingPhase = null;
49 private Set<String> directTransitions = new HashSet<String>();
50 protected Set<String> phaseNames = new LinkedHashSet<String>(4);
51 protected Set<String> completedPhases = new LinkedHashSet<String>(4);
52 protected O object;
53 protected LifecycleState state;
54
55 private TreeMap<String, LifecycleCallback> callbacks = new TreeMap<String, LifecycleCallback>();
56
57 public AbstractLifecycleManager(String id, O object)
58 {
59 lifecycleManagerId = id;
60 this.object = object;
61 state = createLifecycleState();
62
63 currentPhase = NotInLifecyclePhase.PHASE_NAME;
64 completedPhases.add(currentPhase);
65 registerTransitions();
66 }
67
68 protected abstract void registerTransitions();
69
70 public void registerLifecycleCallback(String phaseName, LifecycleCallback<O> callback)
71 {
72 callbacks.put(phaseName, callback);
73 }
74
75 protected LifecycleState createLifecycleState()
76 {
77 return new DefaultLifecycleState(this);
78 }
79
80 protected void addDirectTransition(String phase1, String phase2)
81 {
82 directTransitions.add(phase1 + "-" + phase2);
83 phaseNames.add(phase1);
84 phaseNames.add(phase2);
85 }
86
87 public void checkPhase(String name) throws IllegalStateException
88 {
89 if (executingPhase != null)
90 {
91 if (name.equalsIgnoreCase(executingPhase))
92 {
93 throw new IllegalStateException("Phase '" + name + "' is already currently being executed");
94 }
95 else
96 {
97 throw new IllegalStateException("Cannot fire phase '" + name + "', currently executing lifecycle phase: " + executingPhase);
98 }
99 }
100
101 if (name.equalsIgnoreCase(currentPhase))
102 {
103 throw new IllegalStateException("Already in lifecycle phase '" + name + "', cannot fire the same phase twice");
104 }
105
106
107 if (!phaseNames.contains(name))
108 {
109 throw new IllegalStateException("Phase does not exist: " + name);
110 }
111 else
112 {
113 if (isDirectTransition(name))
114 {
115 return;
116 }
117
118 throw new IllegalStateException("Lifecycle Manager '" + lifecycleManagerId + "' phase '" + currentPhase + "' does not support phase '" + name + "'");
119 }
120 }
121
122 public O getLifecycleObject()
123 {
124 return object;
125 }
126
127 public void fireLifecycle(String phase) throws LifecycleException
128 {
129 checkPhase(phase);
130 invokePhase(phase, object, callbacks.get(phase));
131 }
132
133 protected void invokePhase(String phase, Object object, LifecycleCallback callback) throws LifecycleException
134 {
135 try
136 {
137 setExecutingPhase(phase);
138 callback.onTransition(phase, object);
139 setCurrentPhase(phase);
140 }
141
142 catch (ConnectException ce)
143 {
144 MuleContext muleContext = ((AbstractConnector) ce.getFailed()).getMuleContext();
145 muleContext.getExceptionListener().handleException(ce);
146 }
147 catch (LifecycleException le)
148 {
149 throw le;
150 }
151 catch (Exception e)
152 {
153 throw new LifecycleException(e, object);
154 }
155 finally
156 {
157 setExecutingPhase(null);
158 }
159
160 }
161
162 public boolean isDirectTransition(String destinationPhase)
163 {
164 return isDirectTransition(getCurrentPhase(), destinationPhase);
165 }
166
167 protected boolean isDirectTransition(String startPhase, String endPhase)
168 {
169 String key = startPhase + "-" + endPhase;
170 return directTransitions.contains(key);
171 }
172
173 public String getCurrentPhase()
174 {
175 return currentPhase;
176 }
177
178 protected void setCurrentPhase(String currentPhase)
179 {
180 this.currentPhase = currentPhase;
181 completedPhases.add(currentPhase);
182
183 if (currentPhase.equals(Stoppable.PHASE_NAME))
184 {
185 completedPhases.remove(Startable.PHASE_NAME);
186 }
187 else if (currentPhase.equals(Startable.PHASE_NAME))
188 {
189 completedPhases.remove(Stoppable.PHASE_NAME);
190 }
191 else if (currentPhase.equals(Disposable.PHASE_NAME))
192 {
193 completedPhases.remove(Initialisable.PHASE_NAME);
194 }
195
196 notifyTransition(currentPhase);
197
198 }
199
200 public String getExecutingPhase()
201 {
202 return executingPhase;
203 }
204
205 protected void setExecutingPhase(String executingPhase)
206 {
207 this.executingPhase = executingPhase;
208 }
209
210
211
212
213
214
215
216
217 protected void notifyTransition(String phase)
218 {
219
220 }
221
222 public void reset()
223 {
224 completedPhases.clear();
225 setExecutingPhase(null);
226 setCurrentPhase(NOT_IN_LIFECYCLE_PHASE.getName());
227 completedPhases.add(getCurrentPhase());
228 }
229
230 public boolean isPhaseComplete(String phaseName)
231 {
232 return completedPhases.contains(phaseName);
233 }
234
235 public LifecycleState getState()
236 {
237 return state;
238 }
239 }