[jboss-cvs] JBossAS SVN: r78966 - in projects/naming/trunk/jnpserver/src: main/java/org/jnp/server and 3 other directories.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Tue Sep 30 14:23:15 EDT 2008


Author: scott.stark at jboss.org
Date: 2008-09-30 14:23:14 -0400 (Tue, 30 Sep 2008)
New Revision: 78966

Added:
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingEvents.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListenerInfo.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListeners.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventMgr.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/ExecutorEventMgr.java
   projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/NamingEventsUnitTest.java
   projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/support/
   projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/support/QueueEventListener.java
Modified:
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/Naming.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingBeanImpl.java
   projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingServer.java
   projects/naming/trunk/jnpserver/src/test/resources/log4j.xml
Log:
JBNAME-13, Initial implementation of local only EventContext

Modified: projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/Naming.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/Naming.java	2008-09-30 17:40:08 UTC (rev 78965)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/Naming.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -31,10 +31,10 @@
 import javax.naming.NamingException;
 
 /**
- *   <description> 
+ *   The naming server/proxy interface
  *      
  *   @see <related>
- *   @author $Author$
+ *   @author Scott.Stark at jboss.org
  *   @version $Revision$
  */
 public interface Naming

Modified: projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java	2008-09-30 17:40:08 UTC (rev 78965)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingContext.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -442,6 +442,10 @@
       return serverInfo;
    }
 
+   public Naming getLocal()
+   {
+      return localServer;
+   }
    public static void setLocal(Naming server)
    {
       localServer = server;
@@ -1211,29 +1215,41 @@
    public void addNamingListener(Name target, int scope, NamingListener l)
       throws NamingException
    {
-      // TODO Auto-generated method stub
-      throw new UnsupportedOperationException("This is not supported currently");
+      if((naming instanceof NamingEvents) == false)
+      {
+         throw new UnsupportedOperationException("Naming implementation does not support NamingExt");
+      }
+      NamingEvents next = (NamingEvents) naming;
+      next.addNamingListener(this, target, scope, l);
    }
 
    public void addNamingListener(String target, int scope, NamingListener l)
       throws NamingException
    {
-      // TODO Auto-generated method stub
-      throw new UnsupportedOperationException("This is not supported currently");      
+      Name targetName = parser.parse(target);
+      addNamingListener(targetName, scope, l);
    }
 
    public void removeNamingListener(NamingListener l)
       throws NamingException
    {
-      // TODO Auto-generated method stub
-      throw new UnsupportedOperationException("This is not supported currently");
+      if((naming instanceof NamingEvents) == false)
+      {
+         throw new UnsupportedOperationException("Naming implementation does not support NamingExt");
+      }
+      NamingEvents next = (NamingEvents) naming;
+      next.removeNamingListener(l);
    }
 
    public boolean targetMustExist()
       throws NamingException
    {
-      // TODO Auto-generated method stub
-      return false;
+      if((naming instanceof NamingEvents) == false)
+      {
+         throw new UnsupportedOperationException("Naming implementation does not support NamingExt");
+      }
+      NamingEvents next = (NamingEvents) naming;
+      return next.targetMustExist();
    }
    // End EventContext methods
 

Added: projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingEvents.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingEvents.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/interfaces/NamingEvents.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,72 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.interfaces;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingListener;
+
+/**
+ * An extended naming server/proxy that support events
+ * @see javax.naming.event.EventContext
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public interface NamingEvents extends Naming
+{
+   /**
+    * Adds a listener for receiving naming events fired
+    * when the object(s) identified by a target and scope changes.
+    *
+    * @param context - the non-null EventContext the listener is registering with
+    * @param target A non-null name to be resolved relative to this context.
+    * @param scope One of <tt>OBJECT_SCOPE</tt>, <tt>ONELEVEL_SCOPE</tt>, or
+    * <tt>SUBTREE_SCOPE</tt>.
+    * @param l  The non-null listener.
+    * @exception NamingException If a problem was encountered while
+    * adding the listener.
+    * @see #removeNamingListener
+    */
+   void addNamingListener(EventContext context, Name target, int scope, NamingListener l) 
+      throws NamingException;
+
+   /**
+    * Removes a listener from receiving naming events
+    * @param l non-null listener.
+    * @exception NamingException If a problem was encountered while
+    * removing the listener.
+    * @see #addNamingListener
+    */
+   void removeNamingListener(NamingListener l) throws NamingException;
+
+   /**
+    * Determines whether a listener can register interest in a target
+    * that does not exist.
+    *
+    * @return true if the target must exist; false if the target need not exist.
+    * @exception NamingException If the context's behavior in this regard cannot
+    * be determined.
+    */
+   boolean targetMustExist() throws NamingException;
+}

Added: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListenerInfo.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListenerInfo.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListenerInfo.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,123 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.server;
+
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.NamingListener;
+import javax.naming.event.ObjectChangeListener;
+
+/**
+ * Encapsulation of the NamingListener, scope and EventContext the listener
+ * registered with.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class EventListenerInfo
+   implements NamespaceChangeListener, ObjectChangeListener
+{
+   private NamingListener listener;
+   private String fullTargetName;
+   private int scope;
+
+   public EventListenerInfo(NamingListener listener, String fullTargetName, int scope)
+   {
+      super();
+      this.listener = listener;
+      this.fullTargetName = fullTargetName;
+      this.scope = scope;
+   }
+
+   public NamingListener getListener()
+   {
+      return listener;
+   }
+
+   public String getFullTargetName()
+   {
+      return fullTargetName;
+   }
+
+   public int getScope()
+   {
+      return scope;
+   }
+
+   public boolean isNamespaceChangeListener()
+   {
+      return listener instanceof NamespaceChangeListener;
+   }
+   public boolean isObjectChangeListener()
+   {
+      return listener instanceof ObjectChangeListener;
+   }
+
+   
+   public void objectChanged(NamingEvent evt)
+   {
+      ObjectChangeListener ocl = (ObjectChangeListener) listener;
+      ocl.objectChanged(evt);
+   }
+
+   public void objectAdded(NamingEvent evt)
+   {
+      NamespaceChangeListener ncl = (NamespaceChangeListener) listener;
+      ncl.objectAdded(evt);
+   }
+
+   public void objectRemoved(NamingEvent evt)
+   {
+      NamespaceChangeListener ncl = (NamespaceChangeListener) listener;
+      ncl.objectAdded(evt);
+   }
+
+   public void objectRenamed(NamingEvent evt)
+   {
+      NamespaceChangeListener ncl = (NamespaceChangeListener) listener;
+      ncl.objectAdded(evt);
+   }
+
+   public void namingExceptionThrown(NamingExceptionEvent evt)
+   {
+      listener.namingExceptionThrown(evt);
+   }
+
+   @Override
+   public boolean equals(Object obj)
+   {
+      boolean equals = false;
+      if(obj instanceof EventListenerInfo)
+      {
+         EventListenerInfo eli = (EventListenerInfo) obj;
+         equals = listener.equals(eli.listener);
+      }
+      return equals;
+   }
+
+   @Override
+   public int hashCode()
+   {
+      return listener.hashCode();
+   }
+}

Added: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListeners.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListeners.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventListeners.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,139 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.server;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArrayList;
+
+import javax.naming.Binding;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingListener;
+import javax.naming.event.ObjectChangeListener;
+
+import org.jboss.logging.Logger;
+
+/**
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class EventListeners
+{
+   private static Logger log = Logger.getLogger(EventListeners.class);
+   private EventContext context;
+   private CopyOnWriteArrayList<EventListenerInfo> listeners;
+   private boolean trace;
+
+   public EventListeners(EventContext context)
+   {
+      super();
+      this.context = context;
+      this.trace = log.isTraceEnabled();
+   }
+
+   public synchronized void addNamingListener(EventContext context, Name target, int scope, NamingListener l) 
+      throws NamingException
+   {
+      if(listeners == null)
+         listeners = new CopyOnWriteArrayList<EventListenerInfo>();
+      this.context = context;
+      String prefix = context.getNameInNamespace();
+      String fullTargetName = prefix + target.toString();
+      EventListenerInfo info = new EventListenerInfo(l, fullTargetName, scope);
+      listeners.add(info);
+   }
+   public void removeNamingListener(NamingListener l)
+   {
+      if(listeners == null)
+         return;
+
+      EventListenerInfo info = new EventListenerInfo(l, null, 0);
+      listeners.remove(info);
+   }
+   public void fireEvent(Name fullName, Binding oldb, Binding newb, int type,
+         String changeInfo, Set<Integer> scopes)
+   {
+      if(listeners != null)
+      {
+         if(trace)
+         {
+            log.trace("fireEvent, fullName:"+fullName+" type: "+type
+                  +", changeInfo:"+changeInfo+", scopes:"+scopes);
+         }
+         String name = fullName.toString();
+         NamingEvent event = new NamingEvent(context, type, newb, oldb, changeInfo);
+         for(EventListenerInfo info : listeners)
+         {
+            if(scopes.contains(info.getScope()))
+            {
+               String targetName = info.getFullTargetName();
+               int scope = info.getScope();
+               boolean matches = false;
+               if(scope == EventContext.SUBTREE_SCOPE)
+               {
+                  // SUBTREE_SCOPE matches the target or subcontext
+                  matches = name.startsWith(targetName);
+               }
+               else if(scope == EventContext.ONELEVEL_SCOPE)
+               {
+                  // ONELEVEL_SCOPE matches immediate children of the context
+                  matches = fullName.size() == 1;
+               }
+               else
+                  matches = name.equals(targetName);
+               if(matches)
+                  dispatch(info.getListener(), event);
+            }
+         }
+      }
+   }
+   public void dispatch(NamingListener listener, NamingEvent event)
+   {
+      switch (event.getType())
+      {
+      case NamingEvent.OBJECT_ADDED:
+         if(listener instanceof NamespaceChangeListener)
+          ((NamespaceChangeListener)listener).objectAdded(event);
+          break;
+
+      case NamingEvent.OBJECT_REMOVED:
+         if(listener instanceof NamespaceChangeListener)
+          ((NamespaceChangeListener)listener).objectRemoved(event);
+          break;
+
+      case NamingEvent.OBJECT_RENAMED:
+         if(listener instanceof NamespaceChangeListener)
+          ((NamespaceChangeListener)listener).objectRenamed(event);
+          break;
+
+      case NamingEvent.OBJECT_CHANGED:
+         if(listener instanceof ObjectChangeListener)
+          ((ObjectChangeListener)listener).objectChanged(event);
+          break;
+      }
+   }
+
+}

Added: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventMgr.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventMgr.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/EventMgr.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,37 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.server;
+
+import java.util.Set;
+
+import javax.naming.Binding;
+import javax.naming.Name;
+
+/**
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public interface EventMgr
+{
+   void fireEvent(Name fullName, Binding oldb, Binding newb, int type,
+         String changeInfo, EventListeners listeners, Set<Integer> scopes);
+}

Added: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/ExecutorEventMgr.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/ExecutorEventMgr.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/ExecutorEventMgr.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,93 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.server;
+
+import java.util.List;
+import java.util.Set;
+import java.util.concurrent.Executor;
+import java.util.concurrent.Executors;
+
+import javax.naming.Binding;
+import javax.naming.Name;
+import javax.naming.event.NamingEvent;
+
+import org.jboss.logging.Logger;
+/**
+ * An EventMgr implementation that uses an Executor to dispatch the events
+ * in the background.
+ * 
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class ExecutorEventMgr implements EventMgr
+{
+   private static Logger log = Logger.getLogger(ExecutorEventMgr.class);
+   private Executor executor = Executors.newSingleThreadExecutor();
+
+   public ExecutorEventMgr()
+   {
+   }
+
+   public Executor getExecutor()
+   {
+      return executor;
+   }
+   public void setExecutor(Executor executor)
+   {
+      this.executor = executor;
+   }
+
+   public void fireEvent(Name fullName, Binding oldb, Binding newb, int type,
+         String changeInfo, EventListeners listeners, Set<Integer> scopes)
+   {
+      Dispatcher d = new Dispatcher(fullName, newb, oldb, type,
+            changeInfo, listeners, scopes);
+      executor.execute(d);
+   }
+
+   static class Dispatcher implements Runnable
+   {
+      Name fullName;
+      Binding oldb;
+      Binding newb;
+      int type;
+      String changeInfo;
+      EventListeners listeners;
+      Set<Integer> scopes;
+
+      public Dispatcher(Name fullName, Binding newb, Binding oldb, int type,
+           String changeInfo, EventListeners listeners, Set<Integer> scopes)
+      {
+         this.fullName = fullName;
+         this.newb = newb;
+         this.oldb = oldb;
+         this.type = type;
+         this.listeners = listeners;
+         this.changeInfo = changeInfo;
+         this.scopes = scopes;
+      }
+      public void run()
+      {
+         listeners.fireEvent(fullName, oldb, newb, type, changeInfo, scopes);
+      }
+   }
+ }

Modified: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingBeanImpl.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingBeanImpl.java	2008-09-30 17:40:08 UTC (rev 78965)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingBeanImpl.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -53,6 +53,7 @@
    protected boolean InstallGlobalService = true;
    /** A flag indicating if theServer will try to use the NamingContext.setLocal value */
    protected boolean UseGlobalService = true;
+   private EventMgr eventMgr;
 
    // Static --------------------------------------------------------
    public static void main(String[] args)
@@ -89,6 +90,15 @@
       this.UseGlobalService = flag;
    }
 
+   public EventMgr getEventMgr()
+   {
+      return eventMgr;
+   }
+   public void setEventMgr(EventMgr eventMgr)
+   {
+      this.eventMgr = eventMgr;
+   }
+
    /**
     * Util method for possible override.
     *
@@ -97,9 +107,13 @@
     */
    protected Naming createServer() throws Exception
    {
-      return new NamingServer();
+      return new NamingServer(null, null, eventMgr);
    }
-   
+
+   /**
+    * 
+    * @throws Exception
+    */
    public void start()
       throws Exception
    {
@@ -162,7 +176,12 @@
       iniCtx.close();
    }
 
+   /**
+    * Clear the NamingContext local server if its our theSever value
+    */
    public void stop()
    {
+      if(NamingContext.localServer == theServer)
+         NamingContext.setLocal(null);
    }
 }

Modified: projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingServer.java
===================================================================
--- projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingServer.java	2008-09-30 17:40:08 UTC (rev 78965)
+++ projects/naming/trunk/jnpserver/src/main/java/org/jnp/server/NamingServer.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -21,11 +21,14 @@
   */
 package org.jnp.server;
 
+import java.util.ArrayList;
 import java.util.Collection;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Vector;
 import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.CopyOnWriteArrayList;
 import javax.naming.Binding;
 import javax.naming.CannotProceedException;
 import javax.naming.Context;
@@ -37,15 +40,19 @@
 import javax.naming.NamingException;
 import javax.naming.NotContextException;
 import javax.naming.Reference;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingListener;
 import javax.naming.spi.ResolveResult;
 
 import org.jboss.logging.Logger;
 import org.jnp.interfaces.Naming;
 import org.jnp.interfaces.NamingContext;
+import org.jnp.interfaces.NamingEvents;
 import org.jnp.interfaces.NamingParser;
 
 /**
- * The JNDI naming server implementation class.
+ * The in memory JNDI naming server implementation class.
  * 
  * @author Rickard Oberg
  * @author patriot1burke
@@ -53,7 +60,7 @@
  * @version $Revision$
  */
 public class NamingServer
-   implements Naming, java.io.Serializable
+   implements Naming, NamingEvents, java.io.Serializable
 {
    private static Logger log = Logger.getLogger(NamingServer.class);
 
@@ -62,11 +69,16 @@
    // Constants -----------------------------------------------------
 
    // Attributes ----------------------------------------------------
-   
-   protected Map table = createTable();
+   /** */
+   protected Map<String, Binding> table = createTable();
    protected Name prefix;
    protected NamingParser parser = new NamingParser();
    protected NamingServer parent;
+   /** The NamingListeners registered with this context */
+   private EventListeners listeners;
+   /** The manager for EventContext listeners */
+   private EventMgr eventMgr;
+   private boolean trace;
 
    // Static --------------------------------------------------------
 
@@ -81,33 +93,50 @@
    public NamingServer(Name prefix, NamingServer parent)
       throws NamingException
    {
+      this(null, null, null);   
+   }
+   public NamingServer(Name prefix, NamingServer parent, EventMgr eventMgr)
+      throws NamingException
+   {
       if (prefix == null)
          prefix = parser.parse("");
       this.prefix = prefix;      
       this.parent = parent;
+      this.eventMgr = eventMgr;
+      this.trace = log.isTraceEnabled();
    }
 
-   // Protected -----------------------------------------------------
 
-   protected Map createTable()
+   // Public --------------------------------------------------------
+
+   // NamingListener registration
+   public synchronized void addNamingListener(EventContext context, Name target, int scope, NamingListener l) 
+      throws NamingException
    {
-      return new ConcurrentHashMap();  
+      if(listeners == null)
+         listeners = new EventListeners(context);
+      if(trace)
+         log.trace("addNamingListener, target: "+target+", scope: "+scope);
+      listeners.addNamingListener(context, target, scope, l);
    }
 
-   /**
-    * Create sub naming.
-    *
-    * @param prefix the prefix
-    * @param parent the parent naming server
-    * @return new sub instance
-    * @throws NamingException for any error
-    */
-   protected NamingServer createNamingServer(Name prefix, NamingServer parent) throws NamingException
+   public void removeNamingListener(NamingListener l) throws NamingException
    {
-      return new NamingServer(prefix, parent);
+      if(listeners != null)
+      {
+         listeners.removeNamingListener(l);
+      }
    }
 
-   // Public --------------------------------------------------------
+    /**
+     * We don't need targets to exist?
+     * @return false
+     * @throws NamingException
+     */
+    public boolean targetMustExist() throws NamingException
+    {
+       return false;
+    }
 
    // Naming implementation -----------------------------------------
    public synchronized void bind(Name name, Object obj, String className)
@@ -116,8 +145,9 @@
       if (name.isEmpty())
       {
          // Empty names are not allowed
-         throw new InvalidNameException();
-      } else if (name.size() > 1) 
+         throw new InvalidNameException("An empty name cannot be passed to bind");
+      }
+      else if (name.size() > 1) 
       {
          // Recurse to find correct context
 //         System.out.println("bind#"+name+"#");
@@ -127,8 +157,10 @@
          {
             if (ctx instanceof NamingServer)
             {
-               ((NamingServer)ctx).bind(name.getSuffix(1),obj, className);
-            } else if (ctx instanceof Reference)
+               NamingServer ns = (NamingServer) ctx;
+               ns.bind(name.getSuffix(1),obj, className);
+            }
+            else if (ctx instanceof Reference)
             {
                // Federation
                if (((Reference)ctx).get("nns") != null)
@@ -137,35 +169,47 @@
                   cpe.setResolvedObj(ctx);
                   cpe.setRemainingName(name.getSuffix(1));
                   throw cpe;
-               } else
+               }
+               else
                {
                   throw new NotContextException();
                }
-            } else
+            }
+            else
             {
                throw new NotContextException();
             }
-         } else
+         }
+         else
          {
-            throw new NameNotFoundException();
+            throw new NameNotFoundException(name.toString()+" in: "+prefix);
          }
-      } else
+      }
+      else
       {
          // Bind object
          if (name.get(0).equals(""))
          {
-            throw new InvalidNameException();
-         } else
+            throw new InvalidNameException("An empty name cannot be passed to bind");
+         }
+         else
          {
-//            System.out.println("bind "+name+"="+obj);
+            if(trace)
+               log.trace("bind "+name+"="+obj+", "+className);
             try
             {
                getBinding(name);
                // Already bound
-               throw new NameAlreadyBoundException();
-            } catch (NameNotFoundException e)
+               throw new NameAlreadyBoundException(name.toString());
+            }
+            catch (NameNotFoundException e)
             {
-               setBinding(name,obj,className);
+               Binding newb = setBinding(name,obj,className);
+               // Notify event listeners
+               Binding oldb = null;
+               Name fullName = (Name) prefix.clone();
+               fullName.addAll(name);
+               this.fireEvent(fullName, oldb, newb, NamingEvent.OBJECT_ADDED, "bind");
             }
          }
       }
@@ -177,8 +221,9 @@
       if (name.isEmpty())
       {
          // Empty names are not allowed
-         throw new InvalidNameException();
-      } else if (name.size() > 1) 
+         throw new InvalidNameException("An empty name cannot be passed to rebind");
+      }
+      else if (name.size() > 1) 
       {
          // Recurse to find correct context
 //         System.out.println("rebind#"+name+"#");
@@ -187,7 +232,8 @@
          if (ctx instanceof NamingServer)
          {
             ((NamingServer)ctx).rebind(name.getSuffix(1),obj, className);
-         } else if (ctx instanceof Reference)
+         }
+         else if (ctx instanceof Reference)
          {
             // Federation
             if (((Reference)ctx).get("nns") != null)
@@ -196,24 +242,39 @@
                cpe.setResolvedObj(ctx);
                cpe.setRemainingName(name.getSuffix(1));
                throw cpe;
-            } else
+            }
+            else
             {
                throw new NotContextException();
             }
-         } else
+         }
+         else
          {
             throw new NotContextException();
          }
-      } else
+      }
+      else
       {
          // Bind object
          if (name.get(0).equals(""))
          {
-            throw new InvalidNameException();
-         } else
+            throw new InvalidNameException("An empty name cannot be passed to rebind");
+         }
+         else
          {
-//            System.out.println("rebind "+name+"="+obj+"("+this+")");
-            setBinding(name,obj,className);
+            String comp = name.get(0);
+            Binding oldb = table.get(comp);
+            Binding newb = setBinding(name,obj,className);
+            // Notify event listeners
+            if(listeners != null)
+            {
+               int type = NamingEvent.OBJECT_CHANGED;
+               if(oldb == null)
+                  type = NamingEvent.OBJECT_ADDED;
+               Name fullName = (Name) prefix.clone();
+               fullName.add(comp);
+               this.fireEvent(fullName, oldb, newb, type, "rebind");
+            }
          }
       }
    }
@@ -225,7 +286,8 @@
       {
          // Empty names are not allowed
          throw new InvalidNameException();
-      } else if (name.size() > 1) 
+      }
+      else if (name.size() > 1) 
       {
          // Recurse to find correct context
 //         System.out.println("unbind#"+name+"#");
@@ -234,7 +296,8 @@
          if (ctx instanceof NamingServer)
          {
             ((NamingServer)ctx).unbind(name.getSuffix(1));
-         } else if (ctx instanceof Reference)
+         }
+         else if (ctx instanceof Reference)
          {
             // Federation
             if (((Reference)ctx).get("nns") != null)
@@ -243,11 +306,13 @@
                cpe.setResolvedObj(ctx);
                cpe.setRemainingName(name.getSuffix(1));
                throw cpe;
-            } else
+            }
+            else
             {
                throw new NotContextException();
             }
-         } else
+         }
+         else
          {
             throw new NotContextException();
          }
@@ -257,13 +322,24 @@
          if (name.get(0).equals(""))
          {
             throw new InvalidNameException();
-         } else
+         }
+         else
          {
 //            System.out.println("unbind "+name+"="+getBinding(name));
             if (getBinding(name) != null)
             {
-               removeBinding(name);
-            } else
+               Binding newb = null;
+               Binding oldb = removeBinding(name);
+               // Notify event listeners
+               if(listeners != null)
+               {
+                  int type = NamingEvent.OBJECT_REMOVED;
+                  Name fullName = (Name) prefix.clone();
+                  fullName.addAll(name);
+                  this.fireEvent(fullName, oldb, newb, type, "unbind");
+               }
+            }
+            else
             {
                throw new NameNotFoundException();
             }
@@ -333,31 +409,26 @@
    public Collection list(Name name)
       throws NamingException
    {
-//      System.out.println("list of #"+name+"#"+name.size());
       if (name.isEmpty())
-      {
-//         System.out.println("list "+name);
-         
-         Vector list = new Vector();
-         Iterator iter = table.entrySet().iterator();
-         while(iter.hasNext())
+      {  
+         ArrayList<NameClassPair> list = new ArrayList<NameClassPair>();
+         for(Map.Entry<String, Binding> entry : table.entrySet())
          {
-            Map.Entry entry = (Map.Entry)iter.next();
             String key = (String)entry.getKey();
             Binding b = (Binding)entry.getValue();
-
-            list.addElement(new NameClassPair(b.getName(),b.getClassName(),true));
+            NameClassPair ncp = new NameClassPair(b.getName(),b.getClassName(), true);
+            list.add(ncp);
          }
          return list;
-      } else
-      {
-//         System.out.println("list#"+name+"#");
-         
+      }
+      else
+      {  
          Object ctx = getObject(name);
          if (ctx instanceof NamingServer)
          {
             return ((NamingServer)ctx).list(name.getSuffix(1));
-         } else if (ctx instanceof Reference)
+         }
+         else if (ctx instanceof Reference)
          {
             // Federation
             if (((Reference)ctx).get("nns") != null)
@@ -494,13 +565,21 @@
             Name fullName = (Name) prefix.clone();
             fullName.addAll(name);
             NamingServer subContext = createNamingServer(fullName, this);
+            subCtx = new NamingContext(null, fullName, getRoot());
             setBinding(name, subContext, NamingContext.class.getName());
-            subCtx = new NamingContext(null, fullName, getRoot());
+            // Return the NamingContext as the binding value
+            Binding newb = new Binding(name.toString(), NamingContext.class.getName(), subCtx, true);
+            // Notify event listeners
+            if(listeners != null)
+            {
+               Binding oldb = null;
+               this.fireEvent(fullName, oldb, newb, NamingEvent.OBJECT_ADDED, "createSubcontext");
+            }
          }
       }
       return subCtx;
    }
-      
+
    public Naming getRoot()
    {
       if (parent == null)
@@ -514,13 +593,72 @@
    // Package protected ---------------------------------------------
     
    // Protected -----------------------------------------------------
-    
+
+   protected Map<String, Binding> createTable()
+   {
+      return new ConcurrentHashMap<String, Binding>();  
+   }
+
+   /**
+    * Create sub naming.
+    *
+    * @param prefix the prefix
+    * @param parent the parent naming server
+    * @return new sub instance
+    * @throws NamingException for any error
+    */
+   protected NamingServer createNamingServer(Name prefix, NamingServer parent)
+      throws NamingException
+   {
+      return new NamingServer(prefix, parent, eventMgr);
+   }
+
+   protected void fireEvent(Name fullName, Binding oldb, Binding newb, int type,
+         String changeInfo)
+      throws NamingException
+   {
+      if(eventMgr == null)
+      {
+         if(trace)
+            log.trace("Skipping event dispatch because there is no EventMgr");
+         return;
+      }
+
+      if(listeners != null)
+      {
+         if(trace)
+            log.trace("fireEvent, type: "+type+", fullName: "+fullName);
+         HashSet<Integer> scopes = new HashSet<Integer>();
+         scopes.add(EventContext.OBJECT_SCOPE);
+         scopes.add(EventContext.ONELEVEL_SCOPE);
+         scopes.add(EventContext.SUBTREE_SCOPE);
+         eventMgr.fireEvent(fullName, oldb, newb, type, changeInfo, listeners, scopes);
+      }
+      else if(trace)
+      {
+         log.trace("fireEvent, type: "+type+", fullName: "+fullName);
+      }
+      // Traverse to parent for SUBTREE_SCOPE
+      HashSet<Integer> scopes = new HashSet<Integer>();
+      scopes.add(EventContext.SUBTREE_SCOPE);
+      NamingServer nsparent = parent;
+      while(nsparent != null)
+      {
+         if(nsparent.listeners != null)
+         {
+            eventMgr.fireEvent(fullName, oldb, newb, type, changeInfo, nsparent.listeners, scopes);
+            nsparent = nsparent.parent;
+         }
+      }
+   }
+
    // Private -------------------------------------------------------
-   private void setBinding(Name name, Object obj, String className)
+   private Binding setBinding(Name name, Object obj, String className)
    {
       String n = name.toString();
-      table.put(n, new Binding(n, className, obj, true));
-      if( log.isTraceEnabled() )
+      Binding b = new Binding(n, className, obj, true);
+      table.put(n, b);
+      if( trace )
       {
          StringBuffer tmp = new StringBuffer(super.toString());
          tmp.append(", setBinding: name=");
@@ -531,12 +669,13 @@
          tmp.append(className);
          log.trace(tmp.toString());
       }
+      return b;
    }
 
    private Binding getBinding(String key)
       throws NameNotFoundException
    {
-      Binding b = (Binding)table.get(key);
+      Binding b = table.get(key);
       if (b == null)
       {
          if( log.isTraceEnabled() )
@@ -547,10 +686,10 @@
             tmp.append(" in context ");
             tmp.append(this.prefix);
             tmp.append(", bindings:\n");
-            Iterator bindings = table.values().iterator();
+            Iterator<Binding> bindings = table.values().iterator();
             while( bindings.hasNext() )
             {
-               Binding value = (Binding) bindings.next();
+               Binding value = bindings.next();
                tmp.append(value.getName());
                tmp.append('=');
                if( value.getObject() != null )
@@ -578,9 +717,9 @@
       return getBinding(key).getObject();
    }
 
-   private void removeBinding(Name name)
+   private Binding removeBinding(Name name)
    {
-      table.remove(name.get(0));
+      return table.remove(name.get(0));
    }
    
 }

Added: projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/NamingEventsUnitTest.java
===================================================================
--- projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/NamingEventsUnitTest.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/NamingEventsUnitTest.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,177 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.test;
+
+import java.io.IOException;
+import java.util.Properties;
+
+import javax.naming.Binding;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.event.EventContext;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingListener;
+
+import org.jnp.interfaces.MarshalledValuePair;
+import org.jnp.server.ExecutorEventMgr;
+import org.jnp.server.NamingBeanImpl;
+import org.jnp.test.TestJNPSockets.ClientSocketFactory;
+import org.jnp.test.TestJNPSockets.ServerSocketFactory;
+import org.jnp.test.support.QueueEventListener;
+
+import junit.framework.TestCase;
+
+/**
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class NamingEventsUnitTest extends TestCase
+{
+   /** The actual namingMain service impl bean */
+   private static NamingBeanImpl namingBean;
+   private QueueEventListener listener = new QueueEventListener();
+
+   @Override
+   protected void setUp() throws Exception
+   {
+      namingBean = new NamingBeanImpl();
+      namingBean.setInstallGlobalService(true);
+      namingBean.setEventMgr(new ExecutorEventMgr());
+      namingBean.start();
+   }
+   
+   @Override
+   protected void tearDown() throws Exception
+   {
+      namingBean.stop();
+      super.tearDown();
+   }
+
+   public void testAddRemoveOneLevel() throws Exception
+   {
+      Properties env = new Properties();
+      env.setProperty("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
+      env.setProperty("java.naming.factory.url.pkgs", "org.jnp.interfaces");
+      InitialContext ic = new InitialContext(env);
+      System.out.println("Created InitialContext");
+      Context ctx = (Context) ic.lookup("");
+      assertTrue("Context is an EventContext", ctx instanceof EventContext);
+      EventContext ectx = (EventContext) ctx;
+      ectx.addNamingListener("", EventContext.ONELEVEL_SCOPE, listener);
+      System.out.println("Added NamingListener");
+      ctx.bind("testAddObject", "testAddObject.bind");
+      assertTrue("Saw bind event", listener.waitOnEvent());
+      NamingEvent event = listener.getEvent(0);
+      assertEquals("OBJECT_ADDED", NamingEvent.OBJECT_ADDED, event.getType());
+      assertNull("getOldBinding", event.getOldBinding());      
+      assertEquals("testAddObject.bind", getValue(event.getNewBinding()));
+
+      ctx.rebind("testAddObject", "testAddObject.rebind");
+      assertTrue("Saw rebind event", listener.waitOnEvent());
+      event = listener.getEvent(1);
+      assertEquals("OBJECT_CHANGED", NamingEvent.OBJECT_CHANGED, event.getType());
+      assertEquals("testAddObject.bind", getValue(event.getOldBinding()));
+      assertEquals("testAddObject.rebind", getValue(event.getNewBinding()));
+
+      ctx.unbind("testAddObject");
+      assertTrue("Saw unbind event", listener.waitOnEvent());
+      event = listener.getEvent(2);
+      assertEquals("OBJECT_REMOVED", NamingEvent.OBJECT_REMOVED, event.getType());
+      assertEquals("testAddObject.rebind", getValue(event.getOldBinding()));
+      assertNull("getNewBinding", event.getNewBinding());
+
+      // Create a subcontext
+      Context subctx = ctx.createSubcontext("subctx");
+      listener.waitOnEvent();
+      assertEquals("Should be 4 events", 4, listener.getEventCount());
+      event = listener.getEvent(3);
+      assertEquals("OBJECT_ADDED", NamingEvent.OBJECT_ADDED, event.getType());
+      assertNull("getOldBinding", event.getOldBinding());      
+      assertEquals("getNewBinding", subctx, getValue(event.getNewBinding()));
+
+      // Creating a binding under subctx should not produce an event
+      subctx.bind("subctx.testAddObject", "testAddObject.subctx.bind");
+      assertFalse("Wait on subctx bind", listener.waitOnEvent());
+      assertEquals("Still should be 4 events", 4, listener.getEventCount());
+   }
+
+   public void testAddRemoveSubtree() throws Exception
+   {
+      Properties env = new Properties();
+      env.setProperty("java.naming.factory.initial", "org.jnp.interfaces.LocalOnlyContextFactory");
+      env.setProperty("java.naming.factory.url.pkgs", "org.jnp.interfaces");
+      InitialContext ic = new InitialContext(env);
+      System.out.println("Created InitialContext");
+      Context ctx = (Context) ic.lookup("");
+      assertTrue("Context is an EventContext", ctx instanceof EventContext);
+      EventContext ectx = (EventContext) ctx;
+      ectx.addNamingListener("", EventContext.SUBTREE_SCOPE, listener);
+      System.out.println("Added NamingListener");
+      ctx.bind("testAddObject", "testAddObject.bind");
+      assertTrue("Saw bind event", listener.waitOnEvent());
+      NamingEvent event = listener.getEvent(0);
+      assertEquals("OBJECT_ADDED", NamingEvent.OBJECT_ADDED, event.getType());
+      assertNull("getOldBinding", event.getOldBinding());      
+      assertEquals("testAddObject.bind", getValue(event.getNewBinding()));
+
+      ctx.rebind("testAddObject", "testAddObject.rebind");
+      assertTrue("Saw rebind event", listener.waitOnEvent());
+      event = listener.getEvent(1);
+      assertEquals("OBJECT_CHANGED", NamingEvent.OBJECT_CHANGED, event.getType());
+      assertEquals("testAddObject.bind", getValue(event.getOldBinding()));
+      assertEquals("testAddObject.rebind", getValue(event.getNewBinding()));
+
+      ctx.unbind("testAddObject");
+      assertTrue("Saw unbind event", listener.waitOnEvent());
+      event = listener.getEvent(2);
+      assertEquals("OBJECT_REMOVED", NamingEvent.OBJECT_REMOVED, event.getType());
+      assertEquals("testAddObject.rebind", getValue(event.getOldBinding()));
+      assertNull("getNewBinding", event.getNewBinding());
+
+      // Create a subcontext
+      Context subctx = ctx.createSubcontext("subctx");
+      listener.waitOnEvent();
+      assertEquals("Should be 4 events", 4, listener.getEventCount());
+      event = listener.getEvent(3);
+      assertEquals("OBJECT_ADDED", NamingEvent.OBJECT_ADDED, event.getType());
+      assertNull("getOldBinding", event.getOldBinding());      
+      assertEquals("getNewBinding", subctx, getValue(event.getNewBinding()));
+
+      // Creating a binding under subctx should produce an event
+      subctx.bind("subctx.testAddObject", "testAddObject.subctx.bind");
+      assertTrue("Wait on subctx bind", listener.waitOnEvent());
+      event = listener.getEvent(4);
+      assertEquals("OBJECT_ADDED", NamingEvent.OBJECT_ADDED, event.getType());      
+   }
+
+   protected Object getValue(Binding binding)
+      throws ClassNotFoundException, IOException
+   {
+      Object obj = binding.getObject();
+      if(obj instanceof MarshalledValuePair)
+      {
+         MarshalledValuePair mvp = (MarshalledValuePair) obj;
+         obj = mvp.get();
+      }
+      return obj;
+   }
+}

Added: projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/support/QueueEventListener.java
===================================================================
--- projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/support/QueueEventListener.java	                        (rev 0)
+++ projects/naming/trunk/jnpserver/src/test/java/org/jnp/test/support/QueueEventListener.java	2008-09-30 18:23:14 UTC (rev 78966)
@@ -0,0 +1,90 @@
+/*
+ * JBoss, Home of Professional Open Source
+ * Copyright 2008, Red Hat Middleware LLC, and individual contributors
+ * by the @authors tag. See the copyright.txt in the distribution for a
+ * full listing of individual contributors.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.jnp.test.support;
+
+import java.util.ArrayList;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.TimeUnit;
+
+import javax.naming.event.NamespaceChangeListener;
+import javax.naming.event.NamingEvent;
+import javax.naming.event.NamingExceptionEvent;
+import javax.naming.event.ObjectChangeListener;
+
+/**
+ * @author Scott.Stark at jboss.org
+ * @version $Revision:$
+ */
+public class QueueEventListener implements ObjectChangeListener,
+      NamespaceChangeListener
+{
+   private ArrayList<NamingEvent> events = new ArrayList<NamingEvent>();
+   private Semaphore eventCount = new Semaphore(0);
+   private NamingExceptionEvent ex;
+
+   public boolean waitOnEvent() throws InterruptedException
+   {
+      return eventCount.tryAcquire(2, TimeUnit.SECONDS);
+   }
+   public NamingEvent getEvent(int index)
+   {
+      return events.get(index);
+   }
+
+   public void objectChanged(NamingEvent evt)
+   {
+      System.out.println("Begin objectChanged, "+evt);
+      events.add(evt);
+      eventCount.release();
+      System.out.println("End objectChanged, "+evt);
+   }
+
+   public void namingExceptionThrown(NamingExceptionEvent evt)
+   {
+      ex = evt;
+   }
+
+   public void objectAdded(NamingEvent evt)
+   {
+      System.out.println("Begin objectAdded, "+evt);
+      events.add(evt);
+      eventCount.release();
+      System.out.println("End objectAdded, "+evt);
+   }
+
+   public void objectRemoved(NamingEvent evt)
+   {
+      events.add(evt);
+      eventCount.release();
+   }
+
+   public void objectRenamed(NamingEvent evt)
+   {
+      events.add(evt);
+      eventCount.release();
+   }
+   public int getEventCount()
+   {
+      return events.size();
+   }
+
+}

Modified: projects/naming/trunk/jnpserver/src/test/resources/log4j.xml
===================================================================
--- projects/naming/trunk/jnpserver/src/test/resources/log4j.xml	2008-09-30 17:40:08 UTC (rev 78965)
+++ projects/naming/trunk/jnpserver/src/test/resources/log4j.xml	2008-09-30 18:23:14 UTC (rev 78966)
@@ -13,17 +13,16 @@
     <appender name="CONSOLE" class="org.apache.log4j.ConsoleAppender">
         <errorHandler class="org.jboss.logging.util.OnlyOnceErrorHandler"/>
         <param name="Target" value="System.out"/>
-        <param name="Threshold" value="DEBUG"/>
         
         <layout class="org.apache.log4j.PatternLayout">
-            <!-- The default pattern: Date Priority [Category] Messagen -->
-            <!--
-                <param name="ConversionPattern" value="%d{ABSOLUTE} %-5p [%c{1}] %m%n"/>
-            -->
             <param name="ConversionPattern" value="%-5p %d{dd-MM HH:mm:ss,SSS} (%F:%M:%L)  -%m%n"/>
         </layout>
     </appender>
     
+    <category name="org.jnp.server">
+        <priority value="TRACE"/>
+    </category>
+    
     <root>
         <appender-ref ref="CONSOLE"/>
     </root>




More information about the jboss-cvs-commits mailing list