GERONIMO-6093 changes to satisfy some special Hot-deploy scenarios

git-svn-id: https://svn.apache.org/repos/asf/geronimo/server/trunk@1149529 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
index 5524a3e..340b312 100644
--- a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
+++ b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
@@ -82,7 +82,7 @@
     }
 
     // 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.
+    // this method also can be called with the WAB id. And the WAB's id will also go into the "toRemove" list.
     public void undeployed(Artifact id) {
         if (monitor != null) {
             String moduleId = id.toString();
diff --git a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
index d2a0f83..8ab55ea 100644
--- a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
+++ b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
@@ -53,7 +53,10 @@
     private File directory;
     private boolean done = false;
     private MonitorListener listener; // a little cheesy, but do we really need multiple listeners?
-    private Map<String, FileInfo> files;
+    // This Map records the files in the hot deploy folder. 
+    // The FileInfo's configId could be null, which represents it was not successfully deployed 
+    // through this hot deployer.
+    private Map<String, FileInfo> fileRecords;
     private final ArrayList <String> toRemove = new ArrayList <String>();
     private File monitorFile;
 
@@ -121,12 +124,13 @@
 
     private void doRemoves() {
         synchronized (toRemove) {
-            synchronized (files) {
+            synchronized (fileRecords) {
+                boolean changeMade = false;
                 for (Iterator<String> idItr = toRemove.iterator(); idItr.hasNext();) {
                     String configId = idItr.next();
-                    for (Iterator<String> filesItr = files.keySet().iterator(); filesItr.hasNext();) {
+                    for (Iterator<String> filesItr = fileRecords.keySet().iterator(); filesItr.hasNext();) {
                         String path = filesItr.next();
-                        FileInfo info = files.get(path);
+                        FileInfo info = fileRecords.get(path);
                         if (info.getConfigId() == null) {
                             // the file is new added, have not deployed yet, so its config id is not set.
                             continue;
@@ -138,13 +142,17 @@
                                 if (!FileUtils.recursiveDelete(file)) {
                                     log.error("Hot deployer unable to delete " + path);
                                 }
-                                filesItr.remove();
                             }
+                            filesItr.remove();
+                            changeMade = true;
                         }
                     }
                     // remove the id form the toRemove list no matter if we found it in the "files" list
                     idItr.remove();
                 }
+                if (changeMade) {
+                    persistState();
+                }
             }
         }
     }    
@@ -158,7 +166,7 @@
         ObjectOutputStream outputStream = null;
         try {
             outputStream = new ObjectOutputStream(new FileOutputStream(monitorFile));
-            outputStream.writeObject(files);
+            outputStream.writeObject(fileRecords);
         } catch (IOException ioe) {
             log.warn("Error persisting directory monitor state to " + monitorFile.getName(), ioe);
         } finally {
@@ -226,7 +234,7 @@
     }
 
     private void initialize() {
-        files = readState();
+        fileRecords = readState();
     }
     
     /**
@@ -240,8 +248,8 @@
             done = true;
             return;
         }
-        synchronized (files) {
-            Set<String> oldList = new HashSet<String>(files.keySet());
+        synchronized (fileRecords) {
+            Set<String> oldList = new HashSet<String>(fileRecords.keySet());
             
             Collection<FileInfo> addedFiles = new ArrayList<FileInfo>();
             Collection<FileInfo> modifiedFiles = new ArrayList<FileInfo>();
@@ -257,10 +265,10 @@
                     continue;
                 }
                 FileInfo now = getFileInfo(child);
-                FileInfo last = files.get(now.getPath());
+                FileInfo last = fileRecords.get(now.getPath());
                 if (last == null) { // Brand new, wait a bit to make sure it's not still changing
                     now.setNewFile(true);
-                    files.put(now.getPath(), now);
+                    fileRecords.put(now.getPath(), now);
                     changeMade = true;
                     log.debug("New File: " + now.getPath());
                 } else {
@@ -284,7 +292,7 @@
                         } else { // is replacing file
                             now.setConfigId(last.getConfigId());
                         }
-                        files.put(now.getPath(), now);
+                        fileRecords.put(now.getPath(), now);
                         changeMade = true;
                         log.debug("File Changed: " + now.getPath());
                     }
@@ -294,7 +302,7 @@
             // 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.remove(name);
+                FileInfo info = fileRecords.remove(name);
                 changeMade = true;
                 log.debug("File removed: " + name);
                 deletedFiles.add(info);
@@ -326,7 +334,7 @@
             if (!listener.validateFile(new File(info.getPath()), info.getConfigId())) {
                 it.remove();
                 if (delete) {
-                    files.remove(info.getPath());
+                    fileRecords.remove(info.getPath());
                 }
             }
         }
diff --git a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
index 27fc791..fd15d7b 100644
--- a/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
+++ b/plugins/hotdeploy/geronimo-hot-deploy/src/main/java/org/apache/geronimo/deployment/hot/ModuleHandler.java
@@ -103,119 +103,151 @@
     @Override
     public void scanComplete(Collection<DirectoryMonitor.FileInfo> addedFiles, Collection<DirectoryMonitor.FileInfo> modifiedFiles, Collection<DirectoryMonitor.FileInfo> deletedFiles) {       
         for (DirectoryMonitor.FileInfo deletedFile : deletedFiles) {
-            if (deletedFile.getConfigId() == null) {
+            // the ConfigId of the FileInfo of the file just deleted might be null 
+            // which means the file was not deployed successfully before
+            File file = new File(deletedFile.getPath());
+            String moduleId = deletedFile.getConfigId();
+            if (moduleId == null) {
                 // This means the file was never deployed, and now we are deleting it from the hot deploy folder.
-                // We should not use getModuleId(addedFile) here, because we can not calculate the configId from a non-exist file.
+                // We should not use getModuleId(addedFile) here, because we can not calculate the configId from a non-exist file,
+                // and if then we guess one, it might undeploy a module deployed by other files.
                 log.info("File: {} was removed", deletedFile.getPath());
+                
             } else {
-                String moduleId = deletedFile.getConfigId();
                 if (isModuleDeployed(moduleId)) {
-                    // check if deployed module is older
+                    // check if file is older
                     if (deletedFile.getModified() < getModuleLastModified(moduleId)) {
-                        fileRemoved(new File(deletedFile.getPath()), moduleId);
+                        // un-deploy
+                        if (fileRemoved(file, moduleId)) {
+                            log.info("File: {} was removed, and module: {} was succussfully undeployed.", deletedFile.getPath(), moduleId);
+                        } else {
+                            log.warn("File: {} was removed, but module: {} can not be undeployed.", deletedFile.getPath(), moduleId);
+                        }
                     } else {
-                        log.warn("File: {} was removed, but module: {} was not undeployed, since the deployed one is newer.", deletedFile.getPath(), moduleId);
+                        log.warn("File: {} was removed, but module: {} was not undeployed, "
+                                  + "since the deployed one is older, i.e the module was not deployed by the file you just deleted.", deletedFile.getPath(), moduleId);
                     }
                 } else {
-                    //should not happen
+                    // should not happen
                     log.warn("Module: {} has been already undeployed in other ways", 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);
-                    }
+            // the ConfigId of the FileInfo of the file just added must be null
+            File file = new File(addedFile.getPath());
+            String moduleId = addedFile.getConfigId();
+            if (moduleId == null) {
+                moduleId = calculateModuleId(file);
+                if (isModuleDeployed(moduleId)) {
+                    log.warn("File: {} was added, but Module: {} has been deployed before. " +
+                             "Please undeploy the old one first, and then re-add this file.", addedFile.getPath(), moduleId);                    
                 } else {
-                    log.warn("File: {} was added, but module: {} was not redeployed, since the deployed one is newer.", addedFile.getPath(), moduleId);                    
+                    // new add
+                    String newModuleId = fileAdded(file);
+                    if (newModuleId != null) {
+                        moduleId = newModuleId.length() == 0 ? moduleId : newModuleId;
+                        addedFile.setConfigId(moduleId);
+                        log.info("File: {} was added, and Module: {} was succussfully deployed.", addedFile.getPath(), moduleId);
+                    } else {
+                        log.warn("File: {} was added, but can not be deployed.", addedFile.getPath());
+                    }
                 }
             } else {
-                String newModuleId = fileAdded(moduleFile);
-                if (newModuleId != null) {
-                    addedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
-                }
+                log.error("File: {} is not a new added file!", addedFile.getPath());
             }
         }
 
         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);
-                    }
+            // the ConfigId of the FileInfo of the file just modified might be null
+            // which means the file was not deployed successfully before
+            File file = new File(modifiedFile.getPath());
+            String moduleId = modifiedFile.getConfigId();
+            if (moduleId == null) {
+                moduleId = calculateModuleId(file);
+                if (isModuleDeployed(moduleId)) {
+                    log.warn("File: {} was modified, but Module: {} has been deployed before by other means. " +
+                            "Please undeploy the old one first, and then re-add this file.", modifiedFile.getPath(), moduleId);    
                 } else {
-                    log.warn("File: {} was modified, but module: {} was not redeployed, since the deployed one is newer.", modifiedFile.getPath(), moduleId);                                    
+                    // new add
+                    String newModuleId = fileAdded(file);
+                    if (newModuleId != null) {
+                        moduleId = newModuleId.length() == 0 ? moduleId : newModuleId;
+                        modifiedFile.setConfigId(moduleId);
+                        log.info("File: {} was modified, and Module: {} was succussfully deployed.", modifiedFile.getPath(), moduleId);
+                    } else {
+                        log.warn("File: {} was modified, but can not be deployed.", modifiedFile.getPath());
+                    }
                 }
             } else {
-                String newModuleId = fileAdded(moduleFile);
-                if (newModuleId != null) {
-                    modifiedFile.setConfigId(newModuleId.length() == 0 ? moduleId : newModuleId);
+                if (isModuleDeployed(moduleId)) {
+                    // redeploy
+                    String newModuleId = fileUpdated(file, moduleId);
+                    if (newModuleId != null) {
+                        moduleId = newModuleId.length() == 0 ? moduleId : newModuleId;
+                        modifiedFile.setConfigId(moduleId);
+                        log.info("File: {} was modified, and Module: {} was succussfully re-deployed.", modifiedFile.getPath(), moduleId);
+                    } else {
+                        log.warn("File: {} was modified, but Module: {} can not be re-deployed.", modifiedFile.getPath(), moduleId);
+                    }
+                } else {
+                    // new add
+                    String newModuleId = fileAdded(file);
+                    if (newModuleId != null) {
+                        moduleId = newModuleId.length() == 0 ? moduleId : newModuleId;
+                        modifiedFile.setConfigId(moduleId);
+                        log.info("File: {} was modified, and Module: {} was succussfully deployed.", modifiedFile.getPath(), moduleId);
+                    } else {
+                        log.warn("File: {} was modified, but can not be deployed.", modifiedFile.getPath());
+                    }
                 }
             }
-        }
-    }
 
-    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) {
+    private String calculateModuleId(File moduleFile) {
         String moduleId = null;
         try {
-            moduleId = DeployUtils.extractModuleIdFromArchive(module);
+            moduleId = DeployUtils.extractModuleIdFromArchive(moduleFile);
         } catch (Exception e) {
             try {
-                moduleId = DeployUtils.extractModuleIdFromPlan(module);
+                moduleId = DeployUtils.extractModuleIdFromPlan(moduleFile);
             } catch (Exception e2) {
-                log.error("Unable to calculate module ID for file " + module.getAbsolutePath() + " [" + e2.getMessage() + "]");
+                log.debug("Unable to calculate module ID for file " + moduleFile.getAbsolutePath() + " [" + e2.getMessage() + "]");
             }
         }
         if (moduleId == null) {
-            int pos = module.getName().lastIndexOf('.');
-            moduleId = pos > -1 ? module.getName().substring(0, pos) : module.getName();
-            moduleId = getModuleId(moduleId);
+            int pos = moduleFile.getName().lastIndexOf('.');
+            moduleId = pos > -1 ? moduleFile.getName().substring(0, pos) : moduleFile.getName();
+            moduleId = guessModuleId(moduleId);
         }
         return moduleId;
     }
 
-    public String getModuleId(String config) {
+    private String guessModuleId(String moduleId) {
         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);
+                String[] parts = ids[j].getModuleID().split("/", -1);
                 if (parts.length != 4) {
                     continue;
                 }
-                if (parts[1] != null && parts[1].equals(config))
+                if (parts[1] != null && parts[1].equals(moduleId))
                     return ids[j].getModuleID();
             }
         } catch (Exception ex) {
-            log.error("Unable to getModuleId", ex);
+            log.debug("Unable to guessModuleId", ex);
         } finally {
             if (mgr != null) {
                 mgr.release();
             }
         }
-        return config;
+        return moduleId;
     }
 
     public boolean isModuleDeployed(String configId) {
@@ -227,7 +259,7 @@
             DeployUtils.identifyTargetModuleIDs(ids, configId, true).toArray(new TargetModuleID[0]);
             return true;
         } catch (DeploymentException e) {
-            log.warn("Found new file in deploy directory on startup with ID " + configId);
+            log.debug("Found new file in deploy directory on startup with ID " + configId);
         } catch (Exception e) {
             log.error("Unable to check status", e);
         } finally {