1 package org.apache.fulcrum.yaafi.service.shutdown;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.io.File;
23 import java.security.MessageDigest;
24
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.activity.Initializable;
27 import org.apache.avalon.framework.activity.Startable;
28 import org.apache.avalon.framework.configuration.Configuration;
29 import org.apache.avalon.framework.configuration.ConfigurationException;
30 import org.apache.avalon.framework.configuration.Reconfigurable;
31 import org.apache.avalon.framework.context.Context;
32 import org.apache.avalon.framework.context.ContextException;
33 import org.apache.avalon.framework.context.Contextualizable;
34 import org.apache.avalon.framework.logger.AbstractLogEnabled;
35 import org.apache.avalon.framework.service.ServiceException;
36 import org.apache.avalon.framework.service.ServiceManager;
37 import org.apache.avalon.framework.service.Serviceable;
38
39
40 /**
41 * Monitors the componentConfiguration.xml and triggers a reconfiguration
42 * if the content of the component configuration file has changed.
43 *
44 * @author <a href="mailto:siegfried.goeschl@it20one.at">Siegfried Goeschl</a>
45 */
46
47 public class ShutdownServiceImpl
48 extends AbstractLogEnabled
49 implements ShutdownService, Serviceable, Contextualizable,
50 Reconfigurable, Initializable, Runnable, Startable, Disposable
51 {
52 /** the interval between two checks in ms */
53 private int interval;
54
55 /** shall the worker thread terminate immediately */
56 private boolean terminateNow;
57
58 /** the worker thread polling the resource */
59 private Thread workerThread;
60
61 /** the ServiceManager to use */
62 private ServiceManager serviceManager;
63
64 /** the application directory */
65 private File applicationDir;
66
67 /** our own and only shutdown entry */
68 private ShutdownEntry shutdownEntry;
69
70
71
72
73
74 /**
75 * Constructor
76 */
77 public ShutdownServiceImpl()
78 {
79 this.terminateNow = false;
80 }
81
82 /**
83 * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
84 */
85 public void service(ServiceManager manager) throws ServiceException
86 {
87 this.serviceManager = manager;
88 }
89
90 /**
91 * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
92 */
93 public void contextualize(Context context) throws ContextException
94 {
95 this.applicationDir = (File) context.get("urn:avalon:home");
96 }
97
98 /**
99 * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
100 */
101 public void configure(Configuration configuration) throws ConfigurationException
102 {
103
104
105 this.interval = Math.max( configuration.getAttributeAsInteger("interval",5000), 1000 );
106
107 this.getLogger().debug( "Monitoring the resources every " + this.interval + " ms" );
108
109 if( configuration.getChild("entry",false) != null )
110 {
111 Configuration shutdownConfig = configuration.getChild("entry");
112
113 String shutdownEntryLocation = shutdownConfig.getChild("location").getValue();
114
115 this.shutdownEntry = new ShutdownEntry(
116 this.getLogger(),
117 this.applicationDir,
118 shutdownEntryLocation,
119 shutdownConfig.getChild("useSystemExit").getValueAsBoolean(false)
120 );
121
122 this.getLogger().debug( "Using a shutdown entry : " + shutdownEntryLocation );
123 }
124 else
125 {
126 this.shutdownEntry = null;
127 this.getLogger().debug( "No shutdown entry defined" );
128 }
129 }
130
131 /**
132 * @see org.apache.avalon.framework.activity.Initializable#initialize()
133 */
134 public void initialize() throws Exception
135 {
136
137
138 MessageDigest.getInstance( "SHA1" );
139
140
141
142 if( (this.serviceManager instanceof Disposable) == false )
143 {
144 String msg = "The ServiceManager instance does not implement Disposable?!";
145 throw new IllegalArgumentException( msg );
146 }
147
148
149
150 this.workerThread = new Thread( this, "ShutdownService" );
151 }
152
153 /**
154 * @see org.apache.avalon.framework.activity.Startable#start()
155 */
156 public void start() throws Exception
157 {
158 this.getLogger().debug( "Starting worker thread ..." );
159 this.workerThread.start();
160 }
161
162 /**
163 * @see org.apache.avalon.framework.activity.Startable#stop()
164 */
165 public void stop() throws Exception
166 {
167 this.getLogger().debug( "Stopping worker thread ..." );
168 this.terminateNow = true;
169 this.workerThread.interrupt();
170 this.workerThread.join( 10000 );
171 }
172
173 /**
174 * @see org.apache.avalon.framework.activity.Disposable#dispose()
175 */
176 public void dispose()
177 {
178 this.terminateNow = false;
179 this.applicationDir = null;
180 this.workerThread = null;
181 this.serviceManager = null;
182 }
183
184 /**
185 * @see org.apache.avalon.framework.configuration.Reconfigurable#reconfigure(org.apache.avalon.framework.configuration.Configuration)
186 */
187 public void reconfigure(Configuration configuration)
188 throws ConfigurationException
189 {
190 this.configure(configuration);
191 }
192
193
194
195
196
197 /**
198 * @see java.lang.Runnable#run()
199 */
200 public void run()
201 {
202 while( this.terminateNow == false )
203 {
204 try
205 {
206 Thread.sleep( this.interval );
207 }
208 catch (InterruptedException e)
209 {
210
211 }
212
213 if( this.hasShutdownEntry() && this.getShutdownEntry().hasChanged() )
214 {
215 if( this.serviceManager instanceof Disposable )
216 {
217 if( this.getShutdownEntry().isUseSystemExit() )
218 {
219 this.getLogger().warn( "Forcing a shutdown using System.exit() ..." );
220 }
221 else
222 {
223 this.getLogger().warn( "Forcing a shutdown ..." );
224 }
225
226
227
228 Shutdown shutdown = new Shutdown(
229 (Disposable) this.serviceManager,
230 this.getShutdownEntry().isUseSystemExit()
231 );
232
233 Thread shutdownThread = new Thread( shutdown, "ShutdownServiceThread" );
234 shutdownThread.setDaemon(true);
235 shutdownThread.start();
236 }
237 }
238 }
239 }
240
241
242
243
244
245 /**
246 * @return Returns the shutdownEntry.
247 */
248 private ShutdownEntry getShutdownEntry()
249 {
250 return this.shutdownEntry;
251 }
252
253 /**
254 * @return Is a shutdown entry defined?
255 */
256 private boolean hasShutdownEntry()
257 {
258 return ( this.shutdownEntry != null ? true : false );
259 }
260 }