View Javadoc

1   /*
2    Copyright 2010 Ramon Servadei
3   
4    Licensed under the Apache License, Version 2.0 (the "License");
5    you may not use this file except in compliance with the License.
6    You may obtain a copy of the License at
7   
8    http://www.apache.org/licenses/LICENSE-2.0
9   
10   Unless required by applicable law or agreed to in writing, software
11   distributed under the License is distributed on an "AS IS" BASIS,
12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   See the License for the specific language governing permissions and
14   limitations under the License.
15   */
16  package mirrormap.lifecycle;
17  
18  import java.util.logging.Level;
19  import java.util.logging.Logger;
20  
21  import mirrormap.Utils;
22  
23  /**
24   * Base-class for all {@link ILifeCycle} instances.
25   * 
26   * @author Ramon Servadei
27   */
28  public abstract class AbstractLifeCycle implements ILifeCycle
29  {
30      private final static Logger LOGGER =
31          Logger.getLogger(AbstractLifeCycle.class.getName());
32  
33      /**
34       * The active flag. Uses the <a
35       * href="http://www.ibm.com/developerworks/java/library/j-jtp06197.html"
36       * >'cheap read-write lock'</a>
37       */
38      private volatile boolean active;
39  
40      public AbstractLifeCycle()
41      {
42          super();
43      }
44  
45      public final boolean isActive()
46      {
47          return this.active;
48      }
49  
50      /**
51       * Overridden in subclasses to perform custom logic on activation. Any
52       * exceptions should be thrown as a {@link RuntimeException} or subclass
53       * thereof. When this method is called, the {@link #isActive()} method will
54       * return <code>true</code>.
55       */
56      protected abstract void doStart();
57  
58      /**
59       * Overridden in subclasses to perform custom logic on destruction. Any
60       * exceptions should be thrown as a {@link RuntimeException} or subclass
61       * thereof.
62       */
63      protected abstract void doDestroy();
64  
65      public final void start()
66      {
67          boolean start = false;
68          synchronized (this)
69          {
70              if (!isActive())
71              {
72                  this.active = true;
73                  start = true;
74              }
75          }
76          if (start)
77          {
78              if (LOGGER.isLoggable(Level.FINEST))
79              {
80                  LOGGER.finest("Starting " + Utils.safeToString(this));
81              }
82              try
83              {
84                  doStart();
85              }
86              catch (RuntimeException e)
87              {
88                  Utils.logException(LOGGER, "Exception starting "
89                      + Utils.safeToString(this), e);
90                  throw e;
91              }
92          }
93      }
94  
95      public final void destroy()
96      {
97          boolean destroy = false;
98          synchronized (this)
99          {
100             if (isActive())
101             {
102                 this.active = false;
103                 destroy = true;
104             }
105         }
106         if (destroy)
107         {
108             if (LOGGER.isLoggable(Level.FINEST))
109             {
110                 LOGGER.finest("Destroying " + Utils.safeToString(this));
111             }
112             try
113             {
114                 doDestroy();
115             }
116             catch (RuntimeException e)
117             {
118                 Utils.logException(LOGGER, "Exception destroying "
119                     + Utils.safeToString(this), e);
120             }
121         }
122     }
123 
124     @Override
125     protected final void finalize() throws Throwable
126     {
127         super.finalize();
128         destroy();
129     }
130 
131     /**
132      * Check if this instance is active.
133      * 
134      * @throws IllegalStateException
135      *             if this is not active
136      */
137     protected void checkActive()
138     {
139         if (!isActive())
140         {
141             throw new IllegalStateException(this + " is not active.");
142         }
143     }
144 
145     @Override
146     public String toString()
147     {
148         return getClass().getSimpleName();
149     }
150 }