You are viewing a plain text version of this content. The canonical link for it is here.
Posted to scm@geronimo.apache.org by am...@apache.org on 2006/05/27 00:39:58 UTC

svn commit: r409771 - in /geronimo/trunk: configs/geronimo-gbean-deployer/src/plan/ configs/hot-deployer/src/plan/ configs/j2ee-system/src/plan/ modules/deployment/src/java/org/apache/geronimo/deployment/ modules/hot-deploy/src/java/org/apache/geronimo...

Author: ammulder
Date: Fri May 26 15:39:58 2006
New Revision: 409771

URL: http://svn.apache.org/viewvc?rev=409771&view=rev
Log:
Merge fix for GERONIMO-1174 and GERONIMO-1431 to trunk

Modified:
    geronimo/trunk/configs/geronimo-gbean-deployer/src/plan/plan.xml
    geronimo/trunk/configs/hot-deployer/src/plan/plan.xml
    geronimo/trunk/configs/j2ee-system/src/plan/plan.xml
    geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java
    geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
    geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
    geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java
    geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java
    geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java
    geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java

Modified: geronimo/trunk/configs/geronimo-gbean-deployer/src/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/trunk/configs/geronimo-gbean-deployer/src/plan/plan.xml?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/configs/geronimo-gbean-deployer/src/plan/plan.xml (original)
+++ geronimo/trunk/configs/geronimo-gbean-deployer/src/plan/plan.xml Fri May 26 15:39:58 2006
@@ -24,6 +24,8 @@
          </reference>
         <reference name="Builders">
         </reference>
+        <reference name="Watchers">
+        </reference>
     </gbean>
 
     <!-- Builder for handling plans defining Geronimo modules -->

Modified: geronimo/trunk/configs/hot-deployer/src/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/trunk/configs/hot-deployer/src/plan/plan.xml?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/configs/hot-deployer/src/plan/plan.xml (original)
+++ geronimo/trunk/configs/hot-deployer/src/plan/plan.xml Fri May 26 15:39:58 2006
@@ -30,6 +30,9 @@
         <reference name="ServerInfo">
             <name>ServerInfo</name>
         </reference>
+        <reference name="ConfigManager">
+            <name>ConfigurationManager</name>
+        </reference>
 		<attribute name="path">deploy/</attribute>
         <attribute name="pollIntervalMillis">2000</attribute>
         <dependency>

Modified: geronimo/trunk/configs/j2ee-system/src/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/trunk/configs/j2ee-system/src/plan/plan.xml?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/configs/j2ee-system/src/plan/plan.xml (original)
+++ geronimo/trunk/configs/j2ee-system/src/plan/plan.xml Fri May 26 15:39:58 2006
@@ -72,6 +72,8 @@
     </reference>
     <reference name="Stores">
     </reference>
+    <reference name="Watchers">
+    </reference>
     <reference name="AttributeStore">
       <name>AttributeManager</name>
     </reference>

Modified: geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java (original)
+++ geronimo/trunk/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java Fri May 26 15:39:58 2006
@@ -51,6 +51,7 @@
 import org.apache.geronimo.kernel.config.ConfigurationStore;
 import org.apache.geronimo.kernel.config.ConfigurationUtil;
 import org.apache.geronimo.kernel.config.InvalidConfigException;
+import org.apache.geronimo.kernel.config.DeploymentWatcher;
 import org.apache.geronimo.kernel.repository.Artifact;
 import org.apache.geronimo.kernel.repository.ArtifactResolver;
 import org.apache.geronimo.system.configuration.ExecutableConfigurationUtil;
@@ -68,11 +69,12 @@
     private DeployerReaper reaper;
     private final Collection builders;
     private final Collection stores;
+    private final Collection watchers;
     private final ArtifactResolver artifactResolver;
     private final Kernel kernel;
 
-    public Deployer(Collection builders, Collection stores, Kernel kernel) {
-        this(builders, stores, getArtifactResolver(kernel), kernel);
+    public Deployer(Collection builders, Collection stores, Collection watchers, Kernel kernel) {
+        this(builders, stores, watchers, getArtifactResolver(kernel), kernel);
     }
 
     private static ArtifactResolver getArtifactResolver(Kernel kernel) {
@@ -80,9 +82,10 @@
         return configurationManager.getArtifactResolver();
     }
 
-    public Deployer(Collection builders, Collection stores, ArtifactResolver artifactResolver, Kernel kernel) {
+    public Deployer(Collection builders, Collection stores, Collection watchers, ArtifactResolver artifactResolver, Kernel kernel) {
         this.builders = builders;
         this.stores = stores;
+        this.watchers = watchers;
         this.artifactResolver = artifactResolver;
         this.kernel = kernel;
 
@@ -319,6 +322,7 @@
                         store.install(configurationData);
                         deployedURIs.add(configurationData.getId().toString());
                     }
+                    notifyWatchers(deployedURIs);
                     return deployedURIs;
                 } else {
                     cleanupConfigurations(configurations);
@@ -365,6 +369,21 @@
         }
     }
 
+    private void notifyWatchers(List list) {
+        Artifact[] arts = new Artifact[list.size()];
+        for (int i = 0; i < list.size(); i++) {
+            String s = (String) list.get(i);
+            arts[i] = Artifact.create(s);
+        }
+        for (Iterator it = watchers.iterator(); it.hasNext();) {
+            DeploymentWatcher watcher = (DeploymentWatcher) it.next();
+            for (int i = 0; i < arts.length; i++) {
+                Artifact art = arts[i];
+                watcher.deployed(art);
+            }
+        }
+    }
+
     private void cleanupConfigurations(List configurations) {
         for (Iterator iterator = configurations.iterator(); iterator.hasNext();) {
             ConfigurationData configurationData = (ConfigurationData) iterator.next();
@@ -442,8 +461,9 @@
 
         infoFactory.addReference("Builders", ConfigurationBuilder.class, "ConfigBuilder");
         infoFactory.addReference("Store", ConfigurationStore.class, "ConfigurationStore");
+        infoFactory.addReference("Watchers", DeploymentWatcher.class);
 
-        infoFactory.setConstructor(new String[]{"Builders", "Store", "kernel"});
+        infoFactory.setConstructor(new String[]{"Builders", "Store", "Watchers", "kernel"});
 
         GBEAN_INFO = infoFactory.getBeanInfo();
     }

Modified: geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java (original)
+++ geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java Fri May 26 15:39:58 2006
@@ -27,7 +27,12 @@
 import org.apache.geronimo.deployment.cli.DeployUtils;
 import org.apache.geronimo.common.DeploymentException;
 import org.apache.geronimo.kernel.config.PersistentConfigurationList;
+import org.apache.geronimo.kernel.config.ConfigurationManager;
+import org.apache.geronimo.kernel.config.Configuration;
+import org.apache.geronimo.kernel.config.DeploymentWatcher;
 import org.apache.geronimo.kernel.Kernel;
+import org.apache.geronimo.kernel.repository.Artifact;
+import org.apache.geronimo.kernel.repository.MissingDependencyException;
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
@@ -47,7 +52,7 @@
  *
  * @version $Rev$ $Date$
  */
-public class DirectoryHotDeployer implements HotDeployer, GBeanLifecycle { //todo: write unit tests
+public class DirectoryHotDeployer implements HotDeployer, DeploymentWatcher, GBeanLifecycle { //todo: write unit tests
     private static final Log log = LogFactory.getLog("org.apache.geronimo.deployment.hot.Hot Deployer");
     // 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 " +
@@ -57,6 +62,7 @@
     private DirectoryMonitor monitor;
     private String path;
     private ServerInfo serverInfo;
+    private ConfigurationManager configManager;
     private int pollIntervalMillis;
     private String deploymentURI = "deployer:geronimo:inVM";
     private String deploymentUser;
@@ -66,11 +72,21 @@
     private transient TargetModuleID[] startupModules = null;
     private transient boolean serverRunning = false;
 
-    public DirectoryHotDeployer(String path, int pollIntervalMillis, ServerInfo serverInfo, Kernel kernel) {
+    public DirectoryHotDeployer(String path, int pollIntervalMillis, ServerInfo serverInfo, ConfigurationManager configManager, Kernel kernel) {
         this.path = path;
         this.serverInfo = serverInfo;
         this.pollIntervalMillis = pollIntervalMillis;
         this.kernel = kernel;
+        this.configManager = configManager;
+    }
+
+    public void deployed(Artifact id) {
+        // no action when something is deployed
+    }
+
+    public void undeployed(Artifact id) {
+        // check to see whether the artifact was hot deployed, and if so, delete it
+        monitor.removeModuleId(id);
     }
 
     public String getPath() {
@@ -195,7 +211,14 @@
     }
 
     public long getDeploymentTime(File file, String configId) {
-        return file.lastModified(); //todo: how can we find out when a module was deployed?
+        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 started() {
@@ -374,11 +397,12 @@
         infoFactory.addAttribute("deploymentUser", String.class, true, true);
         infoFactory.addAttribute("deploymentPassword", String.class, true, true);
 
+        infoFactory.addReference("ConfigManager", ConfigurationManager.class, "ConfigurationManager");
         infoFactory.addReference("ServerInfo", ServerInfo.class, "GBean");
         infoFactory.addAttribute("kernel", Kernel.class, false, false);
         infoFactory.addInterface(HotDeployer.class);
 
-        infoFactory.setConstructor(new String[]{"path", "pollIntervalMillis", "ServerInfo", "kernel"});
+        infoFactory.setConstructor(new String[]{"path", "pollIntervalMillis", "ServerInfo", "ConfigManager", "kernel"});
 
         GBEAN_INFO = infoFactory.getBeanInfo();
     }

Modified: geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java (original)
+++ geronimo/trunk/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java Fri May 26 15:39:58 2006
@@ -19,6 +19,8 @@
 import org.apache.commons.logging.LogFactory;
 import org.apache.commons.logging.Log;
 import org.apache.geronimo.deployment.cli.DeployUtils;
+import org.apache.geronimo.kernel.repository.Artifact;
+import org.apache.geronimo.kernel.config.IOUtil;
 
 import java.io.File;
 import java.io.Serializable;
@@ -29,6 +31,7 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.LinkedList;
+import java.util.Set;
 
 /**
  * Meant to be run as a Thread that tracks the contents of a directory.
@@ -107,7 +110,8 @@
     private File directory;
     private boolean done = false;
     private Listener listener; // a little cheesy, but do we really need multiple listeners?
-    private Map files = new HashMap();
+    private final Map files = new HashMap();
+    private volatile String workingOnConfigId;
 
     public DirectoryMonitor(File directory, Listener listener, int pollIntervalMillis) {
         this.directory = directory;
@@ -155,6 +159,34 @@
         this.done = true;
     }
 
+    public void removeModuleId(Artifact id) {
+        log.info("Hot deployer notified that an artifact was removed: "+id);
+        if(id.toString().equals(workingOnConfigId)) {
+            // since the redeploy process inserts a new thread to handle progress,
+            // this is called by a different thread than the hot deploy thread during
+            // a redeploy, and this check must be executed outside the synchronized
+            // block or else it will cause a deadlock!
+            return; // don't react to events we generated ourselves
+        }
+        synchronized(files) {
+            for (Iterator it = files.keySet().iterator(); it.hasNext();) {
+                String path = (String) it.next();
+                FileInfo info = (FileInfo) files.get(path);
+                Artifact target = Artifact.create(info.getConfigId());
+                if(id.matches(target)) { // 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);
+                        if(!IOUtil.recursiveDelete(file)) {
+                            log.error("Hot deployer unable to delete "+path);
+                        }
+                        it.remove();
+                    }
+                }
+            }
+        }
+    }
+
     public void run() {
         boolean serverStarted = false, initialized = false;
         while (!done) {
@@ -163,19 +195,23 @@
             } catch (InterruptedException e) {
                 continue;
             }
-            if (listener != null) {
-                if (!serverStarted && listener.isServerRunning()) {
-                    serverStarted = true;
-                }
-                if (serverStarted) {
-                    if (!initialized) {
-                        initialized = true;
-                        initialize();
-                        listener.started();
-                    } else {
-                        scanDirectory();
+            try {
+                if (listener != null) {
+                    if (!serverStarted && listener.isServerRunning()) {
+                        serverStarted = true;
+                    }
+                    if (serverStarted) {
+                        if (!initialized) {
+                            initialized = true;
+                            initialize();
+                            listener.started();
+                        } else {
+                            scanDirectory();
+                        }
                     }
                 }
+            } catch (Exception e) {
+                log.error("Error during hot deployment", e);
             }
         }
     }
@@ -196,6 +232,7 @@
                     if (listener != null) {
                         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) {
@@ -215,87 +252,93 @@
             done = true;
             return;
         }
-        HashSet oldList = new HashSet(files.keySet());
-        List actions = new LinkedList();
-        for (int i = 0; i < children.length; i++) {
-            File child = children[i];
-            if (!child.canRead()) {
-                continue;
-            }
-            FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
-            FileInfo then = (FileInfo) files.get(now.getPath());
-            if (then == null) { // Brand new, wait a bit to make sure it's not still changing
-                now.setNewFile(true);
-                files.put(now.getPath(), now);
-                log.debug("New File: " + now.getPath());
-            } else {
-                oldList.remove(then.getPath());
-                if (now.isSame(then)) { // File is the same as the last time we scanned it
-                    if (then.isChanging()) {
-                        log.debug("File finished changing: " + now.getPath());
-                        // Used to be changing, now in (hopefully) its final state
-                        if (then.isNewFile()) {
-                            actions.add(new FileAction(FileAction.NEW_FILE, child, then));
-                        } else {
-                            actions.add(new FileAction(FileAction.UPDATED_FILE, child, then));
-                        }
-                        then.setChanging(false);
-                    } // else it's just totally unchanged and we ignore it this pass
-                } else {
-                    // The two records are different -- record the latest as a file that's changing
-                    // and later when it stops changing we'll do the add or update as appropriate.
-                    now.setConfigId(then.getConfigId());
-                    now.setNewFile(then.isNewFile());
+        synchronized (files) {
+            Set oldList = new HashSet(files.keySet());
+            List actions = new LinkedList();
+            for (int i = 0; i < children.length; i++) {
+                File child = children[i];
+                if (!child.canRead()) {
+                    continue;
+                }
+                FileInfo now = child.isDirectory() ? getDirectoryInfo(child) : getFileInfo(child);
+                FileInfo then = (FileInfo) files.get(now.getPath());
+                if (then == null) { // Brand new, wait a bit to make sure it's not still changing
+                    now.setNewFile(true);
                     files.put(now.getPath(), now);
-                    log.debug("File Changed: " + now.getPath());
+                    log.debug("New File: " + now.getPath());
+                } else {
+                    oldList.remove(then.getPath());
+                    if (now.isSame(then)) { // File is the same as the last time we scanned it
+                        if (then.isChanging()) {
+                            log.debug("File finished changing: " + now.getPath());
+                            // Used to be changing, now in (hopefully) its final state
+                            if (then.isNewFile()) {
+                                actions.add(new FileAction(FileAction.NEW_FILE, child, then));
+                            } else {
+                                actions.add(new FileAction(FileAction.UPDATED_FILE, child, then));
+                            }
+                            then.setChanging(false);
+                        } // else it's just totally unchanged and we ignore it this pass
+                    } else if(then.isNewFile() || now.getModified() > then.getModified()) {
+                        // The two records are different -- record the latest as a file that's changing
+                        // and later when it stops changing we'll do the add or update as appropriate.
+                        now.setConfigId(then.getConfigId());
+                        now.setNewFile(then.isNewFile());
+                        files.put(now.getPath(), now);
+                        log.debug("File Changed: " + now.getPath());
+                    }
                 }
             }
-        }
-        // Look for any files we used to know about but didn't find in this pass
-        for (Iterator it = oldList.iterator(); it.hasNext();) {
-            String name = (String) it.next();
-            FileInfo info = (FileInfo) files.get(name);
-            log.debug("File removed: " + name);
-            if (info.isNewFile()) { // Was never added, just whack it
-                files.remove(name);
-            } else {
-                actions.add(new FileAction(FileAction.REMOVED_FILE, new File(name), info));
-            }
-        }
-        if (listener != null) {
-            // First pass: validate all changed files, so any obvious errors come out first
-            for (Iterator it = actions.iterator(); it.hasNext();) {
-                FileAction action = (FileAction) it.next();
-                if (!listener.validateFile(action.child, action.info.getConfigId())) {
-                    resolveFile(action);
-                    it.remove();
+            // Look for any files we used to know about but didn't find in this pass
+            for (Iterator it = oldList.iterator(); it.hasNext();) {
+                String name = (String) it.next();
+                FileInfo info = (FileInfo) files.get(name);
+                log.debug("File removed: " + name);
+                if (info.isNewFile()) { // Was never added, just whack it
+                    files.remove(name);
+                } else {
+                    actions.add(new FileAction(FileAction.REMOVED_FILE, new File(name), info));
                 }
             }
-            // Second pass: do what we're meant to do
-            for (Iterator it = actions.iterator(); it.hasNext();) {
-                FileAction action = (FileAction) it.next();
-                try {
-                    if (action.action == FileAction.REMOVED_FILE) {
-                        if (listener.fileRemoved(action.child, action.info.getConfigId())) {
-                            files.remove(action.child.getPath());
-                        }
-                    } else if (action.action == FileAction.NEW_FILE) {
-                        String result = listener.fileAdded(action.child);
-                        if (result != null) {
-                            if (!result.equals("")) {
-                                action.info.setConfigId(result);
-                            } else {
-                                action.info.setConfigId(calculateModuleId(action.child));
+            if (listener != null) {
+                // First pass: validate all changed files, so any obvious errors come out first
+                for (Iterator it = actions.iterator(); it.hasNext();) {
+                    FileAction action = (FileAction) 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 it = actions.iterator(); it.hasNext();) {
+                    FileAction action = (FileAction) it.next();
+                    try {
+                        if (action.action == FileAction.REMOVED_FILE) {
+                            workingOnConfigId = action.info.getConfigId();
+                            if (listener.fileRemoved(action.child, action.info.getConfigId())) {
+                                files.remove(action.child.getPath());
+                            }
+                            workingOnConfigId = null;
+                        } else if (action.action == FileAction.NEW_FILE) {
+                            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);
                             }
-                            action.info.setNewFile(false);
+                        } else if (action.action == FileAction.UPDATED_FILE) {
+                            workingOnConfigId = action.info.getConfigId();
+                            listener.fileUpdated(action.child, action.info.getConfigId());
+                            workingOnConfigId = null;
                         }
-                    } else if (action.action == FileAction.UPDATED_FILE) {
-                        listener.fileUpdated(action.child, action.info.getConfigId());
+                    } catch (Exception e) {
+                        log.error("Unable to " + action.getActionName() + " file " + action.child.getAbsolutePath(), e);
+                    } finally {
+                        resolveFile(action);
                     }
-                } catch (Exception e) {
-                    log.error("Unable to " + action.getActionName() + " file " + action.child.getAbsolutePath(), e);
-                } finally {
-                    resolveFile(action);
                 }
             }
         }

Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java (original)
+++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java Fri May 26 15:39:58 2006
@@ -43,8 +43,9 @@
             ArtifactManager artifactManager,
             ArtifactResolver artifactResolver,
             Collection repositories,
+            Collection watchers,
             ClassLoader classLoader) {
-        super(kernel, stores, attributeStore, configurationList, artifactManager, artifactResolver, repositories, classLoader);
+        super(kernel, stores, attributeStore, configurationList, artifactManager, artifactResolver, repositories, watchers, classLoader);
     }
 
     public void addGBeanToConfiguration(Artifact configurationId, GBeanData gbean, boolean start) throws InvalidConfigException {
@@ -157,7 +158,7 @@
     static {
         GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(EditableKernelConfigurationManager.class, KernelConfigurationManager.GBEAN_INFO, "ConfigurationManager");
         infoFactory.addInterface(EditableConfigurationManager.class);
-        infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList", "ArtifactManager", "ArtifactResolver", "Repositories", "classLoader"});
+        infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList", "ArtifactManager", "ArtifactResolver", "Repositories", "Watchers", "classLoader"});
         GBEAN_INFO = infoFactory.getBeanInfo();
     }
 

Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java (original)
+++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java Fri May 26 15:39:58 2006
@@ -66,11 +66,12 @@
             ArtifactManager artifactManager,
             ArtifactResolver artifactResolver,
             Collection repositories,
+            Collection watchers,
             ClassLoader classLoader) {
 
         super(stores,
                 createArtifactResolver(artifactResolver, artifactManager, repositories),
-                repositories);
+                repositories, watchers);
 
         this.kernel = kernel;
         this.attributeStore = attributeStore;
@@ -334,9 +335,10 @@
         infoFactory.addReference("ArtifactManager", ArtifactManager.class, "ArtifactManager");
         infoFactory.addReference("ArtifactResolver", ArtifactResolver.class, "ArtifactResolver");
         infoFactory.addReference("Repositories", Repository.class, "Repository");
+        infoFactory.addReference("Watchers", DeploymentWatcher.class);
         infoFactory.addAttribute("classLoader", ClassLoader.class, false);
         infoFactory.addInterface(ConfigurationManager.class);
-        infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList", "ArtifactManager", "ArtifactResolver", "Repositories", "classLoader"});
+        infoFactory.setConstructor(new String[]{"kernel", "Stores", "AttributeStore", "PersistentConfigurationList", "ArtifactManager", "ArtifactResolver", "Repositories", "Watchers", "classLoader"});
         GBEAN_INFO = infoFactory.getBeanInfo();
     }
 

Modified: geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java (original)
+++ geronimo/trunk/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java Fri May 26 15:39:58 2006
@@ -51,14 +51,21 @@
     protected final Map configurations = new LinkedHashMap();
     protected final ConfigurationModel configurationModel = new ConfigurationModel();
     protected final Collection repositories;
+    protected final Collection watchers;
 
     public SimpleConfigurationManager(Collection stores, ArtifactResolver artifactResolver, Collection repositories) {
+        this(stores, artifactResolver, repositories, Collections.EMPTY_SET);
+    }
+    
+    public SimpleConfigurationManager(Collection stores, ArtifactResolver artifactResolver, Collection repositories, Collection watchers) {
         if (stores == null) stores = Collections.EMPTY_SET;
         if (repositories == null) repositories = Collections.EMPTY_SET;
+        if (watchers == null) watchers = Collections.EMPTY_SET;
 
         this.stores = stores;
         this.artifactResolver = artifactResolver;
         this.repositories = repositories;
+        this.watchers = watchers;
     }
 
     public synchronized boolean isInstalled(Artifact configId) {
@@ -1220,6 +1227,14 @@
         }
 
         removeConfigurationFromModel(configurationId);
+        notifyWatchers(configurationId);
+    }
+
+    private void notifyWatchers(Artifact id) {
+        for (Iterator it = watchers.iterator(); it.hasNext();) {
+            DeploymentWatcher watcher = (DeploymentWatcher) it.next();
+            watcher.undeployed(id);
+        }
     }
 
     public ArtifactResolver getArtifactResolver() {

Modified: geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java
URL: http://svn.apache.org/viewvc/geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java?rev=409771&r1=409770&r2=409771&view=diff
==============================================================================
--- geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java (original)
+++ geronimo/trunk/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java Fri May 26 15:39:58 2006
@@ -731,6 +731,7 @@
                 artifactManager,
                 artifactResolver,
                 Collections.singleton(testRepository),
+                Collections.EMPTY_SET,
                 KernelConfigurationManager.class.getClassLoader());
     }