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:00:23 UTC

svn commit: r409761 - in /geronimo/branches/1.1: 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/g...

Author: ammulder
Date: Fri May 26 15:00:23 2006
New Revision: 409761

URL: http://svn.apache.org/viewvc?rev=409761&view=rev
Log:
Fixes to hot deployer
 - If you deploy with the hot deploy dir and then undeploy with the
   console or CLI, delete the file from the hot deploy dir so the
   hot deployer doesn't get confused (GERONIMO-1431)
 - If file in hot deploy dir is updated while server is down,
   redeploy it when the server starts up again (GERONIMO-1174)

Added:
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java   (with props)
Modified:
    geronimo/branches/1.1/configs/geronimo-gbean-deployer/src/plan/plan.xml
    geronimo/branches/1.1/configs/hot-deployer/src/plan/plan.xml
    geronimo/branches/1.1/configs/j2ee-system/src/plan/plan.xml
    geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java
    geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
    geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java
    geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java
    geronimo/branches/1.1/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java

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

Modified: geronimo/branches/1.1/configs/hot-deployer/src/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/configs/hot-deployer/src/plan/plan.xml?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/configs/hot-deployer/src/plan/plan.xml (original)
+++ geronimo/branches/1.1/configs/hot-deployer/src/plan/plan.xml Fri May 26 15:00:23 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/branches/1.1/configs/j2ee-system/src/plan/plan.xml
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/configs/j2ee-system/src/plan/plan.xml?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/configs/j2ee-system/src/plan/plan.xml (original)
+++ geronimo/branches/1.1/configs/j2ee-system/src/plan/plan.xml Fri May 26 15:00:23 2006
@@ -72,6 +72,8 @@
     </reference>
     <reference name="Stores">
     </reference>
+    <reference name="Watchers">
+    </reference>
     <reference name="AttributeStore">
       <name>AttributeManager</name>
     </reference>

Modified: geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java (original)
+++ geronimo/branches/1.1/modules/deployment/src/java/org/apache/geronimo/deployment/Deployer.java Fri May 26 15:00:23 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/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java (original)
+++ geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryHotDeployer.java Fri May 26 15:00:23 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/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java (original)
+++ geronimo/branches/1.1/modules/hot-deploy/src/java/org/apache/geronimo/deployment/hot/DirectoryMonitor.java Fri May 26 15:00:23 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);
                 }
             }
         }

Added: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java?rev=409761&view=auto
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java (added)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java Fri May 26 15:00:23 2006
@@ -0,0 +1,29 @@
+/**
+ *
+ * Copyright 2005 The Apache Software Foundation
+ *
+ *  Licensed 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.kernel.config;
+
+import org.apache.geronimo.kernel.repository.Artifact;
+
+/**
+ * Interface for receiving deployment notifications
+ *
+ * @version $Rev: 46019 $ $Date: 2004-09-14 05:56:06 -0400 (Tue, 14 Sep 2004) $
+ */
+public interface DeploymentWatcher {
+    void deployed(Artifact id);
+    void undeployed(Artifact id);
+}

Propchange: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/DeploymentWatcher.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/EditableKernelConfigurationManager.java Fri May 26 15:00:23 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/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/KernelConfigurationManager.java Fri May 26 15:00:23 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/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/java/org/apache/geronimo/kernel/config/SimpleConfigurationManager.java Fri May 26 15:00:23 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/branches/1.1/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java
URL: http://svn.apache.org/viewvc/geronimo/branches/1.1/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java?rev=409761&r1=409760&r2=409761&view=diff
==============================================================================
--- geronimo/branches/1.1/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java (original)
+++ geronimo/branches/1.1/modules/kernel/src/test/org/apache/geronimo/kernel/config/ConfigurationManagerTest.java Fri May 26 15:00:23 2006
@@ -731,6 +731,7 @@
                 artifactManager,
                 artifactResolver,
                 Collections.singleton(testRepository),
+                Collections.EMPTY_SET,
                 KernelConfigurationManager.class.getClassLoader());
     }