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