KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > lifecycle > Lifecycle


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.lifecycle;
31
32 import com.caucho.util.Alarm;
33
34 import java.lang.ref.WeakReference JavaDoc;
35 import java.util.ArrayList JavaDoc;
36 import java.util.logging.Level JavaDoc;
37 import java.util.logging.Logger JavaDoc;
38
39 /**
40  * Lifecycle class.
41  */

42 public final class Lifecycle implements LifecycleState {
43   private final Logger JavaDoc _log;
44   private String JavaDoc _name;
45   private Level JavaDoc _level = Level.FINE;
46   
47   private int _state;
48
49   private long _activeCount;
50   private long _failCount;
51
52   private long _lastFailTime;
53   private long _lastChangeTime;
54
55   private ArrayList JavaDoc<WeakReference JavaDoc<LifecycleListener>> _listeners;
56
57   /**
58    * Creates an anonymous lifecycle.
59    */

60   public Lifecycle()
61   {
62     _log = null;
63   }
64
65   /**
66    * Creates an lifecycle with logger and name.
67    */

68   public Lifecycle(Logger JavaDoc log)
69   {
70     _log = log;
71   }
72
73   /**
74    * Creates an lifecycle with logger and name.
75    */

76   public Lifecycle(Logger JavaDoc log, String JavaDoc name)
77   {
78     _log = log;
79     _name = name;
80   }
81
82   /**
83    * Creates an lifecycle with logger, a name, and a level.
84    */

85   public Lifecycle(Logger JavaDoc log, String JavaDoc name, Level JavaDoc level)
86   {
87     _log = log;
88     _name = name;
89     _level = level;
90   }
91
92   /**
93    * Gets the lifecycle name.
94    */

95   public String JavaDoc getName()
96   {
97     return _name;
98   }
99
100   /**
101    * Sets the lifecycle name, and the level to Level.INFO.
102    */

103   public void setName(String JavaDoc name)
104   {
105     _name = name;
106   }
107
108   /**
109    * Gets the lifecycle logging level.
110    */

111   public Level JavaDoc getLevel()
112   {
113     return _level;
114   }
115
116   /**
117    * Sets the lifecycle logging level.
118    */

119   public void setLevel(Level JavaDoc level)
120   {
121     _level = level;
122   }
123
124   /**
125    * Adds a listener to detect lifecycle changes.
126    */

127   public void addListener(LifecycleListener listener)
128   {
129     synchronized (this) {
130       if (isDestroyed()) {
131         IllegalStateException JavaDoc e = new IllegalStateException JavaDoc("attempted to add listener to a destroyed lifecyle " + this);
132
133         if (_log != null)
134           _log.log(Level.WARNING, e.toString(), e);
135         else
136           Logger.getLogger(Lifecycle.class.getName()).log(Level.WARNING, e.toString(), e);
137
138         return;
139       }
140
141       if (_listeners == null)
142         _listeners = new ArrayList JavaDoc<WeakReference JavaDoc<LifecycleListener>>();
143
144       for (int i = _listeners.size() - 1; i >= 0; i--) {
145         LifecycleListener oldListener = _listeners.get(i).get();
146
147         if (listener == oldListener)
148           return;
149         else if (oldListener == null)
150           _listeners.remove(i);
151       }
152
153       _listeners.add(new WeakReference JavaDoc<LifecycleListener>(listener));
154     }
155   }
156
157   /**
158    * Removes a listener.
159    */

160   public void removeListener(LifecycleListener listener)
161   {
162     synchronized (this) {
163
164       if (_listeners == null)
165         return;
166
167       for (int i = _listeners.size() - 1; i >= 0; i--) {
168         LifecycleListener oldListener = _listeners.get(i).get();
169
170         if (listener == oldListener) {
171           _listeners.remove(i);
172
173           return;
174         }
175         else if (oldListener == null)
176           _listeners.remove(i);
177       }
178     }
179   }
180
181   /**
182    * Returns the listeners.
183    */

184   private void notifyListeners(int oldState, int newState)
185   {
186     synchronized (this) {
187       if (_listeners == null) {
188         return;
189       }
190       else {
191         for (int i = 0; i < _listeners.size(); i++) {
192           LifecycleListener listener = _listeners.get(i).get();
193
194           if (listener != null) {
195             listener.lifecycleEvent(oldState, newState);
196           }
197           else {
198             _listeners.remove(i);
199             i--;
200           }
201         }
202       }
203     }
204   }
205
206   /**
207    * Returns the current state.
208    */

209   public int getState()
210   {
211     return _state;
212   }
213
214   /**
215    * Returns the state name for the passed state.
216    */

217   public static String JavaDoc getStateName(int state)
218   {
219     switch (state) {
220       case IS_NEW:
221         return "new";
222       case IS_INITIALIZING:
223         return "initializing";
224       case IS_INIT:
225         return "init";
226       case IS_STARTING:
227         return "starting";
228       case IS_ACTIVE:
229         return "active";
230       case IS_FAILED:
231         return "failed";
232       case IS_STOPPING:
233         return "stopping";
234       case IS_STOPPED:
235         return "stopped";
236       case IS_DESTROYING:
237         return "destroying";
238       case IS_DESTROYED:
239         return "destroyed";
240       default:
241         return "unknown";
242     }
243   }
244
245   /**
246    * Returns the current state name.
247    */

248   public String JavaDoc getStateName()
249   {
250     return getStateName(_state);
251   }
252
253   /**
254    * Returns the last lifecycle change time.
255    */

256   public long getLastChangeTime()
257   {
258     return _lastChangeTime;
259   }
260
261   /**
262    * Returns the last failure time.
263    */

264   public long getLastFailTime()
265   {
266     return _lastFailTime;
267   }
268
269   /**
270    * Returns the number of times the lifecycle has switched to active.
271    */

272   public long getActiveCount()
273   {
274     return _activeCount;
275   }
276
277   /**
278    * Returns the number of times the lifecycle has switched to failing.
279    */

280   public long getFailCount()
281   {
282     return _failCount;
283   }
284
285   /**
286    * Returns true for the initializing state.
287    */

288   public boolean isInitializing()
289   {
290     return _state == IS_INITIALIZING;
291   }
292
293   /**
294    * Returns true for the init state.
295    */

296   public boolean isInit()
297   {
298     return _state == IS_INIT;
299   }
300
301   /**
302    * Returns true for the init state.
303    */

304   public boolean isBeforeInit()
305   {
306     return _state < IS_INIT;
307   }
308
309   /**
310    * Returns true for the init state.
311    */

312   public boolean isAfterInit()
313   {
314     return _state >= IS_INIT;
315   }
316
317   /**
318    * Returns true if the service is starting.
319    */

320   public boolean isStarting()
321   {
322     return _state == IS_STARTING;
323   }
324
325   /**
326    * Returns true for the warmup state.
327    */

328   public boolean isWarmup()
329   {
330     return _state == IS_WARMUP;
331   }
332
333   /**
334    * Returns true for the initializing state.
335    */

336   public boolean isBeforeActive()
337   {
338     return _state < IS_ACTIVE;
339   }
340
341   /**
342    * Returns true for the closing states
343    */

344   public boolean isAfterActive()
345   {
346     return IS_ACTIVE < _state;
347   }
348
349   /**
350    * Wait for a period of time until the service starts.
351    */

352   public boolean waitForActive(long timeout)
353   {
354     if (_state == IS_ACTIVE)
355       return true;
356     
357     long waitEnd = Alarm.getCurrentTime() + timeout;
358     
359     synchronized (this) {
360       while (Alarm.getCurrentTime() < waitEnd) {
361     if (_state == IS_ACTIVE)
362       return true;
363     else if (IS_ACTIVE < _state)
364       return false;
365     else if (Alarm.isTest())
366       return false;
367
368     try {
369       wait(waitEnd - Alarm.getCurrentTime());
370     } catch (InterruptedException JavaDoc e) {
371     }
372       }
373     }
374     
375     return _state == IS_ACTIVE;
376   }
377
378   /**
379    * Returns true for the active state.
380    */

381   public boolean isActive()
382   {
383     return _state == IS_ACTIVE;
384   }
385
386   /**
387    * Returns true for the a runnable state, including warmup
388    */

389   public boolean isRunnable()
390   {
391     return IS_WARMUP <= _state && _state <= IS_ACTIVE;
392   }
393
394   /**
395    * Returns true for the failed state.
396    */

397   public boolean isError()
398   {
399     return isFailed();
400   }
401
402   /**
403    * Returns true for the failed state.
404    */

405   public boolean isFailed()
406   {
407     return _state == IS_FAILED;
408   }
409
410   /**
411    * Returns true if the state is stopping.
412    */

413   public boolean isStopping()
414   {
415     return IS_STOPPING <= _state;
416   }
417
418   /**
419    * Returns true if the state is stopping.
420    */

421   public boolean isStopped()
422   {
423     return IS_STOPPING <= _state;
424   }
425
426   /**
427    * Returns true if the state is closed
428    */

429   public boolean isDestroying()
430   {
431     return IS_DESTROYING <= _state;
432   }
433
434   /**
435    * Returns true if the state is closed
436    */

437   public boolean isDestroyed()
438   {
439     return IS_DESTROYED <= _state;
440   }
441   
442   /**
443    * Changes to the initializing state.
444    *
445    * @return true if the transition is allowed
446    */

447   public synchronized boolean toInitializing()
448   {
449     if (IS_INITIALIZING <= _state)
450       return false;
451
452     int oldState = _state;
453
454     _state = IS_INITIALIZING;
455     _lastChangeTime = Alarm.getCurrentTime();
456
457     if (_log != null && _log.isLoggable(Level.FINE))
458       _log.fine(_name + " initializing");
459
460     notifyListeners(oldState, _state);
461
462     return true;
463   }
464
465   /**
466     * Changes to the init state.
467     *
468     * @return true if the transition is allowed
469     */

470    public synchronized boolean toInit()
471    {
472      if (IS_INIT <= _state)
473        return false;
474
475      int oldState = _state;
476
477      _state = IS_INIT;
478      _lastChangeTime = Alarm.getCurrentTime();
479
480      if (_log != null && _log.isLoggable(Level.FINE))
481        _log.fine(_name + " initialized");
482
483      notifyListeners(oldState, _state);
484
485      return true;
486    }
487   /**
488     * Changes to the init from the stopped state.
489     *
490     * @return true if the transition is allowed
491     */

492    public synchronized boolean toPostInit()
493    {
494      if (IS_STOPPED == _state) {
495        int oldState = _state;
496
497        _state = IS_INIT;
498        _lastChangeTime = Alarm.getCurrentTime();
499
500        notifyListeners(oldState, _state);
501
502        return true;
503      }
504      else if (IS_INIT == _state) {
505        return true;
506      }
507
508      return false;
509    }
510
511   /**
512    * Changes to the starting state.
513    *
514    * @return true if the transition is allowed
515    */

516   public synchronized boolean toStarting()
517   {
518     if (_state < IS_STARTING || _state == IS_STOPPED) {
519       int oldState = _state;
520
521       _state = IS_STARTING;
522        _lastChangeTime = Alarm.getCurrentTime();
523
524       if (_log != null && _log.isLoggable(_level))
525     _log.log(_level, _name + " starting");
526
527       notifyListeners(oldState, _state);
528
529       return true;
530     }
531     else
532       return false;
533   }
534   
535   /**
536    * Changes to the active state.
537    *
538    * @return true if the transition is allowed
539    */

540   public synchronized boolean toActive()
541   {
542     if (_state < IS_ACTIVE || IS_FAILED <= _state && _state <= IS_STOPPED) {
543       int oldState = _state;
544
545       _state = IS_ACTIVE;
546       _lastChangeTime = Alarm.getCurrentTime();
547       _activeCount++;
548        
549       if (_log != null && _log.isLoggable(Level.FINE))
550     _log.fine(_name + " active");
551
552       notifyListeners(oldState, _state);
553
554       notifyAll();
555
556       return true;
557     }
558     else
559       return false;
560   }
561   
562   /**
563    * Changes to the error state.
564    *
565    * @return true if the transition is allowed
566    */

567   public boolean toError()
568   {
569     return toFail();
570   }
571   
572   /**
573    * Changes to the failed state.
574    *
575    * @return true if the transition is allowed
576    */

577   public synchronized boolean toFail()
578   {
579     if (_state < IS_DESTROYING && _state != IS_FAILED) {
580       int oldState = _state;
581
582       _state = IS_FAILED;
583       _lastChangeTime = Alarm.getCurrentTime();
584       _failCount++;
585
586       if (_log != null && _log.isLoggable(_level))
587     _log.log(_level, _name + " error");
588
589       notifyListeners(oldState, _state);
590
591       notifyAll();
592
593       return true;
594     }
595     else
596       return false;
597   }
598   
599   /**
600    * Changes to the stopping state.
601    *
602    * @return true if the transition is allowed
603    */

604   public synchronized boolean toStopping()
605   {
606     if (_state < IS_STOPPING && _state != IS_STARTING) {
607       int oldState = _state;
608
609       _state = IS_STOPPING;
610       _lastChangeTime = Alarm.getCurrentTime();
611
612       if (_log != null && _log.isLoggable(_level))
613     _log.log(_level, _name + " stopping");
614
615       notifyListeners(oldState, _state);
616
617       return true;
618     }
619     else
620       return false;
621   }
622   
623   /**
624    * Changes to the stopped state.
625    *
626    * @return true if the transition is allowed
627    */

628   public synchronized boolean toStop()
629   {
630     if (_state < IS_STOPPED) {
631       if (_log == null) {
632       }
633       else if (_state < IS_STOPPING && _log.isLoggable(_level))
634     _log.log(_level, _name + " stopped");
635       else if (_log.isLoggable(Level.FINE))
636     _log.fine(_name + " stopped");
637       
638       int oldState = _state;
639
640       _state = IS_STOPPED;
641       _lastChangeTime = Alarm.getCurrentTime();
642
643       notifyListeners(oldState, _state);
644
645       notifyAll();
646
647       return true;
648     }
649     else
650       return false;
651   }
652   
653   /**
654    * Changes to the destroying state.
655    *
656    * @return true if the transition is allowed
657    */

658   public synchronized boolean toDestroying()
659   {
660     if (_state < IS_DESTROYING) {
661       int oldState = _state;
662
663       _state = IS_DESTROYING;
664       _lastChangeTime = Alarm.getCurrentTime();
665
666       if (_log != null && _log.isLoggable(Level.FINE))
667     _log.fine(_name + " destroying");
668
669       notifyListeners(oldState, _state);
670
671       return true;
672     }
673     else
674       return false;
675   }
676   
677   /**
678    * Changes to the closed state.
679    *
680    * @return true if the transition is allowed
681    */

682   public synchronized boolean toDestroy()
683   {
684     if (_state < IS_DESTROYED) {
685       int oldState = _state;
686
687       _state = IS_DESTROYED;
688       _lastChangeTime = Alarm.getCurrentTime();
689
690       if (_log != null && _log.isLoggable(Level.FINE))
691     _log.fine(_name + " destroyed");
692
693       notifyListeners(oldState, _state);
694
695       notifyAll();
696
697       return true;
698     }
699     else
700       return false;
701   }
702   
703   /**
704    * Copies from a target state.
705    *
706    * @return true if the transition is allowed
707    */

708   public void copyState(Lifecycle source)
709   {
710     _state = source._state;
711   }
712
713   /**
714    * Debug string value.
715    */

716   public String JavaDoc toString()
717   {
718     if (_name != null)
719       return "Lifecycle[" + _name + ", " + getStateName() + "]";
720     else
721       return "Lifecycle[" + getStateName() + "]";
722   }
723 }
724
Popular Tags