001 package com.croftsoft.core.lang.lifecycle;
002
003 /*********************************************************************
004 * Strictly enforces the Lifecycle method calling order by frameworks.
005 *
006 * <p>
007 * Methods throw an IllegalStateException if they are called out of
008 * order. The acceptable state transition sequence is as follows:
009 * <code>
010 * <pre>
011 * init() --> ( start() --> stop() )* --> destroy().
012 * </pre>
013 * </code>
014 * [* start() then stop() may be called zero or more times.]
015 *
016 * <p>
017 * LifecycleEnforcer can be used via inheritance, by delegation, or as
018 * a wrapper.
019 * </p>
020 *
021 * <p>
022 * When used via inheritance, LifecycleEnforcer is subclassed and
023 * the subclass methods call the corresponding superclass methods
024 * as their first actions.
025 * </p>
026 *
027 * <p>
028 * Inheritance example:
029 * <code>
030 * <pre>
031 * public class ActiveResource1
032 * extends LifecycleEnforcer
033 * {
034 * public ActiveResource1 ( )
035 * {
036 * super ( ); // use the zero argument superclass constructor
037 *
038 * // insert subclass specific constructor code here
039 * }
040 *
041 * public void init ( )
042 * {
043 * super.init ( ); // may throw IllegalStateException
044 *
045 * // insert subclass specific initialization here
046 * }
047 *
048 * public void start ( )
049 * {
050 * super.start ( ); // may throw IllegalStateException
051 *
052 * // insert subclass specific start code here
053 * }
054 *
055 * public void stop ( )
056 * {
057 * super.stop ( ); // may throw IllegalStateException
058 *
059 * // insert subclass specific stop code here
060 * }
061 *
062 * public void destroy ( )
063 * {
064 * super.destroy ( ); // may throw IllegalStateException
065 *
066 * // insert subclass specific destroy code here
067 * }
068 * }
069 * </pre>
070 * </code>
071 * </p>
072 *
073 * <p>
074 * When used via delegation, it is much like inheritance
075 * except that a reference is maintained to a LifecycleEnforcer
076 * instead of subclassing from it. The containing Lifecycle
077 * instance will delegate Lifecycle method calls to the delegate
078 * LifecycleEnforcer as the first action.
079 * </p>
080 *
081 * <p>
082 * Delegation example:
083 * <code>
084 * <pre>
085 * public class ActiveResource2
086 * {
087 * private final Lifecycle lifecycleEnforcer;
088 *
089 * public ActiveResource1 ( )
090 * {
091 * lifecycleEnforcer = new LifecycleEnforcer ( );
092 * }
093 *
094 * public void init ( )
095 * {
096 * lifecycleEnforcer.init ( ); // may throw IllegalStateException
097 *
098 * // insert subclass specific initialization here
099 * }
100 *
101 * public void start ( )
102 * {
103 * lifecycleEnforcer.start ( ); // may throw IllegalStateException
104 *
105 * // insert subclass specific start code here
106 * }
107 *
108 * public void stop ( )
109 * {
110 * lifecycleEnforcer.stop ( ); // may throw IllegalStateException
111 *
112 * // insert subclass specific stop code here
113 * }
114 *
115 * public void destroy ( )
116 * {
117 * lifecycleEnforcer.destroy ( ); // may throw IllegalStateException
118 *
119 * // insert subclass specific destroy code here
120 * }
121 * }
122 * </pre>
123 * </code>
124 * </p>
125 *
126 * <p>
127 * When used as a wrapper, LifecycleEnforcer acts as a
128 * protective exterior around a private Lifecycle instance.
129 * Calls to the lifecycle methods are delegated to the
130 * private instance only after checking for proper state
131 * transitions. The wrapper
132 * has the added benefit of effectively making all but the
133 * lifecycle methods of the private instance inaccessible by
134 * direct reference.
135 * </p>
136 *
137 * <p>
138 * Wrapper example:
139 * <code>
140 * <pre>
141 * Lifecycle unprotectedLifecycle = new ActiveResource3 ( );
142 *
143 * Lifecycle protectedLifecycle
144 * = new LifecycleEnforcer ( unprotectedLifecycle );
145 *
146 * untrustedFramework.manageLifecycleObject ( protectedLifecycle );
147 * </pre>
148 * </code>
149 * </p>
150 *
151 * @version
152 * 2001-05-31
153 * @since
154 * 2001-03-08
155 * @author
156 * <A HREF="http://www.alumni.caltech.edu/~croft">David W. Croft</A>
157 *********************************************************************/
158
159 public class LifecycleEnforcer
160 implements Lifecycle
161 //////////////////////////////////////////////////////////////////////
162 //////////////////////////////////////////////////////////////////////
163 {
164
165 public static final int STATE_UNINITIALIZED = 0;
166
167 public static final int STATE_INITIALIZED = 1;
168
169 public static final int STATE_STARTED = 2;
170
171 public static final int STATE_STOPPED = 3;
172
173 public static final int STATE_DESTROYED = 4;
174
175 private final Lifecycle lifecycle;
176
177 private int state = STATE_UNINITIALIZED;
178
179
180 //////////////////////////////////////////////////////////////////////
181 //////////////////////////////////////////////////////////////////////
182
183 public LifecycleEnforcer ( Lifecycle lifecycle )
184 //////////////////////////////////////////////////////////////////////
185 {
186 this.lifecycle = lifecycle;
187 }
188
189 public LifecycleEnforcer ( )
190 //////////////////////////////////////////////////////////////////////
191 {
192 this.lifecycle = null;
193 }
194
195 //////////////////////////////////////////////////////////////////////
196 //////////////////////////////////////////////////////////////////////
197
198 public synchronized int getState ( ) { return state; }
199
200 //////////////////////////////////////////////////////////////////////
201 //////////////////////////////////////////////////////////////////////
202
203 public synchronized void init ( )
204 //////////////////////////////////////////////////////////////////////
205 {
206 switch ( state )
207 {
208 case STATE_UNINITIALIZED:
209
210 break;
211
212 case STATE_INITIALIZED:
213
214 // drop through
215
216 case STATE_STARTED:
217
218 // drop through
219
220 case STATE_STOPPED:
221
222 throw new IllegalStateException ( "already initialized" );
223
224 case STATE_DESTROYED:
225
226 throw new IllegalStateException ( "destroyed" );
227
228 default:
229
230 throw new IllegalStateException ( "illegal state: " + state );
231 }
232
233 if ( lifecycle != null )
234 {
235 lifecycle.init ( );
236 }
237
238 state = STATE_INITIALIZED;
239 }
240
241 public synchronized void start ( )
242 //////////////////////////////////////////////////////////////////////
243 {
244 switch ( state )
245 {
246 case STATE_UNINITIALIZED:
247
248 throw new IllegalStateException ( "not yet initialized" );
249
250 case STATE_INITIALIZED:
251
252 break;
253
254 case STATE_STARTED:
255
256 throw new IllegalStateException ( "already started" );
257
258 case STATE_STOPPED:
259
260 break;
261
262 case STATE_DESTROYED:
263
264 throw new IllegalStateException ( "destroyed" );
265
266 default:
267
268 throw new IllegalStateException ( "illegal state: " + state );
269 }
270
271 if ( lifecycle != null )
272 {
273 lifecycle.start ( );
274 }
275
276 state = STATE_STARTED;
277 }
278
279 public synchronized void stop ( )
280 //////////////////////////////////////////////////////////////////////
281 {
282 switch ( state )
283 {
284 case STATE_UNINITIALIZED:
285
286 throw new IllegalStateException ( "not yet initialized" );
287
288 case STATE_INITIALIZED:
289
290 throw new IllegalStateException ( "not yet started" );
291
292 case STATE_STARTED:
293
294 break;
295
296 case STATE_STOPPED:
297
298 throw new IllegalStateException ( "already stopped" );
299
300 case STATE_DESTROYED:
301
302 throw new IllegalStateException ( "destroyed" );
303
304 default:
305
306 throw new IllegalStateException ( "illegal state: " + state );
307 }
308
309 if ( lifecycle != null )
310 {
311 lifecycle.stop ( );
312 }
313
314 state = STATE_STOPPED;
315 }
316
317 public synchronized void destroy ( )
318 //////////////////////////////////////////////////////////////////////
319 {
320 switch ( state )
321 {
322 case STATE_UNINITIALIZED:
323
324 throw new IllegalStateException ( "not yet initialized" );
325
326 case STATE_INITIALIZED:
327
328 break;
329
330 case STATE_STARTED:
331
332 throw new IllegalStateException ( "not stopped" );
333
334 case STATE_STOPPED:
335
336 break;
337
338 case STATE_DESTROYED:
339
340 throw new IllegalStateException ( "already destroyed" );
341
342 default:
343
344 throw new IllegalStateException ( "illegal state: " + state );
345 }
346
347 if ( lifecycle != null )
348 {
349 lifecycle.destroy ( );
350 }
351
352 state = STATE_DESTROYED;
353 }
354
355 //////////////////////////////////////////////////////////////////////
356 //////////////////////////////////////////////////////////////////////
357 }