User: user57  
  Date: 02/03/01 00:29:57

  Added:       src/main/org/jboss/deployment/scanner DeploymentScanner.java
                        DeploymentScannerMBean.java
                        DirectoryDeploymentScanner.java
                        DirectoryDeploymentScannerMBean.java package.html
  Log:
   o Seperated deployment "scanning" from MainDeployer
   o Adding DeploymentScanner APIs + default local directory based scanner
   o Moved common deployment sorting into DeploymentSorter (a temporary hack)
   o Added default scanner at the top of jboss-service.xml, which scans in
     a deploy/ directory under the server's home (aka server/default/deploy)
  
  Revision  Changes    Path
  1.1                  
jboss-system/src/main/org/jboss/deployment/scanner/DeploymentScanner.java
  
  Index: DeploymentScanner.java
  ===================================================================
  /***************************************
   *                                     *
   *  JBoss: The OpenSource J2EE WebOS   *
   *                                     *
   *  Distributable under LGPL license.  *
   *  See terms of license at gnu.org.   *
   *                                     *
   ***************************************/
  
  package org.jboss.deployment.scanner;
  
  import javax.management.ObjectName;
  
  import org.jboss.system.Service;
  
  /**
   * Provides the basic interface for a deployment scanner.
   *
   * <p>A deployment scanner scans for new, removed or changed
   *    deployments.
   *
   * @todo Expose deployer name as depenent MBean when there is
   *       a common interface for deployment management (not
   *       deployment lifecycle mgmnt).
   *
   * @version <tt>$Revision: 1.1 $</tt>
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Jason Dillon</a>
   */
  public interface DeploymentScanner
     extends Service
  {
     /**
      * Set the scan period for the scanner.
      *
      * @param period    This is the time in milliseconds between scans.
      *
      * @throws IllegalArgumentException    Period value out of range.
      */
     void setScanPeriod(long period);
  
     /**
      * Get the scan period for the scanner.
      *
      * @return    This is the time in milliseconds between scans.
      */
     long getScanPeriod();
  
     /**
      * Disable or enable the period based deployment scanning.
      *
      * <p>Manual scanning can still be performed by calling
      *    {@link #scan}.
      *
      * @param flag    True to enable or false to disable period
      *                based scanning.
      */
     void setScanEnabled(boolean flag);
  
     /**
      * Check if period based scanning is enabled.
      *
      * @return    True if enabled, false if disabled.
      */
     boolean isScanEnabled();
  
     /**
      * Scan for deployment changes.
      *
      * @throws IllegalStateException    Not initialized.
      * @throws Exception                Scan failed.
      */
     void scan() throws Exception;
  }
  
  
  
  1.1                  
jboss-system/src/main/org/jboss/deployment/scanner/DeploymentScannerMBean.java
  
  Index: DeploymentScannerMBean.java
  ===================================================================
  /***************************************
   *                                     *
   *  JBoss: The OpenSource J2EE WebOS   *
   *                                     *
   *  Distributable under LGPL license.  *
   *  See terms of license at gnu.org.   *
   *                                     *
   ***************************************/
  
  package org.jboss.deployment.scanner;
  
  import org.jboss.system.ServiceMBean;
  
  /**
   * The JMX management interface for {@link DeploymentScanner} components.
   *
   * @version <tt>$Revision: 1.1 $</tt>
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Jason Dillon</a>
   */
  public interface DeploymentScannerMBean
     extends DeploymentScanner, ServiceMBean
  {
     // for now just extend DS
  }
  
  
  
  1.1                  
jboss-system/src/main/org/jboss/deployment/scanner/DirectoryDeploymentScanner.java
  
  Index: DirectoryDeploymentScanner.java
  ===================================================================
  /***************************************
   *                                     *
   *  JBoss: The OpenSource J2EE WebOS   *
   *                                     *
   *  Distributable under LGPL license.  *
   *  See terms of license at gnu.org.   *
   *                                     *
   ***************************************/
  
  package org.jboss.deployment.scanner;
  
  import java.io.File;
  
  import java.util.Collection;
  import java.util.List;
  import java.util.ArrayList;
  import java.util.Iterator;
  import java.util.Set;
  import java.util.HashSet;
  import java.util.StringTokenizer;
  
  import java.net.URL;
  import java.net.MalformedURLException;
  
  import javax.management.ObjectName;
  import javax.management.MBeanServer;
  
  import org.jboss.system.ServiceMBeanSupport;
  import org.jboss.system.ConfigurationException;
  
  import org.jboss.deployment.MainDeployerMBean;
  import org.jboss.deployment.DeploymentInfo;
  import org.jboss.deployment.DeploymentException;
  import org.jboss.deployment.DeploymentSorter;
  
  import org.jboss.system.server.ServerConfigImplMBean;
  
  import org.jboss.logging.Logger;
  
  import org.jboss.util.NullArgumentException;
  import org.jboss.util.jmx.MBeanProxy;
  
  /**
   * A local directory based deployment file scanner.
   *
   * <p>This integrates with MainDeployer via {@link MainDeployerMBean#deploy(String)}
   *    and {@link MainDeployerMBean#undeploy(String)}.  DeploymentInfo
   *    objects are used to track last modified, cause it was easier to
   *    copy that from MD over.
   *
   * @version <tt>$Revision: 1.1 $</tt>
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Jason Dillon</a>
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Marc Fleury</a>
   */
  public class DirectoryDeploymentScanner
     extends ServiceMBeanSupport
     implements DeploymentScanner, DirectoryDeploymentScannerMBean
  {
     /** The scan period in milliseconds */
     protected long scanPeriod = 5000;
  
     /** True if period based scanning is enabled. */
     protected boolean scanEnabled = true;
  
     /** A proxy to the main deployer. */
     protected MainDeployerMBean deployer;
  
     /** The list of directories to scan. */
     protected List directoryList;
  
     /** A set of deployment info objects for deployed files. */
     protected Set deploymentSet = new HashSet();
  
     /** The scanner thread. */
     protected ScannerThread scannerThread;
  
     /** A helper for sorting deployments. */
     protected DeploymentSorter sorter = new DeploymentSorter();
  
     /** The server's home directory, for relative paths. */
     protected File serverHome;
  
     /**
      * Explicit no-args consturctor for JMX.
      */
     public DirectoryDeploymentScanner()
     {
        super();
     }
  
  
     /////////////////////////////////////////////////////////////////////////
     //                           DeploymentScanner                         //
     /////////////////////////////////////////////////////////////////////////
  
     /**
      * Period must be >= 0.
      */
     public void setScanPeriod(final long period)
     {
        if (period < 0)
           throw new IllegalArgumentException("ScanPeriod must be >= 0; have: " + 
period);
  
        this.scanPeriod = period;
     }
  
     public long getScanPeriod()
     {
        return scanPeriod;
     }
  
     public void setScanEnabled(final boolean flag)
     {
        this.scanEnabled = flag;
     }
  
     public boolean isScanEnabled()
     {
        return scanEnabled;
     }
  
     public void scan() throws Exception
     {
        if (directoryList == null)
           throw new IllegalStateException("not initialized");
  
        boolean trace = log.isTraceEnabled();
  
        if (trace) {
           log.trace("Scanning directories for new files");
        }
  
        // Scan directories for new deployments 
        for (Iterator added = scanNew().listIterator(); added.hasNext();)
        {
           File file = (File)added.next();
           DeploymentInfo di = new DeploymentInfo(file.toURL(), null);
           deploy(di);
        }
  
        if (trace) {
           log.trace("Scanning directories for removed files");
        }
  
        // Undeploy the removed ones
        for (Iterator removed = scanRemoved().listIterator(); removed.hasNext();)
        {
           DeploymentInfo di = (DeploymentInfo)removed.next();
           undeploy(di);
        }  
  
        if (trace) {
           log.trace("Scanning directories for modified files");
        }
  
        // Undeploy and redeploy the modified ones
        for (Iterator modified = scanModified().listIterator(); modified.hasNext();)
        {
           DeploymentInfo di = (DeploymentInfo)modified.next();
           undeploy(di);
           deploy(di);
        }
     }
  
     /** 
      * A simple helper to call deployer.deploy, also updates deploymentSet
      * and tracks lastDeployed time.
      */
     protected void deploy(final DeploymentInfo di)
     {
        try 
        {
           if (log.isTraceEnabled()) {
              log.trace("Deploying: " + di.url);
           }
           deployer.deploy(di.url.toString());
  
           di.lastDeployed = System.currentTimeMillis();
           
           if (!deploymentSet.contains(di)) {
              deploymentSet.add(di);
           }
        }
        catch (Exception e)
        {
           log.error("Failed to deploy: " + di.url, e);
        }
     }
  
     /** A simple helper to call deployer.undeploy */
     protected void undeploy(final DeploymentInfo di)
     {
        try 
        {
           if (log.isTraceEnabled()) {
              log.trace("Undeploying: " + di.url);
           }
           deployer.undeploy(di.url.toString());
        }
        catch (Exception e)
        {
           log.error("Failed to undeploy: " + di.url, e);
        }
     }
  
     /**
      * Scans the directories in the directory list and returns a
      * set of new files to deploy.
      */
     protected List scanNew()
     {
        try 
        {
           HashSet added = new HashSet();
           boolean trace = log.isTraceEnabled();
           
           // Scan directories
           for (Iterator iterator = directoryList.listIterator(); iterator.hasNext();) 
           {
              File dir = (File)iterator.next();
  
              if (!dir.exists()) {
                 log.warn("Skipping non-existant directory: " + dir);
                 continue;
              }
  
              if (trace)
              {
                 log.trace("Scanning directory: " + dir);
              }
  
              if (!dir.isDirectory()) 
              {
                 if (trace)
                 {
                    log.trace("Checking explicit deployment file: " + dir);
                 }
  
                 // It is a new file
                 if (!isDeployed(dir))
                 {
                    added.add(dir);
                 }
  
                 continue;
              }
              // else it is a directory
  
              File[] files = dir.listFiles();
              if (files == null)
              {
                 log.error("we have a problem null files in directory; should not 
happen");
                 continue;
              }
  
              for (int i = 0; i < files.length; i++)
              {
                 if (files[i].isDirectory())
                 {
                    log.warn("Ignoring nested directory: " + files[i]);
                    continue;
                 }
  
                 if (trace)
                 {
                    log.trace("Checking deployment file: " + files[i]);
                 }
  
                 // It is a new file
                 if (!isDeployed(files[i]))
                 {
                    added.add(files[i]);
                 }
              }   
           }
           
           return sorter.sortFiles(added);
        }
        catch (Exception e)
        {
           log.error("operation failed", e);
           return null;
        }
     }
     
     /**
      * Check if the given file is in the deployment set.
      */
     protected boolean isDeployed(final File file) 
        throws MalformedURLException, DeploymentException
     {
        DeploymentInfo di = new DeploymentInfo(file.toURL(), null);
        return deploymentSet.contains(di);
     }
  
     /**
      * Scans the existing deployments and return a 
      * set of deployment info objects which have been removed.
      */
     protected List scanRemoved()
     {
        HashSet removed = new HashSet();
           
        if (log.isTraceEnabled())
        {
           log.trace("Scanning installed deployments");
        }
  
        // People already deployed, scan for modifications  
        synchronized (deploymentSet)
        {
           for (Iterator it = deploymentSet.iterator(); it.hasNext();)
           {
              DeploymentInfo deployment = (DeploymentInfo)it.next();
              File file = new File(deployment.url.getFile());
              if (!file.exists())
              {
                 removed.add(deployment);
              }
           }
        }
        return sorter.sort(removed);
     }
     
     /**
      * Scans the existing deployments and returs a 
      * set of deployment info objects which have been modified.
      */
     protected List scanModified()
     {
        HashSet modified = new HashSet();
           
        if (log.isTraceEnabled())
        {
           log.trace("Scanning installed deployments");
        }
  
        // People already deployed, scan for modifications  
        synchronized (deploymentSet)
        {
           for (Iterator it = deploymentSet.iterator(); it.hasNext();)
           {
              DeploymentInfo deployment = (DeploymentInfo)it.next();
              
              long lastModified = 0;
              
              // if noone told us what to watch, we'll look for something...
              if (deployment.watch == null)
              {
                 deployment.watch = deployment.url;
              }
  
              // Get lastModified of file from file system
              File file = new File(deployment.watch.getFile());
              if (file.exists())
              {
                 lastModified = file.lastModified();
              }
                 
              // Check the record in the DeploymentInfo against the physical one 
              if (deployment.lastDeployed < lastModified) 
              {
                 modified.add(deployment);
              }
           }
        }
        return sorter.sort(modified);
     }
  
  
     /////////////////////////////////////////////////////////////////////////
     //                    DirectoryDeploymentScannerMBean                  //
     /////////////////////////////////////////////////////////////////////////
  
     public void setDirectories(final String listspec)
     {
        if (listspec == null)
           throw new NullArgumentException("listspec");
  
        boolean debug = log.isDebugEnabled();
  
        // start out with a fresh list
        directoryList = new ArrayList();
  
        StringTokenizer stok = new StringTokenizer(listspec, ",");
        while (stok.hasMoreTokens()) {
           String dirspec = stok.nextToken().trim();
  
           // use URL to deal with platform isses from this spec
           try {
              URL url = new URL("file:" + dirspec);
              dirspec = url.getFile();
           }
           catch (MalformedURLException ignore) {}
  
           if (debug) {
              log.debug("Adding directory from spec: " + dirspec);
           }
  
           File dir = new File(dirspec);
           addDirectory(dir);
        }
  
        if (debug) {
           log.debug("Directory list: " + directoryList);
        }
     }
  
     public void setDirectoryList(final List list)
     {
        if (list == null)
           throw new NullArgumentException("list");
      
        boolean debug = log.isDebugEnabled();
  
        // start out with a fresh list
        directoryList = new ArrayList();
    
        Iterator iter = list.iterator();
        while (iter.hasNext()) {
           File dir = (File)iter;
           if (dir == null)
              throw new NullArgumentException("list element");
  
           addDirectory(dir);
        }
  
        if (debug) {
           log.debug("Directory list: " + directoryList);
        }
     }
  
     public List getDirectoryList()
     {
        return new ArrayList(directoryList);
     }
  
     public void addDirectory(File dir)
     {
        if (dir == null)
           throw new NullArgumentException("dir");
  
        if (!dir.isAbsolute()) {
           dir = new File(serverHome, dir.getPath());
        }
  
        try {
           directoryList.add(dir.getCanonicalFile());
  
           if (log.isDebugEnabled()) {
              log.debug("Added directory: " + dir);
           }
        }
        catch (java.io.IOException e) {
           log.error("failed to add directory: " + dir, e);
        }
     }
  
     public void removeDirectory(final File dir)
     {
        if (dir == null)
           throw new NullArgumentException("dir");
  
        boolean success = directoryList.remove(dir);
  
        if (success && log.isDebugEnabled()) {
           log.debug("Removed directory: " + dir);
        }
     }
  
  
     /////////////////////////////////////////////////////////////////////////
     //                           Scanner Thread                            //
     /////////////////////////////////////////////////////////////////////////
  
     /**
      * Should use Timer/TimerTask instead?  This has some issues with
      * interaction with ScanEnabled attribute.  ScanEnabled works only
      * when starting/stopping.
      */
     protected class ScannerThread
        extends Thread
     {
        /** We get our own logger. */
        protected Logger log = Logger.getLogger(ScannerThread.class);
  
        /** True if the scan loop should run. */
        protected boolean enabled;
  
        /** True if we are shutting down. */
        protected boolean shuttingDown;
  
        /** Lock/notify object. */
        protected Object lock = new Object();
  
        public ScannerThread(boolean enabled)
        {
           super("ScannerThread");
  
           this.enabled = enabled;
        }
  
        public void setEnabled(boolean enabled)
        {
           this.enabled = enabled;
  
           synchronized (lock) {
              lock.notifyAll();
           }
  
           if (log.isDebugEnabled()) {
              log.debug("Notified that enabled: " + enabled);
           }
        }
  
        public void shutdown()
        {
           enabled = false;
           shuttingDown = true;
  
           synchronized (lock) {
              lock.notifyAll();
           }
  
           if (log.isDebugEnabled()) {
              log.debug("Notified to shutdown");
           }
        }
      
        public void run()
        {
           log.info("Running");
  
           while (!shuttingDown) {
  
              // If we are not enabled, then wait
              if (!enabled) {
                 try {
                    log.debug("Disabled, waiting for notification");
                    synchronized (lock) {
                       lock.wait();
                    }
                 }
                 catch (InterruptedException ignore) {}
              }
  
              loop();
           }
  
           log.info("Shutdown");
        }
  
        protected void loop()
        {
           while (enabled) {
              // Scan for new/removed/changed/whatever
              try {
                 scan();
              }
              catch (Exception e) {
                 log.error("Scanning failed; continuing", e);
              }
  
              // Sleep for scan period
              try {
                 log.trace("Sleeping...");
                 Thread.sleep(scanPeriod);
              }
              catch (InterruptedException ignore) {}
           }
        }
     }
  
  
     /////////////////////////////////////////////////////////////////////////
     //                     Service/ServiceMBeanSupport                     //
     /////////////////////////////////////////////////////////////////////////
  
     public ObjectName preRegister(MBeanServer server, ObjectName name)
        throws Exception
     {
        // get server's home for relative paths, need this for setting
        // attribute final values, so we need todo it here
        serverHome = (File)
           server.getAttribute(ServerConfigImplMBean.OBJECT_NAME, "ServerHomeDir");
  
        return super.preRegister(server, name);
     }
  
     protected void createService() throws Exception
     {
        // setup deployer
        deployer = (MainDeployerMBean)
           MBeanProxy.create(MainDeployerMBean.class, 
                             MainDeployerMBean.OBJECT_NAME,
                             server);
  
        // setup + start scanner thread
        scannerThread = new ScannerThread(false);
        scannerThread.start();
        log.debug("Scanner thread started");
     }
     
     protected void startService() throws Exception 
     {
        // scan before we enable the thread, so JBoss version shows up afterwards
        scan();
  
        // enable scanner thread if we are enabled
        scannerThread.setEnabled(scanEnabled);
     }
     
     protected void stopService() throws Exception 
     {
        // disable scanner thread
        scannerThread.setEnabled(false);
     }
     
     protected void destroyService() throws Exception 
     {
        // drop our ref to deployer, so scan will fail
        deployer = null;
  
        // shutdown scanner thread
        scannerThread.shutdown();
  
        // help gc
        scannerThread = null;
     }
  }
  
  
  
  1.1                  
jboss-system/src/main/org/jboss/deployment/scanner/DirectoryDeploymentScannerMBean.java
  
  Index: DirectoryDeploymentScannerMBean.java
  ===================================================================
  /***************************************
   *                                     *
   *  JBoss: The OpenSource J2EE WebOS   *
   *                                     *
   *  Distributable under LGPL license.  *
   *  See terms of license at gnu.org.   *
   *                                     *
   ***************************************/
  
  package org.jboss.deployment.scanner;
  
  import java.io.File;
  
  import java.util.List;
  
  /**
   * The JMX management interface for the {@link DirectoryDeploymentScanner} 
   * component.
   *
   * @version <tt>$Revision: 1.1 $</tt>
   * @author  <a href="mailto:[EMAIL PROTECTED]";>Jason Dillon</a>
   */
  public interface DirectoryDeploymentScannerMBean
     extends DeploymentScannerMBean
  {
     /**
      * Set the list of directories to scan.
      *
      * @param list    The list of directories to scan.
      */
     void setDirectoryList(List list);
  
     /**
      * Get the list of directories being scanned.
      *
      * @return   The list of directories being scanned.
      */
     List getDirectoryList();
  
     /**
      * Add a directory to the scan list.
      *
      * @param dir    The directory to add to the scan list.
      *
      * @throws IllegalArgumentException    Directory argument is null.
      */
     void addDirectory(File dir);
  
     /**
      * Remove a directory from the scan list.
      *
      * @param dir    The directory to remove from the scan list.
      *
      * @throws IllegalArgumentException    Directory argument is null.
      */
     void removeDirectory(File dir);
  
  
     /////////////////////////////////////////////////////////////////////////
     //                  Managment/Configuration Helpers                    //
     /////////////////////////////////////////////////////////////////////////
  
     /**
      * Set the list of directories to scan.
      *
      * <p>This kinda sucks... should take a List, but since JMX can't 
      *    handle overloaded method names, lets just use the string
      *    version for now... =(
      *
      * @param listspec   A comma seperated list of directory names to 
      *                   scan.
      */
     void setDirectories(String listspec);
  }
  
  
  
  1.1                  jboss-system/src/main/org/jboss/deployment/scanner/package.html
  
  Index: package.html
  ===================================================================
  <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  <html>
    <head>
      <!-- $Id: package.html,v 1.1 2002/03/01 08:29:57 user57 Exp $ -->
      <!--
  
      JBoss: The OpenSource J2EE WebOS 
  
      Distributable under LGPL license.
      See terms of license at gnu.org.
  
      -->
    </head>
  
    <body bgcolor="white">
      <p>Deployment scanning framework and components.
  
      <h2>Package Specification</h2>
      <ul>
        <li><a href="javascript: alert('not available')">Not Available</a>
      </ul>
        
      <h2>Related Documentation</h2>
      <ul>
        <li><a href="javascript: alert('not available')">Not Available</a>
      </ul>
  
      <h2>Package Status</h2>
      <ul>
        <li><font color="green"><b>STABLE</b></font>
      </ul>
  
      <h2>Todo</h2>
      <ul>
        <li>???
      </ul>
  
      <!-- Put @see and @since tags down here. -->
  
    </body>
  </html>
  
  
  

_______________________________________________
Jboss-development mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/jboss-development

Reply via email to