geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ga...@apache.org
Subject svn commit: r1131238 - in /geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot: DirectoryHotDeployer.java DirectoryMonitor.java HotDeployer.java ModuleHandler.java
Date Fri, 03 Jun 2011 20:58:42 GMT
Author: gawor
Date: Fri Jun  3 20:58:41 2011
New Revision: 1131238

URL: http://svn.apache.org/viewvc?rev=1131238&view=rev
Log:
GERONIMO-5994: Hot deployer fixes & refactoring

Added:
    geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java   (with props)
Modified:
    geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
    geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
    geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/HotDeployer.java

Modified: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java?rev=1131238&r1=1131237&r2=1131238&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java (original)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java Fri Jun  3 20:58:41 2011
@@ -18,6 +18,7 @@ package org.apache.geronimo.deployment.h
 
 import java.io.File;
 import java.io.IOException;
+import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
 
@@ -46,6 +47,7 @@ import org.apache.geronimo.kernel.reposi
 import org.apache.geronimo.kernel.repository.MissingDependencyException;
 import org.apache.geronimo.kernel.util.FileUtils;
 import org.apache.geronimo.kernel.util.JarUtils;
+import org.apache.geronimo.system.main.ServerStatus;
 import org.apache.geronimo.system.serverinfo.ServerInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -55,27 +57,16 @@ import org.slf4j.LoggerFactory;
  *
  * @version $Rev$ $Date$
  */
-public class DirectoryHotDeployer implements HotDeployer, DeploymentWatcher, GBeanLifecycle { //todo: write unit tests
+public class DirectoryHotDeployer implements HotDeployer, DeploymentWatcher, ServerStatus, GBeanLifecycle { 
     private static final Logger log = LoggerFactory.getLogger(DirectoryHotDeployer.class);
 
-    // Try to make this stand out as the user is likely to get a ton of errors if this comes up
-    private static final String BAD_LAYOUT_MESSAGE = "CANNOT DEPLOY: It looks like you unpacked an application or module " +
-            "directly into the hot deployment directory.  THIS DOES NOT WORK.  You need to unpack into a " +
-            "subdirectory directly under the hot deploy directory.  For example, if the hot deploy directory " +
-            "is 'deploy/' and your file is 'webapp.war' then you could unpack it into a directory 'deploy/webapp.war/'";
     private DirectoryMonitor monitor;
     private String path;
     private String monitorFileName;
     private ServerInfo serverInfo;
-    private ConfigurationManager configManager;
     private int pollIntervalMillis;
-    private String deploymentURI = "deployer:geronimo:inVM";
-    private String deploymentUser;
-    private String deploymentPassword;
-    private transient Kernel kernel;
-    private transient DeploymentFactory factory;
-    private transient TargetModuleID[] startupModules = null;
     private transient boolean serverRunning = false;
+    private ModuleHandler moduleHandler;
 
     public DirectoryHotDeployer(String path, String monitorFileName, int pollIntervalMillis, 
                                 ServerInfo serverInfo, ConfigurationManager configManager, Kernel kernel) {
@@ -83,17 +74,26 @@ public class DirectoryHotDeployer implem
         this.monitorFileName = monitorFileName;
         this.serverInfo = serverInfo;
         this.pollIntervalMillis = pollIntervalMillis;
-        this.kernel = kernel;
-        this.configManager = configManager;
+        this.moduleHandler = new ModuleHandler(kernel, configManager);
     }
 
     public void deployed(Artifact id) {
         // no action when something is deployed
     }
 
+    // BTW, now we support EBA deployment. And if an EBA includes a WAB, which also has a configuration id during EBA deployment, 
+    // this method also can be called with the WAB id. And the WAB' so id will also go into the "toRemove" list.
     public void undeployed(Artifact id) {
-        // check to see whether the artifact was hot deployed, and if so, delete it
-        monitor.removeModuleId(id);
+        if (monitor != null) {
+            String moduleId = id.toString();
+            if (moduleId.equals(moduleHandler.getWorkingOnConfigId())) {
+                // don't react to undelpoy events we generated ourselves
+                // because the file update action(i.e. redeploy) will cause the old module to undeploy first
+                // we must handle this so that its config id won't go "toRemove" list to avoid the deletion of the new file.
+                return; 
+            }
+            monitor.removeFile(id.toString());
+        }
     }
 
     public String getPath() {
@@ -121,36 +121,30 @@ public class DirectoryHotDeployer implem
     }
 
     public String getDeploymentURI() {
-        return deploymentURI;
+        return moduleHandler.getDeploymentURI();
     }
 
     public void setDeploymentURI(String deploymentURI) {
-        if (deploymentURI != null && !deploymentURI.trim().equals("")) {
-            this.deploymentURI = deploymentURI.trim();
-        }
+        moduleHandler.setDeploymentURI(deploymentURI);
     }
 
     public String getDeploymentUser() {
-        return deploymentUser;
+        return moduleHandler.getDeploymentUser();
     }
 
     public void setDeploymentUser(String deploymentUser) {
-        this.deploymentUser = deploymentUser;
+       moduleHandler.setDeploymentUser(deploymentUser);
     }
 
     public String getDeploymentPassword() {
-        return deploymentPassword;
+        return moduleHandler.getDeploymentPassword();
     }
 
     public void setDeploymentPassword(String deploymentPassword) {
-        this.deploymentPassword = deploymentPassword;
+        moduleHandler.setDeploymentPassword(deploymentPassword);
     }
 
     public void doStart() throws Exception {
-        if (factory == null) {
-            factory = new DeploymentFactoryWithKernel(kernel);
-        }
-        
         File dir = serverInfo.resolveServer(path);
         if (!dir.exists()) {
             if (!dir.mkdirs()) {
@@ -169,22 +163,9 @@ public class DirectoryHotDeployer implem
                 }
             }
         }
-        
-        DeploymentManager mgr = null;
-        try {
-            mgr = getDeploymentManager();
-            Target[] targets = mgr.getTargets();
-            startupModules = mgr.getAvailableModules(null, targets);
-            mgr.release();
-            mgr = null;
-            monitor = new DirectoryMonitor(dir, monitorFile, this, pollIntervalMillis);
-            log.debug("Hot deploy scanner intialized; starting main loop.");
-            Thread t = new Thread(monitor, "Geronimo hot deploy scanner");
-            t.setDaemon(true);
-            t.start();
-        } finally {
-            if (mgr != null) mgr.release();
-        }
+                
+        monitor = new DirectoryMonitor(dir, monitorFile, moduleHandler, pollIntervalMillis);
+        log.debug("Hot deploy scanner intialized");
     }
 
     public void doStop() throws Exception {
@@ -197,284 +178,24 @@ public class DirectoryHotDeployer implem
         }
     }
 
-    public boolean isFileDeployed(File file, String configId) {
-        DeploymentManager mgr = null;
-        try {
-            if (startupModules != null) {
-                DeployUtils.identifyTargetModuleIDs(startupModules, configId, true).toArray(new TargetModuleID[0]);
-            }
-            else {
-                mgr = getDeploymentManager();
-                Target[] targets = mgr.getTargets();
-                TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
-                DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
-                mgr.release();
-                mgr = null;
-            }
-            return true;
-        } catch (DeploymentException e) {
-            log.debug("Found new file in deploy directory on startup with ID " + configId);
-        } catch (Exception e) {
-            log.error("Unable to check status", e);
-        } finally {
-            if (mgr != null) {
-                mgr.release();
-                mgr = null;
-            }
-        }
-        return false;
+    public boolean isServerStarted() {
+        return serverRunning;
     }
-
-    public boolean isServerRunning() {
-        if (serverRunning) {
-            return true;
-        }
-
-        // a bit of a hack, but the PersistentConfigurationList is the only thing that knows whether the server is full started!
-        Set<AbstractName> configLists = kernel.listGBeans(new AbstractNameQuery(PersistentConfigurationList.class.getName()));
-        for (Iterator<AbstractName> i = configLists.iterator(); i.hasNext();) {
-            AbstractName configListName = i.next();
-            try {
-                Boolean result = (Boolean) kernel.getAttribute(configListName, "kernelFullyStarted");
-                if (!result.booleanValue()) {
-                    return false;
-                }
-            } catch (Exception e) {
-                log.warn("Hot deployer unable to determine whether kernel is started", e);
-            }
-        }
-        serverRunning = true;
-        return true;
-    }
-
-    public long getDeploymentTime(File file, String configId) {
-        try {
-            Artifact art = configManager.getArtifactResolver().resolveInClassLoader(Artifact.create(configId));
-            Configuration config = configManager.getConfiguration(art);
-            return config.getCreated();
-        } catch (MissingDependencyException e) {
-            log.error("Unknown configuration "+configId);
-            return -1;
+    
+    public void setServerStarted(boolean started) {
+        serverRunning = started;
+        if (started) {
+            Thread t = new Thread(monitor, "Geronimo hot deploy scanner");
+            t.setDaemon(true);
+            t.start();
+            log.debug("Hot deploy scanner started");
         }
     }
-
+    
     public void started() {
-        startupModules = null;
         log.debug("Initialization complete; directory scanner entering normal scan mode");
     }
 
-    public boolean validateFile(File file, String configId) {
-        //todo: some more detailed evaluation
-        if (file.isDirectory() && (file.getName().equals("WEB-INF") || file.getName().equals("META-INF"))) {
-            log.error("(" + file.getName() + ") " + BAD_LAYOUT_MESSAGE);
-            return false;
-        }
-        return true;
-    }
-
-    public String fileAdded(File file) {
-        log.info("Deploying " + file.getName());
-        DeploymentManager mgr = null;
-        TargetModuleID[] modules = null;
-        boolean completed = false;
-        try {
-            mgr = getDeploymentManager();
-            Target[] targets = mgr.getTargets();
-            if (null == targets) {
-                throw new IllegalStateException("No target to distribute to");
-            }
-            targets = new Target[] {targets[0]};
-
-            ProgressObject po;
-
-            if (JarUtils.isJarFile(file) || file.isDirectory()) {
-                po = mgr.distribute(targets, file, null);
-            } else {
-                po = mgr.distribute(targets, null, file);
-            }
-            waitForProgress(po);
-            if (po.getDeploymentStatus().isCompleted()) {
-                modules = po.getResultTargetModuleIDs();
-                po = mgr.start(modules);
-                waitForProgress(po);
-                if (po.getDeploymentStatus().isCompleted()) {
-                    completed = true;
-                } else {
-                    log.warn("Unable to start some modules for " + file.getAbsolutePath());
-                }
-                modules = po.getResultTargetModuleIDs();
-                for (int i = 0; i < modules.length; i++) {
-                    TargetModuleID result = modules[i];
-                    log.info(DeployUtils.reformat("Deployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : "") + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
-                    if (result.getChildTargetModuleID() != null) {
-                        for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
-                            TargetModuleID child = result.getChildTargetModuleID()[j];
-                            log.info(DeployUtils.reformat("  `-> " + child.getModuleID() + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
-                        }
-                    }
-                }
-            } else {
-            	 //Try to delete the module , that failed to successfully hot-deploy
-            	log.error("Unable to deploy: " + po.getDeploymentStatus().getMessage());
-            	String delfile=file.getAbsolutePath();
-                File fd = new File(delfile);
-                if(fd.isDirectory()){
-               	    log.info("Deleting the Directory: "+delfile);
-               	    if(FileUtils.recursiveDelete(fd))
-               		    log.debug("Successfully deleted the Directory: "+delfile);
-               	    else
-               		    log.error("Couldn't delete the hot deployed directory"+delfile);
-                }else if(fd.isFile()){
-               	    log.info("Deleting the File: "+delfile);
-               	    if(fd.delete()){
-               		log.debug("Successfully deleted the File: "+delfile);
-               	}else
-               		log.error("Couldn't delete the hot deployed directory"+delfile);
-                }
-
-                return null;
-            }
-        } catch (DeploymentManagerCreationException e) {
-            log.error("Unable to open deployer", e);
-        } catch (IOException e) {
-            log.error("Unable to determine if file is a jar", e);
-        } finally {
-            if (mgr != null) mgr.release();
-        }
-        if (completed && modules != null) {
-            if (modules.length == 1) {
-                return modules[0].getModuleID();
-            } else {
-                return "";
-            }
-        } else if (modules != null) { //distribute completed but not start or something like that
-            return "";
-        } else {
-            return null;
-        }
-    }
-
-    private DeploymentManager getDeploymentManager() throws DeploymentManagerCreationException {
-        DeploymentManager manager = factory.getDeploymentManager(deploymentURI, deploymentUser, deploymentPassword);
-        if (manager instanceof JMXDeploymentManager) {
-            ((JMXDeploymentManager) manager).setLogConfiguration(false, true);
-        }
-        return manager;
-    }
-
-    public boolean fileRemoved(File file, String configId) {
-        log.info("Undeploying " + file.getName());
-        DeploymentManager mgr = null;
-        try {
-            mgr = getDeploymentManager();
-            Target[] targets = mgr.getTargets();
-            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
-            ids = DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
-            ProgressObject po = mgr.undeploy(ids);
-            waitForProgress(po);
-            if (po.getDeploymentStatus().isCompleted()) {
-                TargetModuleID[] modules = po.getResultTargetModuleIDs();
-                for (int i = 0; i < modules.length; i++) {
-                    TargetModuleID result = modules[i];
-                    log.info(DeployUtils.reformat("Undeployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : ""), 4, 72));
-                }
-            } else {
-                log.error("Unable to undeploy " + file.getAbsolutePath() + "(" + configId + ")" + po.getDeploymentStatus().getMessage());
-                return false;
-            }
-        } catch (DeploymentManagerCreationException e) {
-            log.error("Unable to open deployer", e);
-            return false;
-        } catch (Exception e) {
-            log.error("Unable to undeploy", e);
-            return false;
-        } finally {
-            if (mgr != null) mgr.release();
-        }
-        return true;
-    }
-
-    public String getModuleId(String config) {
-        DeploymentManager mgr = null;
-        //TargetModuleID[] modules = null;
-        try {
-            mgr = getDeploymentManager();
-            Target[] targets = mgr.getTargets();
-            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
-            for(int j=0;j<ids.length;j++) {
-                String moduleId=ids[j].getModuleID();
-                String[] parts = moduleId.split("/", -1);
-                if (parts.length != 4) {
-                    continue;
-                }
-                if(parts[1] != null && parts[1].equals(config))
-                    return ids[j].getModuleID();
-            }
-        } catch(Exception ex){
-            log.error("Unable to getModuleId",ex);
-        }
-        return config;
-    }
-
-    public String fileUpdated(File file, String configId) {
-        log.info("Redeploying " + file.getName());
-        DeploymentManager mgr = null;
-        TargetModuleID[] modules = null;
-        try {
-            mgr = getDeploymentManager();
-            Target[] targets = mgr.getTargets();
-            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
-            ids = DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
-            ProgressObject po;
-            if (JarUtils.isJarFile(file) || file.isDirectory()) {
-                po = mgr.redeploy(ids, file, null);
-            } else {
-                po = mgr.redeploy(ids, null, file);
-            }
-            waitForProgress(po);
-            if (po.getDeploymentStatus().isCompleted()) {
-                modules = po.getResultTargetModuleIDs();
-                for (int i = 0; i < modules.length; i++) {
-                    TargetModuleID result = modules[i];
-                    log.info(DeployUtils.reformat("Redeployed " + result.getModuleID() + (targets.length > 1 ? " to " + result.getTarget().getName() : "") + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
-                    if (result.getChildTargetModuleID() != null) {
-                        for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
-                            TargetModuleID child = result.getChildTargetModuleID()[j];
-                            log.info(DeployUtils.reformat("  `-> " + child.getModuleID() + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
-                        }
-                    }
-                }
-            } else {
-                log.error("Unable to undeploy " + file.getAbsolutePath() + "(" + configId + ")" + po.getDeploymentStatus().getMessage());
-            }
-        } catch (DeploymentManagerCreationException e) {
-            log.error("Unable to open deployer", e);
-        } catch (Exception e) {
-            log.error("Unable to undeploy", e);
-        } finally {
-            if (mgr != null) mgr.release();
-        }
-        if (modules != null) {
-            if (modules.length == 1) {
-                return modules[0].getModuleID();
-            } else {
-                return "";
-            }
-        } else {
-            return null;
-        }
-    }
-
-    private void waitForProgress(ProgressObject po) {
-        while (po.getDeploymentStatus().isRunning()) {
-            try {
-                Thread.sleep(100);
-            } catch (InterruptedException e) {
-                log.error(e.getMessage(), e);
-            }
-        }
-    }
-
     public static final GBeanInfo GBEAN_INFO;
 
     static {
@@ -502,4 +223,5 @@ public class DirectoryHotDeployer implem
     public static GBeanInfo getGBeanInfo() {
         return GBEAN_INFO;
     }
+ 
 }

Modified: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java?rev=1131238&r1=1131237&r2=1131238&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java (original)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java Fri Jun  3 20:58:41 2011
@@ -24,16 +24,13 @@ import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
-import org.apache.geronimo.deployment.cli.DeployUtils;
-import org.apache.geronimo.kernel.repository.Artifact;
 import org.apache.geronimo.kernel.util.FileUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -49,94 +46,26 @@ import org.slf4j.LoggerFactory;
  * @version $Rev$ $Date$
  */
 public class DirectoryMonitor implements Runnable {
+    
     private static final Logger log = LoggerFactory.getLogger(DirectoryMonitor.class);
 
-    public static interface Listener {
-        /**
-         * The directory monitor doesn't take any action unless this method
-         * returns true (to avoid deploying before the deploy GBeans are
-         * running, etc.).
-         */
-        boolean isServerRunning();
-
-        /**
-         * Checks if the file with same configID is already deployed
-         *
-         * @return true if the file in question is already available in the
-         *         server, false if it should be deployed on the next pass.
-         */
-        boolean isFileDeployed(File file, String configId);
-
-        /**
-         * Called during initialization on previously deployed files.
-         *
-         * @return The time that the file was deployed.  If the current
-         *         version in the directory is newer, the file will be
-         *         updated on the first pass.
-         */
-        long getDeploymentTime(File file, String configId);
-
-        /**
-         * Called to indicate that the monitor has fully initialized
-         * and will be doing normal deployment operations from now on.
-         */
-        void started();
-
-        /**
-         * Called to check whether a file passes the smell test before
-         * attempting to deploy it.
-         *
-         * @return true if there's nothing obviously wrong with this file.
-         *         false if there is (for example, it's clearly not
-         *         deployable).
-         */
-        boolean validateFile(File file, String configId);
-
-        /**
-         * @return A configId for the deployment if the addition was processed
-         *         successfully (or an empty String if the addition was OK but
-         *         the configId could not be determined).  null if the addition
-         *         failed, in which case the file will be added again next time
-         *         it changes.
-         */
-        String fileAdded(File file);
-
-        /**
-         * @return true if the removal was processed successfully.  If not
-         *         the file will be removed again on the next pass.
-         */
-        boolean fileRemoved(File file, String configId);
-
-        String fileUpdated(File file, String configId);
-
-        /**
-         * This method returns the module id of an application deployed in the default group.
-         * @return String respresenting the ModuleId if the application is already deployed
-         */
-        String getModuleId(String config);
-
-    }
-
     private int pollIntervalMillis;
     private File directory;
     private boolean done = false;
-    private Listener listener; // a little cheesy, but do we really need multiple listeners?
-    private final Map<String, FileInfo> files;
-    private volatile String workingOnConfigId;
-    private final ArrayList <Artifact> toRemove = new ArrayList <Artifact>();
+    private MonitorListener listener; // a little cheesy, but do we really need multiple listeners?
+    private Map<String, FileInfo> files;
+    private final ArrayList <String> toRemove = new ArrayList <String>();
     private File monitorFile;
 
-    public DirectoryMonitor(File directory, Listener listener, int pollIntervalMillis) {
+    public DirectoryMonitor(File directory, MonitorListener listener, int pollIntervalMillis) {
         this(directory, null, listener, pollIntervalMillis);
     }
 
-    public DirectoryMonitor(File directory, File monitorFile, Listener listener, int pollIntervalMillis) {
+    public DirectoryMonitor(File directory, File monitorFile, MonitorListener listener, int pollIntervalMillis) {
         this.directory = directory;
         this.listener = listener;
         this.pollIntervalMillis = pollIntervalMillis;
         this.monitorFile = monitorFile;
-        this.files = readState();
-        persistState();
     }
 
     public int getPollIntervalMillis() {
@@ -147,11 +76,11 @@ public class DirectoryMonitor implements
         this.pollIntervalMillis = pollIntervalMillis;
     }
 
-    public Listener getListener() {
+    public MonitorListener getMonitorListener() {
         return listener;
     }
 
-    public void setListener(Listener listener) {
+    public void setMonitorListener(MonitorListener listener) {
         this.listener = listener;
     }
 
@@ -179,40 +108,33 @@ public class DirectoryMonitor implements
         this.done = true;
     }
 
-    // The undeployed operation could occur in this hot-deploy thread or in console/cli.
-    // The id that go to "toRemove" should be the ones that not undeployed in this hot-deploy thread 
-    // BTW, now we support EBA deployment. And if an EBA includes a WAB, which also has a configuration id during EBA deployment, 
-    // this method also can be called with the WAB id. And the WAB' so id will also go into the "toRemove" list.
-    public void removeModuleId(Artifact id) {
-        log.info("Hot deployer notified that an artifact was undeployed: "+id);
-        if(id.toString().equals(workingOnConfigId)) {
-            // don't react to undelpoy events we generated ourselves
-            // because the file update action(i.e. redeploy) will cause the old module to undeploy first
-            // we must handle this so that its config id won't go "toRemove" list to avoid the deletion of the new file.
-            return; 
-        }
+    /* 
+     * The undeployed operation could occur in this hot-deploy thread or in console/cli.
+     * The id that go to "toRemove" should be the ones that not undeployed in this hot-deploy thread. 
+     */
+    public void removeFile(String configId) {
+        log.info("Hot deployer notified that an artifact was undeployed: " + configId);
         synchronized (toRemove) {
-            toRemove.add(id);
+            toRemove.add(configId);
         }
     }
 
     private void doRemoves() {
         synchronized (toRemove) {
             synchronized (files) {
-                for (Iterator<Artifact> idItr = toRemove.iterator(); idItr.hasNext();) {
-                    Artifact id = idItr.next();
+                for (Iterator<String> idItr = toRemove.iterator(); idItr.hasNext();) {
+                    String configId = idItr.next();
                     for (Iterator<String> filesItr = files.keySet().iterator(); filesItr.hasNext();) {
                         String path = filesItr.next();
                         FileInfo info = files.get(path);
-                        if (info.getConfigId() == null){
+                        if (info.getConfigId() == null) {
                             // the file is new added, have not deployed yet, so its config id is not set.
                             continue;
                         }
-                        Artifact target = Artifact.create(info.getConfigId());
-                        if (id.matches(target)) { // need to remove record & delete file
+                        if (configId.equals(info.getConfigId())) { // need to remove record & delete file
                             File file = new File(path);
                             if (file.exists()) {  // if not, probably it's deletion kicked off this whole process
-                                log.info("Hot deployer deleting " + id);
+                                log.info("Hot deployer deleting " + path);
                                 if (!FileUtils.recursiveDelete(file)) {
                                     log.error("Hot deployer unable to delete " + path);
                                 }
@@ -225,7 +147,7 @@ public class DirectoryMonitor implements
                 }
             }
         }
-    }
+    }    
 
     private void persistState() {
         if (monitorFile == null) {
@@ -251,35 +173,36 @@ public class DirectoryMonitor implements
     }
     
     @SuppressWarnings("unchecked")
-    private Map<String,FileInfo> readState() {
-        Map<String,FileInfo> newFiles = null;
+    private Map<String, FileInfo> readState() {
+        Map<String, FileInfo> newFiles = null;
         if (monitorFile != null) {
-                ObjectInputStream inputStream = null;
+            ObjectInputStream inputStream = null;
+            try {
+                inputStream = new ObjectInputStream(new FileInputStream(monitorFile));
+                newFiles = (Map<String, FileInfo>) inputStream.readObject();
+            } catch (IOException ex) {
+                log.info("No directory monitor state to be read. This is to be expected on initial start of a new server");
+            } catch (ClassNotFoundException cnfe) {
+                log.warn("ClassNotFoundException reading directory monitor state from " + monitorFile.getName(), cnfe);
+            } finally {
                 try {
-                    inputStream = new ObjectInputStream(new FileInputStream(monitorFile));
-                    newFiles = (Map<String,FileInfo>) inputStream.readObject();
-                } catch (IOException ex) {
-                    log.info("No directory monitor state to be read. This is to be expected on initial start of a new server");
-                } catch (ClassNotFoundException cnfe) {
-                    log.warn("ClassNotFoundException reading directory monitor state from " + monitorFile.getName(), cnfe);
-                } finally {
-                    try {
-                        if (inputStream != null) {
-                            inputStream.close();
-                        }
-                    } catch (IOException ioe) {
-                        // ignore
+                    if (inputStream != null) {
+                        inputStream.close();
                     }
+                } catch (IOException ioe) {
+                    // ignore
                 }
+            }
         }
         if (newFiles == null) {
-            newFiles = new HashMap<String,FileInfo>();
+            newFiles = new HashMap<String, FileInfo>();
         }
         return newFiles;
     }
     
+    
     public void run() {
-        boolean serverStarted = false, initialized = false;
+        boolean initialized = false;
         while (!done) {
             try {
                 Thread.sleep(pollIntervalMillis);
@@ -288,18 +211,12 @@ public class DirectoryMonitor implements
             }
             try {
                 if (listener != null) {
-                    if (!serverStarted && listener.isServerRunning()) {
-                        serverStarted = true;
-                    }
-                    if (serverStarted) {
-                        if (!initialized) {
-                            initialized = true;
-                            initialize();
-                            listener.started();
-                        } else {
-                            doRemoves();
-                            scanDirectory();
-                        }
+                    if (!initialized) {
+                        initialized = true;
+                        initialize();
+                    } else {
+                        doRemoves();
+                        scanDirectory();
                     }
                 }
             } catch (Exception e) {
@@ -309,32 +226,9 @@ public class DirectoryMonitor implements
     }
 
     private void initialize() {
-        File parent = directory;
-        File[] children = parent.listFiles();
-        for (int i = 0; i < children.length; i++) {
-            File child = children[i];
-            if (!child.canRead()) {
-                continue;
-            }
-            if (child.equals(monitorFile)) {
-                continue;
-            }
-            FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
-            now.setChanging(false);
-            try {
-                now.setConfigId(calculateModuleId(child));
-                if (listener.isFileDeployed(child, now.getConfigId())) {
-                    now.setModified(listener.getDeploymentTime(child, now.getConfigId()));
-                    log.info("At startup, found "+now.getPath()+" with deploy time "+now.getModified()+" and file time "+new File(now.getPath()).lastModified());
-                    files.put(now.getPath(), now);
-                }
-            } catch (Exception e) {
-                log.error("Unable to scan file " + child.getAbsolutePath() + " during initialization", e);
-            }
-        }
-        persistState();
+        files = readState();
     }
-
+    
     /**
      * Looks for changes to the immediate contents of the directory we're watching.
      */
@@ -348,7 +242,11 @@ public class DirectoryMonitor implements
         }
         synchronized (files) {
             Set<String> oldList = new HashSet<String>(files.keySet());
-            List<FileAction> actions = new LinkedList<FileAction>();
+            
+            Collection<FileInfo> addedFiles = new ArrayList<FileInfo>();
+            Collection<FileInfo> modifiedFiles = new ArrayList<FileInfo>();
+            Collection<FileInfo> deletedFiles = new ArrayList<FileInfo>();
+
             boolean changeMade = false;
             for (int i = 0; i < children.length; i++) {
                 File child = children[i];
@@ -358,7 +256,7 @@ public class DirectoryMonitor implements
                 if (child.equals(monitorFile)) {
                     continue;
                 }
-                FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
+                FileInfo now = getFileInfo(child);
                 FileInfo last = files.get(now.getPath());
                 if (last == null) { // Brand new, wait a bit to make sure it's not still changing
                     now.setNewFile(true);
@@ -372,14 +270,16 @@ public class DirectoryMonitor implements
                             log.debug("File finished changing: " + now.getPath());
                             // Used to be changing, now in (hopefully) its final state
                             if (last.isNewFile()) {
-                                actions.add(new FileAction(FileAction.NEW_FILE, child, last));
+                                addedFiles.add(last);
+                                last.setNewFile(false);
                             } else {
-                                actions.add(new FileAction(FileAction.UPDATED_FILE, child, last));
+                                modifiedFiles.add(last);
                             }
                             last.setChanging(false);
+                            changeMade = true;
                         } 
                     } else { // is changing, when finish will do the file action accordingly
-                        if (last.isNewFile()){ // is adding file
+                        if (last.isNewFile()) { // is adding file
                             now.setNewFile(last.isNewFile());
                         } else { // is replacing file
                             now.setConfigId(last.getConfigId());
@@ -394,207 +294,92 @@ public class DirectoryMonitor implements
             // Look for any files we used to know about but didn't find in this pass
             for (Iterator<String> it = oldList.iterator(); it.hasNext();) {
                 String name = it.next();
-                FileInfo info = files.get(name);
+                FileInfo info = files.remove(name);
+                changeMade = true;
                 log.debug("File removed: " + name);
-                if (info.isNewFile()) { // was never deployed, just drop it
-                    files.remove(name);
-                    changeMade = true;
-                } else {
-                    actions.add(new FileAction(FileAction.REMOVED_FILE, new File(name), info));
-                }
+                deletedFiles.add(info);
             }
+                        
+            validate(addedFiles, false);
+            validate(modifiedFiles, false);
             
-            // First pass: validate all changed files, so any obvious errors come out first
-            for (Iterator<FileAction> it = actions.iterator(); it.hasNext();) {
-                FileAction action = it.next();
-                if (!listener.validateFile(action.child, action.info.getConfigId())) {
-                    resolveFile(action);
-                    it.remove();
-                }
-            }
-                
-            // Second pass: do what we're meant to do
-            for (Iterator<FileAction> it = actions.iterator(); it.hasNext();) {
-                FileAction action = it.next();
+            if (!addedFiles.isEmpty() || !modifiedFiles.isEmpty() || !deletedFiles.isEmpty()) {
+                log.debug("Added files: {}", addedFiles);
+                log.debug("Modified files: {}", modifiedFiles);
+                log.debug("Deleted files: {}", deletedFiles);
                 try {
-                    if (action.action == FileAction.REMOVED_FILE) {
-                        workingOnConfigId = action.info.getConfigId();
-                        if (action.info.getConfigId() == null || listener.fileRemoved(action.child, action.info.getConfigId())) {
-                            files.remove(action.child.getPath());
-                            changeMade = true;
-                        }
-                        workingOnConfigId = null;
-                    } else if (action.action == FileAction.NEW_FILE) {
-                        if (listener.isFileDeployed(action.child, calculateModuleId(action.child))) {
-                            workingOnConfigId = calculateModuleId(action.child);
-                            String result = listener.fileUpdated(action.child, workingOnConfigId);
-                            if (result != null) {
-                                if (!result.equals("")) {
-                                    action.info.setConfigId(result);
-                                } else {
-                                    action.info.setConfigId(calculateModuleId(action.child));
-                                }
-                            }
-                            // remove the previous jar or directory if duplicate
-                            File[] childs = directory.listFiles();
-                            for (int i = 0; i < childs.length; i++) {
-                                File child = children[i];
-                                if (!child.canRead()) {
-                                    continue;
-                                }
-                                if (child.equals(monitorFile)) {
-                                    continue;
-                                }
-                                String path = child.getAbsolutePath();
-                                String configId = files.get(path).getConfigId();
-                                if (configId != null && configId.equals(workingOnConfigId) && !action.child.getAbsolutePath().equals(path)) {
-                                    File fd = new File(path);
-                                    if (fd.isDirectory()) {
-                                        log.info("Deleting the Directory: " + path);
-                                        if (FileUtils.recursiveDelete(fd))
-                                            log.debug("Successfully deleted the Directory: " + path);
-                                        else
-                                            log.error("Couldn't delete the hot deployed directory=" + path);
-                                    } else if (fd.isFile()) {
-                                        log.info("Deleting the File: " + path);
-                                        if (fd.delete()) {
-                                            log.debug("Successfully deleted the File: " + path);
-                                        } else
-                                            log.error("Couldn't delete the hot deployed file=" + path);
-                                    }
-                                    files.remove(path);
-                                    changeMade = true;
-                                }
-                            }
-                            workingOnConfigId = null;
-                        } else {
-                            String result = listener.fileAdded(action.child);
-                            if (result != null) {
-                                if (!result.equals("")) {
-                                    action.info.setConfigId(result);
-                                } else {
-                                    action.info.setConfigId(calculateModuleId(action.child));
-                                }
-                            }
-                        }
-                        action.info.setNewFile(false);
-                        changeMade = true;
-                    } else if (action.action == FileAction.UPDATED_FILE) {
-                        workingOnConfigId = action.info.getConfigId();
-                        String result = listener.fileUpdated(action.child, action.info.getConfigId());
-                        FileInfo update = action.info;
-                        if (result != null) {
-                            if (!result.equals("")) {
-                                update.setConfigId(result);
-                            } else {
-                                update.setConfigId(calculateModuleId(action.child));
-                            }
-                        }
-                        workingOnConfigId = null;
-                    }
-                } catch (Exception e) {
-                    log.error("Unable to " + action.getActionName() + " file " + action.child.getAbsolutePath(), e);
-                } finally {
-                    resolveFile(action);
+                    listener.scanComplete(addedFiles, modifiedFiles, deletedFiles);
+                } catch (Throwable e) {
+                    log.warn("Error calling scanComplete()", e);
                 }
             }
-
+            
             if (changeMade) {
                 persistState();
             }
         }
     }
     
-    private void resolveFile(FileAction action) {
-        if (action.action == FileAction.REMOVED_FILE) {
-            files.remove(action.child.getPath());
-        } 
-        
-        /* we don't need this, because the setChanging(false) has been called after the NEW_FILE/UPDATED_FILE action object was created.
-          else {
-            action.info.setChanging(false);
-        }*/
-    }
-
-    private String calculateModuleId(File module) {
-        String moduleId = null;
-        try {
-            moduleId = DeployUtils.extractModuleIdFromArchive(module);
-        } catch (Exception e) {
-            try {
-                moduleId = DeployUtils.extractModuleIdFromPlan(module);
-            } catch (IOException e2) {
-                log.warn("Unable to calculate module ID for file " + module.getAbsolutePath() + " [" + e2.getMessage() + "]");
+    private void validate(Collection<FileInfo> updatedFiles, boolean delete) {
+        for (Iterator<FileInfo> it = updatedFiles.iterator(); it.hasNext();) {
+            FileInfo info = it.next();
+            if (!listener.validateFile(new File(info.getPath()), info.getConfigId())) {
+                it.remove();
+                if (delete) {
+                    files.remove(info.getPath());
+                }
             }
         }
-        if (moduleId == null) {
-            int pos = module.getName().lastIndexOf('.');
-            moduleId = pos > -1 ? module.getName().substring(0, pos) : module.getName();
-            moduleId = listener.getModuleId(moduleId);
-        }
-        return moduleId;
     }
-
+   
+    private FileInfo getFileInfo(File file) {
+        FileInfo info = new FileInfo(file.getAbsolutePath());
+        info.setSize(file.isDirectory() ? 0 : file.length());
+        info.setModified(getLastModified(file));
+        return info;
+    }
+    
     /**
      * We don't pay attention to the size of the directory or files in the
      * directory, only the highest last modified time of anything in the
      * directory.  Hopefully this is good enough.
      */
-    private FileInfo getDirectoryInfo(File dir) {
-        FileInfo info = new FileInfo(dir.getAbsolutePath());
-        info.setSize(0);
-        info.setModified(getLastModifiedInDir(dir));
-        return info;
-    }
-
-    private long getLastModifiedInDir(File dir) {
-        long value = dir.lastModified();
-        File[] children = dir.listFiles();
-        long test;
-        for (int i = 0; i < children.length; i++) {
-            File child = children[i];
-            if (!child.canRead()) {
-                continue;
-            }
-            if (child.isDirectory()) {
-                test = getLastModifiedInDir(child);
-            } else {
-                test = child.lastModified();
-            }
-            if (test > value) {
-                value = test;
+    public static long getLastModified(File file) {
+        long value = file.lastModified();
+        if (file.isDirectory()) {
+            File[] children = file.listFiles();
+            long test;
+            for (int i = 0; i < children.length; i++) {
+                File child = children[i];
+                if (!child.canRead()) {
+                    continue;
+                }
+                test = getLastModified(child);
+                if (test > value) {
+                    value = test;
+                }
             }
         }
         return value;
     }
 
-    private FileInfo getFileInfo(File child) {
-        FileInfo info = new FileInfo(child.getAbsolutePath());
-        info.setSize(child.length());
-        info.setModified(child.lastModified());
-        return info;
-    }
-
-    private static class FileAction {
-        private static int NEW_FILE = 1;
-        private static int UPDATED_FILE = 2;
-        private static int REMOVED_FILE = 3;
-        private int action;
-        private File child;
-        private FileInfo info;
-
-        public FileAction(int action, File child, FileInfo info) {
-            this.action = action;
-            this.child = child;
-            this.info = info;
-        }
+    public static interface MonitorListener {
+        
+        /**
+         * Called to check whether a file passes the smell test before
+         * attempting to deploy it.
+         *
+         * @return true if there's nothing obviously wrong with this file.
+         *         false if there is (for example, it's clearly not
+         *         deployable).
+         */
+        boolean validateFile(File file, String configId);
+        
+        void scanComplete(Collection<FileInfo> addedFiles, Collection<FileInfo> modifiedFiles, Collection<FileInfo> deletedFiles);
 
-        public String getActionName() {
-            return action == NEW_FILE ? "deploy" : action == UPDATED_FILE ? "redeploy" : "undeploy";
-        }
     }
-
-    private static class FileInfo implements Serializable {
+    
+    public static class FileInfo implements Serializable {
         private String path;
         private long size;
         private long modified;
@@ -651,7 +436,7 @@ public class DirectoryMonitor implements
         public void setConfigId(String configId) {
             this.configId = configId;
         }
-
+        
         public boolean isSame(FileInfo info) {
             if (!path.equals(info.path)) {
                 throw new IllegalArgumentException("Should only be used to compare two files representing the same path!");

Modified: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/HotDeployer.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/HotDeployer.java?rev=1131238&r1=1131237&r2=1131238&view=diff
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/HotDeployer.java (original)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/HotDeployer.java Fri Jun  3 20:58:41 2011
@@ -21,7 +21,7 @@ package org.apache.geronimo.deployment.h
  *
  * @version $Rev$ $Date$
  */
-public interface HotDeployer extends DirectoryMonitor.Listener {
+public interface HotDeployer {
     public int getPollIntervalMillis();
     public void setPollIntervalMillis(int millis);
 }

Added: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java?rev=1131238&view=auto
==============================================================================
--- geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java (added)
+++ geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java Fri Jun  3 20:58:41 2011
@@ -0,0 +1,429 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.deployment.hot;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Collection;
+
+import javax.enterprise.deploy.spi.DeploymentManager;
+import javax.enterprise.deploy.spi.Target;
+import javax.enterprise.deploy.spi.TargetModuleID;
+import javax.enterprise.deploy.spi.exceptions.DeploymentManagerCreationException;
+import javax.enterprise.deploy.spi.factories.DeploymentFactory;
+import javax.enterprise.deploy.spi.status.ProgressObject;
+
+import org.apache.geronimo.common.DeploymentException;
+import org.apache.geronimo.deployment.cli.DeployUtils;
+import org.apache.geronimo.deployment.plugin.factories.DeploymentFactoryWithKernel;
+import org.apache.geronimo.deployment.plugin.jmx.JMXDeploymentManager;
+import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.config.Configuration;
+import org.apache.geronimo.kernel.config.ConfigurationManager;
+import org.apache.geronimo.kernel.repository.Artifact;
+import org.apache.geronimo.kernel.repository.MissingDependencyException;
+import org.apache.geronimo.kernel.util.JarUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class ModuleHandler implements DirectoryMonitor.MonitorListener {
+
+    private static final Logger log = LoggerFactory.getLogger(ModuleHandler.class);
+    
+    // Try to make this stand out as the user is likely to get a ton of errors if this comes up
+    private static final String BAD_LAYOUT_MESSAGE = "CANNOT DEPLOY: It looks like you unpacked an application or module " +
+            "directly into the hot deployment directory.  THIS DOES NOT WORK.  You need to unpack into a " +
+            "subdirectory directly under the hot deploy directory.  For example, if the hot deploy directory " +
+            "is 'deploy/' and your file is 'webapp.war' then you could unpack it into a directory 'deploy/webapp.war/'";
+    
+    private final DeploymentFactory factory;
+    private final ConfigurationManager configManager;
+    private String deploymentURI = "deployer:geronimo:inVM";
+    private String deploymentUser;
+    private String deploymentPassword;
+    private volatile String workingOnConfigId;
+    
+    public ModuleHandler(Kernel kernel, ConfigurationManager configManager) {
+        this.factory = new DeploymentFactoryWithKernel(kernel);
+        this.configManager = configManager;
+    }
+    
+    public String getDeploymentUser() {
+        return deploymentUser;
+    }
+
+    public void setDeploymentUser(String deploymentUser) {
+        this.deploymentUser = deploymentUser;
+    }
+
+    public String getDeploymentPassword() {
+        return deploymentPassword;
+    }
+
+    public void setDeploymentPassword(String deploymentPassword) {
+        this.deploymentPassword = deploymentPassword;
+    }
+    
+    public String getDeploymentURI() {
+        return deploymentURI;
+    }
+
+    public void setDeploymentURI(String deploymentURI) {
+        if (deploymentURI != null && !deploymentURI.trim().equals("")) {
+            this.deploymentURI = deploymentURI.trim();
+        }
+    }
+    
+    public String getWorkingOnConfigId() {
+        return workingOnConfigId;
+    }
+    
+    private DeploymentManager getDeploymentManager() throws DeploymentManagerCreationException {
+        DeploymentManager manager = factory.getDeploymentManager(deploymentURI, deploymentUser, deploymentPassword);
+        if (manager instanceof JMXDeploymentManager) {
+            ((JMXDeploymentManager) manager).setLogConfiguration(false, true);
+        }
+        return manager;
+    }
+    
+    @Override
+    public void scanComplete(Collection<DirectoryMonitor.FileInfo> addedFiles, Collection<DirectoryMonitor.FileInfo> modifiedFiles, Collection<DirectoryMonitor.FileInfo> deletedFiles) {       
+        for (DirectoryMonitor.FileInfo deletedFile : deletedFiles) {
+            String moduleId = getModuleId(deletedFile);
+            if (isModuleDeployed(moduleId)) {
+                // check if deployed module is older
+                if (deletedFile.getModified() < getModuleLastModified(moduleId)) {
+                    fileRemoved(new File(deletedFile.getPath()), moduleId);
+                } else {
+                    log.debug("File {} was removed but {} module was not undeployed since the deployed module is newer", deletedFile.getPath(), moduleId);
+                }
+            }
+        }
+
+        for (DirectoryMonitor.FileInfo addedFile : addedFiles) {
+            String moduleId = getModuleId(addedFile);
+            File moduleFile = new File(addedFile.getPath());
+            if (isModuleDeployed(moduleId)) {
+                // check if deployed module is newer
+                if (addedFile.getModified() > getModuleLastModified(moduleId)) {
+                    String newModuleId = fileUpdated(moduleFile, moduleId);
+                    if (newModuleId != null) {
+                        addedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
+                    }
+                } else {
+                    log.debug("File {} was added but {} module was not redeployed since the deployed module is newer", addedFile.getPath(), moduleId);                    
+                }
+            } else {
+                String newModuleId = fileAdded(moduleFile);
+                if (newModuleId != null) {
+                    addedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
+                }
+            }
+        }
+
+        for (DirectoryMonitor.FileInfo modifiedFile : modifiedFiles) {
+            String moduleId = getModuleId(modifiedFile);
+            File moduleFile = new File(modifiedFile.getPath());
+            if (isModuleDeployed(moduleId)) {
+                // check if deployed module is newer
+                if (modifiedFile.getModified() > getModuleLastModified(moduleId)) {
+                    String newModuleId = fileUpdated(moduleFile, moduleId);
+                    if (newModuleId != null) {
+                        modifiedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
+                    }
+                } else {
+                    log.debug("File {} was modified but {} module was not redeployed since the deployed module is newer", modifiedFile.getPath(), moduleId);                                    
+                }
+            } else {
+                String newModuleId = fileAdded(moduleFile);
+                if (newModuleId != null) {
+                    modifiedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
+                }
+            }
+        }
+    }
+
+    private String getModuleId(DirectoryMonitor.FileInfo fileInfo) {
+        String moduleId = fileInfo.getConfigId();
+        if (moduleId == null) {
+            moduleId = calculateModuleId(new File(fileInfo.getPath()));
+        }
+        return moduleId;
+    }
+    
+    private String calculateModuleId(File module) {
+        String moduleId = null;
+        try {
+            moduleId = DeployUtils.extractModuleIdFromArchive(module);
+        } catch (Exception e) {
+            try {
+                moduleId = DeployUtils.extractModuleIdFromPlan(module);
+            } catch (Exception e2) {
+                log.debug("Unable to calculate module ID for file " + module.getAbsolutePath() + " [" + e2.getMessage() + "]");
+            }
+        }
+        if (moduleId == null) {
+            int pos = module.getName().lastIndexOf('.');
+            moduleId = pos > -1 ? module.getName().substring(0, pos) : module.getName();
+            moduleId = getModuleId(moduleId);
+        }
+        return moduleId;
+    }
+
+    public String getModuleId(String config) {
+        DeploymentManager mgr = null;
+        try {
+            mgr = getDeploymentManager();
+            Target[] targets = mgr.getTargets();
+            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
+            for (int j = 0; j < ids.length; j++) {
+                String moduleId = ids[j].getModuleID();
+                String[] parts = moduleId.split("/", -1);
+                if (parts.length != 4) {
+                    continue;
+                }
+                if (parts[1] != null && parts[1].equals(config))
+                    return ids[j].getModuleID();
+            }
+        } catch (Exception ex) {
+            log.error("Unable to getModuleId", ex);
+        } finally {
+            if (mgr != null) {
+                mgr.release();
+            }
+        }
+        return config;
+    }
+
+    public boolean isModuleDeployed(String configId) {
+        DeploymentManager mgr = null;
+        try {
+            mgr = getDeploymentManager();
+            Target[] targets = mgr.getTargets();
+            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
+            DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
+            return true;
+        } catch (DeploymentException e) {
+            log.debug("Found new file in deploy directory on startup with ID " + configId);
+        } catch (Exception e) {
+            log.error("Unable to check status", e);
+        } finally {
+            if (mgr != null) {
+                mgr.release();
+            }
+        }
+        return false;
+    }
+
+    public String fileAdded(File file) {
+        log.info("Deploying " + file.getName());
+        DeploymentManager mgr = null;
+        TargetModuleID[] modules = null;
+        boolean completed = false;
+        try {
+            mgr = getDeploymentManager();
+            Target[] targets = mgr.getTargets();
+            if (null == targets) {
+                throw new IllegalStateException("No target to distribute to");
+            }
+            targets = new Target[] { targets[0] };
+
+            ProgressObject po;
+
+            if (JarUtils.isJarFile(file) || file.isDirectory()) {
+                po = mgr.distribute(targets, file, null);
+            } else {
+                po = mgr.distribute(targets, null, file);
+            }
+            waitForProgress(po);
+            if (po.getDeploymentStatus().isCompleted()) {
+                modules = po.getResultTargetModuleIDs();
+                po = mgr.start(modules);
+                waitForProgress(po);
+                if (po.getDeploymentStatus().isCompleted()) {
+                    completed = true;
+                } else {
+                    log.warn("Unable to start some modules for " + file.getAbsolutePath());
+                }
+                modules = po.getResultTargetModuleIDs();
+                for (int i = 0; i < modules.length; i++) {
+                    TargetModuleID result = modules[i];
+                    log.info(DeployUtils.reformat("Deployed " + result.getModuleID()
+                            + (targets.length > 1 ? " to " + result.getTarget().getName() : "")
+                            + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
+                    if (result.getChildTargetModuleID() != null) {
+                        for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
+                            TargetModuleID child = result.getChildTargetModuleID()[j];
+                            log.info(DeployUtils.reformat("  `-> " + child.getModuleID()
+                                    + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
+                        }
+                    }
+                }
+            } else {
+                log.error("Unable to deploy: " + po.getDeploymentStatus().getMessage());
+                return null;
+            }
+        } catch (DeploymentManagerCreationException e) {
+            log.error("Unable to open deployer", e);
+        } catch (IOException e) {
+            log.error("Unable to determine if file is a jar", e);
+        } finally {
+            if (mgr != null)
+                mgr.release();
+        }
+        if (completed && modules != null) {
+            if (modules.length == 1) {
+                return modules[0].getModuleID();
+            } else {
+                return "";
+            }
+        } else if (modules != null) { // distribute completed but not start or
+                                      // something like that
+            return "";
+        } else {
+            return null;
+        }
+    }
+
+    public String fileUpdated(File file, String configId) {
+        workingOnConfigId = configId;
+        log.info("Redeploying " + file.getName());
+        DeploymentManager mgr = null;
+        TargetModuleID[] modules = null;
+        try {
+            mgr = getDeploymentManager();
+            Target[] targets = mgr.getTargets();
+            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
+            ids = DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
+            ProgressObject po;
+            if (JarUtils.isJarFile(file) || file.isDirectory()) {
+                po = mgr.redeploy(ids, file, null);
+            } else {
+                po = mgr.redeploy(ids, null, file);
+            }
+            waitForProgress(po);
+            if (po.getDeploymentStatus().isCompleted()) {
+                modules = po.getResultTargetModuleIDs();
+                for (int i = 0; i < modules.length; i++) {
+                    TargetModuleID result = modules[i];
+                    log.info(DeployUtils.reformat("Redeployed " + result.getModuleID()
+                            + (targets.length > 1 ? " to " + result.getTarget().getName() : "")
+                            + (result.getWebURL() == null ? "" : " @ " + result.getWebURL()), 4, 72));
+                    if (result.getChildTargetModuleID() != null) {
+                        for (int j = 0; j < result.getChildTargetModuleID().length; j++) {
+                            TargetModuleID child = result.getChildTargetModuleID()[j];
+                            log.info(DeployUtils.reformat("  `-> " + child.getModuleID()
+                                    + (child.getWebURL() == null ? "" : " @ " + child.getWebURL()), 4, 72));
+                        }
+                    }
+                }
+            } else {
+                log.error("Unable to redeploy " + file.getAbsolutePath() + "(" + configId + ")"
+                        + po.getDeploymentStatus().getMessage());
+            }
+        } catch (DeploymentManagerCreationException e) {
+            log.error("Unable to open deployer", e);
+        } catch (Exception e) {
+            log.error("Unable to undeploy", e);
+        } finally {
+            if (mgr != null) {
+                mgr.release();
+            }
+            workingOnConfigId = null;
+        }
+        if (modules != null) {
+            if (modules.length == 1) {
+                return modules[0].getModuleID();
+            } else {
+                return "";
+            }
+        } else {
+            return null;
+        }
+    }
+
+    public boolean fileRemoved(File file, String configId) {
+        workingOnConfigId = configId;
+        log.info("Undeploying " + file.getName());
+        DeploymentManager mgr = null;
+        try {
+            mgr = getDeploymentManager();
+            Target[] targets = mgr.getTargets();
+            TargetModuleID[] ids = mgr.getAvailableModules(null, targets);
+            ids = DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
+            ProgressObject po = mgr.undeploy(ids);
+            waitForProgress(po);
+            if (po.getDeploymentStatus().isCompleted()) {
+                TargetModuleID[] modules = po.getResultTargetModuleIDs();
+                for (int i = 0; i < modules.length; i++) {
+                    TargetModuleID result = modules[i];
+                    log.info(DeployUtils.reformat("Undeployed " + result.getModuleID()
+                            + (targets.length > 1 ? " to " + result.getTarget().getName() : ""), 4, 72));
+                }
+            } else {
+                log.error("Unable to undeploy " + file.getAbsolutePath() + "(" + configId + ")"
+                        + po.getDeploymentStatus().getMessage());
+                return false;
+            }
+        } catch (DeploymentManagerCreationException e) {
+            log.error("Unable to open deployer", e);
+            return false;
+        } catch (Exception e) {
+            log.error("Unable to undeploy", e);
+            return false;
+        } finally {
+            if (mgr != null) {
+                mgr.release();
+            }
+            workingOnConfigId = null;
+        }
+        return true;
+    }
+
+    private void waitForProgress(ProgressObject po) {
+        while (po.getDeploymentStatus().isRunning()) {
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+                log.error(e.getMessage(), e);
+            }
+        }
+    }
+
+    public long getModuleLastModified(String configId) {
+        try {
+            Artifact art = configManager.getArtifactResolver().resolveInClassLoader(Artifact.create(configId));
+            Configuration config = configManager.getConfiguration(art);
+            File file = config.getConfigurationResolver().resolve(art);
+            long lastModified = DirectoryMonitor.getLastModified(file);
+            return lastModified;
+        } catch (MissingDependencyException e) {
+            log.error("Unknown configuration " + configId);
+            return -1;
+        }
+    }
+    
+    @Override
+    public boolean validateFile(File file, String configId) {
+        if (file.isDirectory() && (file.getName().equals("WEB-INF") || file.getName().equals("META-INF"))) {
+            log.error("(" + file.getName() + ") " + BAD_LAYOUT_MESSAGE);
+            return false;
+        }
+        return true;
+    }
+    
+}

Propchange: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
------------------------------------------------------------------------------
    svn:keywords = Date Revision

Propchange: geronimo/server/trunk/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain



Mime
View raw message