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