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         }