1 /*
2 Copyright 2008 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 fulmine;
17
18 import static fulmine.util.Utils.safeToString;
19 import fulmine.util.log.AsyncLog;
20
21 /**
22 * Base-class for all {@link ILifeCycle} instances.
23 *
24 * @author Ramon Servadei
25 *
26 */
27 public abstract class AbstractLifeCycle implements ILifeCycle
28 {
29 private final static AsyncLog LOG = new AsyncLog(AbstractLifeCycle.class);
30
31 /**
32 * The active flag. Uses the <a
33 * href="http://www.ibm.com/developerworks/java/library/j-jtp06197.html"
34 * >'cheap read-write lock'</a>
35 */
36 private volatile boolean active;
37
38 public AbstractLifeCycle()
39 {
40 super();
41 }
42
43 public final boolean isActive()
44 {
45 return this.active;
46 }
47
48 /**
49 * Overridden in subclasses to perform custom logic on activation. Any
50 * exceptions should be thrown as a {@link RuntimeException} or subclass
51 * thereof. When this method is called, the {@link #isActive()} method will
52 * return <code>true</code>.
53 */
54 protected abstract void doStart();
55
56 /**
57 * Overridden in subclasses to perform custom logic on destruction. Any
58 * exceptions should be thrown as a {@link RuntimeException} or subclass
59 * thereof.
60 */
61 protected abstract void doDestroy();
62
63 public final void start()
64 {
65 boolean start = false;
66 synchronized (this)
67 {
68 if (!isActive())
69 {
70 this.active = true;
71 start = true;
72 }
73 }
74 if (start)
75 {
76 if (getLog().isTraceEnabled())
77 {
78 getLog().trace("Starting " + safeToString(this));
79 }
80 try
81 {
82 doStart();
83 }
84 catch (RuntimeException e)
85 {
86 getLog().warn("Exception starting " + safeToString(this), e);
87 throw e;
88 }
89 }
90 }
91
92 public final void destroy()
93 {
94 boolean destroy = false;
95 synchronized (this)
96 {
97 if (isActive())
98 {
99 this.active = false;
100 destroy = true;
101 }
102 }
103 if (destroy)
104 {
105 if (getLog().isTraceEnabled())
106 {
107 getLog().trace("Destroying " + safeToString(this));
108 }
109 try
110 {
111 doDestroy();
112 }
113 catch (RuntimeException e)
114 {
115 getLog().warn("Exception destroying " + safeToString(this), e);
116 }
117 }
118 }
119
120 @Override
121 protected final void finalize() throws Throwable
122 {
123 super.finalize();
124 destroy();
125 }
126
127 /**
128 * Get the log to use for the object hierarchy
129 *
130 * @return the log to use for the object hierarchy
131 */
132 protected AsyncLog getLog()
133 {
134 return LOG;
135 }
136
137 /**
138 * Check if this instance is active.
139 *
140 * @throws IllegalStateException
141 * if this is not active
142 */
143 protected void checkActive()
144 {
145 if (!isActive())
146 {
147 throw new IllegalStateException(this + " is not active.");
148 }
149 }
150
151 @Override
152 public String toString()
153 {
154 return getClass().getSimpleName();
155 }
156 }