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 }