/* * JBoss, the OpenSource EJB server * * Distributable under LGPL license. * See terms of license at gnu.org. */ package org.jboss.deployment; import java.io.File; import java.io.FilenameFilter; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.StringTokenizer; import javax.management.MBeanException; import javax.management.MBeanServer; import javax.management.MalformedObjectNameException; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.RuntimeErrorException; import javax.management.RuntimeMBeanException; import org.jboss.util.ServiceMBeanSupport; /** * The AutoDeployer is used to automatically deploy applications or * components thereof. * *

It can be used on either .jar or .xml files. The AutoDeployer * can be configured to "watch" one or more files. If they are * updated they will be redeployed. * *

If it is set to watch a directory instead of a single file, * all files within that directory will be watched separately. * *

When a file is to be deployed, the AutoDeployer will use the * configured deployer to deploy it. * * @see org.jboss.deployment.J2eeDeployer * @author Rickard Öberg (rickard.oberg@telkel.com) * @author Toby Allsopp (toby.allsopp@peace.com) * @author Scott.Stark@jboss.org * @version $Revision: 1.7.2.2 $ */ public class AutoDeployer extends ServiceMBeanSupport implements AutoDeployerMBean, Runnable { // Constants ----------------------------------------------------- // Attributes ---------------------------------------------------- // Callback to the JMX agent MBeanServer server; // in case more then one J2eeDeployers are available String deployerList = ""; /** JMX names of the configured deployers */ ObjectName[] deployerNames; /** DeploymentInfo check interval */ int timeout = 3000; // The watch thread boolean running = false; // Watch these directories for new files ArrayList watchedDirectories = new ArrayList(); // These URL's are being watched HashMap watchedURLs = new HashMap(); // URL list String urlList = ""; /** Filters, one per configured deployer, to decide which files are deployable and which should be ignored */ FilenameFilter[] deployableFilters = null; // Static -------------------------------------------------------- // Constructors -------------------------------------------------- public AutoDeployer() { this(""); } public AutoDeployer(String urlList) { this ("J2EE:service=J2eeDeployer", urlList); } public AutoDeployer(String _namedDeployer, String urlList) { setDeployers(_namedDeployer); setURLs(urlList); } public void setURLs(String urlList) { this.urlList = urlList; } public String getURLs() { return urlList; } /** * Gets the Timeout attribute of the AutoDeployer object * * @return The Timeout value */ public int getTimeout() { return timeout; } /** * Sets the Timeout attribute of the AutoDeployer object * * @param to The new Timeout value */ public void setTimeout(int to) { this.timeout = to; } public void setDeployers(String deployers) { this.deployerList = deployers; } public String getDeployers() { return deployerList; } // Public -------------------------------------------------------- public void run() { do { // Sleep if (running) { try { Thread.sleep(timeout); } catch (InterruptedException e) {} } try { // Check directories - add new entries to list of files for (int i = 0; i < watchedDirectories.size(); i++) { File dir = (File)watchedDirectories.get(i); File[] files = dir.listFiles(); for (int idx = 0; idx < files.length; idx++) { URL fileURL = files[idx].toURL(); // Check if it's a deployable file for (int j=0; j= 0 ) { // This is an unpackaged J2EE module URL modURL = modFile.toURL(); DeploymentInfo info = new DeploymentInfo(modURL); watchedURLs.put(modURL, info); log.info("Watching module directory: "+modFile); } else { // This is a directory whose contents shall be checked // for deployments watchedDirectories.add(modFile); log.info("Watching directory: "+modFile); } } catch (Exception e) { log.info("Cannot auto-deploy module: "+urlFile, e); } } else if (urlFile.exists()) // It's a file { try { File modFile = urlFile.getCanonicalFile(); URL modURL = modFile.toURL(); DeploymentInfo info = new DeploymentInfo(modURL); watchedURLs.put(modURL, info); log.info("Auto-deploying module archive: "+modFile); } catch (Exception e) { log.info("Cannot auto-deploy module: "+urlFile, e); } } else // It's a real URL (probably http:) { try { URL infoURL = new URL(url); watchedURLs.put(infoURL, new DeploymentInfo(infoURL)); } catch (MalformedURLException e) { // Didn't work log.warn("Cannot auto-deploy "+url); } } } // Pre-deploy. This is done so that deployments available // on start of container is deployed ASAP run(); // Start auto deploy thread running = true; new Thread(this, "AutoDeployer").start(); } protected void stopService() { // Stop auto deploy thread running = false; // Clear lists watchedDirectories.clear(); watchedURLs.clear(); } // Protected ----------------------------------------------------- protected void deploy(String url, ObjectName deployerName) throws Exception { try { // Call the appropriate deployer through the JMX server server.invoke(deployerName, "deploy", new Object[] { url }, new String[] { "java.lang.String" }); } catch (RuntimeMBeanException e) { throw e.getTargetException(); } catch (MBeanException e) { throw e.getTargetException(); } catch (RuntimeErrorException e) { throw e.getTargetError(); } } protected void undeploy(String url, ObjectName deployerName) throws Exception { try { // Call the appropriate deployer through the JMX server server.invoke(deployerName, "undeploy", new Object[] { url }, new String[] { "java.lang.String" }); } catch (MBeanException e) { throw e.getTargetException(); } catch (RuntimeErrorException e) { throw e.getTargetError(); } } // Inner classes ------------------------------------------------- // This class holds info about a deployement, such as the URL and the last timestamp class DeploymentInfo { long lastModified; URL url; URL watch; ObjectName deployerName; DeploymentInfo(URL url) throws MalformedURLException { this.url = url; for (int i=0; i