Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » scanner » [javadoc | source]
    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;
   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 shutdownHook;
   71      
   72   
   73      /////////////////////////////////////////////////////////////////////////
   74      //                           DeploymentScanner                         //
   75      /////////////////////////////////////////////////////////////////////////
   76   
   77      public void setDeployer(final ObjectName 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 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("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;
  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
  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 lock = new Object();
  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 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 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 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 ignore) {}
  283            }
  284         }
  285      }
  286   
  287   
  288      /////////////////////////////////////////////////////////////////////////
  289      //                     Service/ServiceMBeanSupport                     //
  290      /////////////////////////////////////////////////////////////////////////
  291   
  292      protected void createService() throws Exception
  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("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 e)
  326         {
  327            log.warn("Failed to add shutdown hook", e);
  328         }
  329      }
  330   
  331      protected void startService() throws Exception 
  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 
  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 
  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 ignore)
  375         {
  376         } // who cares really
  377   
  378         // help gc
  379         shutdownHook = null;
  380         scannerThread = null;
  381      }
  382   }

Save This Page
Home » jboss-5.0.0.CR1-src » org » jboss » deployment » scanner » [javadoc | source]