KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > deployment > scanner > AbstractDeploymentScanner


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.deployment.scanner;
23
24 import javax.management.ObjectName JavaDoc;
25
26 import org.jboss.deployment.Deployer;
27 import org.jboss.deployment.MainDeployerMBean;
28 import org.jboss.logging.Logger;
29 import org.jboss.mx.util.MBeanProxyExt;
30 import org.jboss.mx.util.MBeanProxyInstance;
31 import org.jboss.system.MissingAttributeException;
32 import org.jboss.system.ServiceMBeanSupport;
33 import org.jboss.util.NullArgumentException;
34
35 import EDU.oswego.cs.dl.util.concurrent.SynchronizedBoolean;
36
37 /**
38  * An abstract support class for implementing a deployment scanner.
39  *
40  * <p>Provides the implementation of period-based scanning, as well
41  * as Deployer integration.
42  *
43  * <p>Sub-classes only need to implement {@link DeploymentScanner#scan}.
44  *
45  * @version <tt>$Revision: 57108 $</tt>
46  * @author <a HREF="mailto:jason@planet57.com">Jason Dillon</a>
47  * @author Scott.Stark@jboss.org
48  */

49 public abstract class AbstractDeploymentScanner extends ServiceMBeanSupport
50    implements DeploymentScanner, DeploymentScannerMBean
51 {
52    /** The scan period in milliseconds */
53    protected long scanPeriod = 5000;
54
55    /** True if period based scanning is enabled. */
56    protected boolean scanEnabled = true;
57
58    /** The stop timeout */
59    protected long stopTimeOut = 60000;
60    
61    /** A proxy to the deployer we are using. */
62    protected Deployer deployer;
63
64    protected MainDeployerMBean mainDeployer;
65
66    /** The scanner thread. */
67    protected ScannerThread scannerThread;
68
69    /** HACK: Shutdown hook to get around problems with system service shutdown ordering. */
70    private Thread JavaDoc shutdownHook;
71    
72
73    /////////////////////////////////////////////////////////////////////////
74
// DeploymentScanner //
75
/////////////////////////////////////////////////////////////////////////
76

77    public void setDeployer(final ObjectName JavaDoc deployerName)
78    {
79       if (deployerName == null)
80          throw new NullArgumentException("deployerName");
81
82       deployer = (Deployer)
83          MBeanProxyExt.create(Deployer.class, deployerName, server);
84    }
85
86    public ObjectName JavaDoc getDeployer()
87    {
88       return ((MBeanProxyInstance)deployer).getMBeanProxyObjectName();
89    }
90
91    /**
92     * Period must be >= 0.
93     */

94    public void setScanPeriod(final long period)
95    {
96       if (period < 0)
97          throw new IllegalArgumentException JavaDoc("ScanPeriod must be >= 0; have: " + period);
98
99       this.scanPeriod = period;
100    }
101
102    public long getScanPeriod()
103    {
104       return scanPeriod;
105    }
106
107    public void setScanEnabled(final boolean flag)
108    {
109       this.scanEnabled = flag;
110    }
111
112    public boolean isScanEnabled()
113    {
114       return scanEnabled;
115    }
116
117    public long getStopTimeOut()
118    {
119       return stopTimeOut;
120    }
121
122    public void setStopTimeOut(long stopTimeOut)
123    {
124       this.stopTimeOut = stopTimeOut;
125    }
126
127    /** This is here to work around a bug in the IBM vm that causes an
128     * AbstractMethodError to be thrown when the ScannerThread calls scan.
129     * @throws Exception
130     */

131    public abstract void scan() throws Exception JavaDoc;
132
133    /////////////////////////////////////////////////////////////////////////
134
// Scanner Thread //
135
/////////////////////////////////////////////////////////////////////////
136

137    /**
138     * Should use Timer/TimerTask instead? This has some issues with
139     * interaction with ScanEnabled attribute. ScanEnabled works only
140     * when starting/stopping.
141     */

142    public class ScannerThread
143       extends Thread JavaDoc
144    {
145       /** We get our own logger. */
146       protected Logger scannerLog = Logger.getLogger(ScannerThread.class);
147
148       /** True if the scan loop should run. */
149       protected SynchronizedBoolean enabled = new SynchronizedBoolean(false);
150
151       /** True if we are shutting down. */
152       protected SynchronizedBoolean shuttingDown = new SynchronizedBoolean(false);
153
154       /** Lock/notify object. */
155       protected Object JavaDoc lock = new Object JavaDoc();
156
157       /** Active synchronization. */
158       protected SynchronizedBoolean active = new SynchronizedBoolean(false);
159
160       public ScannerThread(boolean enabled)
161       {
162          super("ScannerThread");
163
164          this.enabled.set(enabled);
165       }
166
167       public void setEnabled(boolean enabled)
168       {
169          this.enabled.set(enabled);
170
171          synchronized (lock)
172          {
173             lock.notifyAll();
174          }
175          
176          scannerLog.debug("Notified that enabled: " + enabled);
177       }
178
179       public void shutdown()
180       {
181          enabled.set(false);
182          shuttingDown.set(true);
183
184          synchronized (lock)
185          {
186             lock.notifyAll();
187          }
188
189          scannerLog.debug("Notified to shutdown");
190
191          // jason: shall we also interrupt this thread?
192
}
193     
194       public void run()
195       {
196          scannerLog.debug("Running");
197
198          active.set(true);
199          try
200          {
201             while (shuttingDown.get() == false)
202             {
203                // If we are not enabled, then wait
204
if (enabled.get() == false)
205                {
206                   synchronized (active)
207                   {
208                      active.set(false);
209                      active.notifyAll();
210                   }
211                   try
212                   {
213                      scannerLog.debug("Disabled, waiting for notification");
214                      synchronized (lock)
215                      {
216                         lock.wait();
217                      }
218                   }
219                   catch (InterruptedException JavaDoc ignore)
220                   {
221                   }
222                   active.set(true);
223                }
224
225                loop();
226             }
227          }
228          finally
229          {
230             synchronized (active)
231             {
232                active.set(false);
233                active.notifyAll();
234             }
235          }
236          
237          scannerLog.debug("Shutdown");
238       }
239
240       protected void waitForInactive()
241       {
242          boolean interrupted = false;
243          synchronized (active)
244          {
245             try
246             {
247                if (active.get() && stopTimeOut > 0)
248                   active.wait(stopTimeOut);
249             }
250             catch (InterruptedException JavaDoc ignored)
251             {
252                interrupted = true;
253             }
254          }
255          if (interrupted)
256             Thread.currentThread().interrupt();
257       }
258       
259       public void doScan()
260       {
261          // Scan for new/removed/changed/whatever
262
try {
263             scan();
264          }
265          catch (Exception JavaDoc e) {
266             scannerLog.error("Scanning failed; continuing", e);
267          }
268       }
269       
270       protected void loop()
271       {
272          while (enabled.get() && shuttingDown.get() == false)
273          {
274             doScan();
275
276             // Sleep for scan period
277
try
278             {
279                scannerLog.trace("Sleeping...");
280                Thread.sleep(scanPeriod);
281             }
282             catch (InterruptedException JavaDoc ignore) {}
283          }
284       }
285    }
286
287
288    /////////////////////////////////////////////////////////////////////////
289
// Service/ServiceMBeanSupport //
290
/////////////////////////////////////////////////////////////////////////
291

292    protected void createService() throws Exception JavaDoc
293    {
294       if (deployer == null)
295          throw new MissingAttributeException("Deployer");
296       mainDeployer = (MainDeployerMBean)MBeanProxyExt.create(MainDeployerMBean.class, MainDeployerMBean.OBJECT_NAME, server);
297       // setup + start scanner thread
298
scannerThread = new ScannerThread(false);
299       scannerThread.setDaemon(true);
300       scannerThread.start();
301       log.debug("Scanner thread started");
302
303       // HACK
304
//
305
// install a shutdown hook, as the current system service shutdown
306
// mechanism will not call this until all other services have stopped.
307
// we need to know soon, so we can stop scanning to try to avoid
308
// starting new services when shutting down
309

310       final ScannerThread _scannerThread = scannerThread;
311       shutdownHook = new Thread JavaDoc("DeploymentScanner Shutdown Hook")
312          {
313             ScannerThread thread = _scannerThread;
314             
315             public void run()
316             {
317                thread.shutdown();
318             }
319          };
320       
321       try
322       {
323          Runtime.getRuntime().addShutdownHook(shutdownHook);
324       }
325       catch (Exception JavaDoc e)
326       {
327          log.warn("Failed to add shutdown hook", e);
328       }
329    }
330
331    protected void startService() throws Exception JavaDoc
332    {
333       synchronized( scannerThread )
334       {
335          // scan before we enable the thread, so JBoss version shows up afterwards
336
scannerThread.doScan();
337
338          // enable scanner thread if we are enabled
339
scannerThread.setEnabled(scanEnabled);
340       }
341    }
342    
343    protected void stopService() throws Exception JavaDoc
344    {
345       // disable scanner thread
346
if( scannerThread != null )
347       {
348          scannerThread.setEnabled(false);
349          scannerThread.waitForInactive();
350       }
351    }
352
353    protected void destroyService() throws Exception JavaDoc
354    {
355       // drop our ref to deployer, so scan will fail
356
deployer = null;
357
358       // shutdown scanner thread
359
if( scannerThread != null )
360       {
361          synchronized( scannerThread )
362          {
363             scannerThread.shutdown();
364          }
365       }
366
367       // HACK
368
//
369
// remove the shutdown hook, we don't need it anymore
370
try
371       {
372          Runtime.getRuntime().removeShutdownHook(shutdownHook);
373       }
374       catch (Exception JavaDoc ignore)
375       {
376       } // who cares really
377

378       // help gc
379
shutdownHook = null;
380       scannerThread = null;
381    }
382 }
383
Popular Tags