You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ak...@apache.org on 2005/09/07 23:52:44 UTC

svn commit: r279432 - in /directory/apacheds/trunk: core/src/main/java/org/apache/ldap/server/configuration/ core/src/main/java/org/apache/ldap/server/event/ core/src/main/java/org/apache/ldap/server/jndi/ main/

Author: akarasulu
Date: Wed Sep  7 14:52:34 2005
New Revision: 279432

URL: http://svn.apache.org/viewcvs?rev=279432&view=rev
Log:
initial code drop for EventDirContext functionality

changes ...

 o added new event interceptor to detect write operations on entries
 o added filter evaluation structures for detecting when to fire notifications
 o modified default interceptor setup to add the new eventService interceptor
 o modified the main's server.xml configuration to include the eventService
 o changed the context partition nexus proxy to add new functionality of 
   registering and deregistering clients

todo ...

 o check with Trustin if it's best to move code in proxy out to the actual nexus
 o testing - there has been no testing at all yet on this code 

Added:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java   (with props)
Modified:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ContextPartitionNexusProxy.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java
    directory/apacheds/trunk/main/server.xml

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java?rev=279432&r1=279431&r2=279432&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/configuration/StartupConfiguration.java Wed Sep  7 14:52:34 2005
@@ -44,6 +44,7 @@
 import org.apache.ldap.server.schema.bootstrap.JavaSchema;
 import org.apache.ldap.server.schema.bootstrap.SystemSchema;
 import org.apache.ldap.server.subtree.SubentryService;
+import org.apache.ldap.server.event.EventService;
 
 /**
  * A {@link Configuration} that starts up ApacheDS.
@@ -166,7 +167,12 @@
         interceptorCfg.setName( "operationalAttributeService" );
         interceptorCfg.setInterceptor( new OperationalAttributeService() );
         list.add( interceptorCfg );
-        
+
+        interceptorCfg = new MutableInterceptorConfiguration();
+        interceptorCfg.setName( "eventService" );
+        interceptorCfg.setInterceptor( new EventService() );
+        list.add( interceptorCfg );
+
         setInterceptorConfigurations( list );
     }
 

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,47 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.server.partition.impl.btree.IndexRecord;
+
+
+/**
+ * Tests if an entry is eligable for return by evaluating a filter expression on
+ * the candidate.  The evaluation can proceed by applying the filter on the 
+ * attributes of the entry itself or indices can be used for rapid evaluation.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public interface Evaluator
+{
+    /**
+     * Evaluates a candidate to determine if a filter expression selects it.
+     * 
+     * @param node the filter expression to evaluate on the candidate
+     * @param dn the normalized distinguished name of the entry being tested
+     * @param entry the entry to evaluate
+     * @return true if the filter selects the candidate false otherwise
+     * @throws javax.naming.NamingException if there is a database fault during evaluation
+     */
+    boolean evaluate( ExprNode node, String dn, Attributes entry ) throws NamingException;
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/Evaluator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,388 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import org.apache.ldap.server.interceptor.BaseInterceptor;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+import org.apache.ldap.server.jndi.ContextFactoryConfiguration;
+import org.apache.ldap.server.configuration.InterceptorConfiguration;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.schema.OidRegistry;
+import org.apache.ldap.server.partition.ContextPartitionNexus;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.ScopeNode;
+import org.apache.ldap.common.filter.BranchNode;
+import org.apache.ldap.common.message.DerefAliasesEnum;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.Binding;
+import javax.naming.event.*;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.ModificationItem;
+import javax.naming.directory.SearchControls;
+import java.util.*;
+
+
+/**
+ * An interceptor based serivice for notifying NamingListeners of EventContext
+ * and EventDirContext changes.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class EventService extends BaseInterceptor
+{
+    private ContextPartitionNexus nexus;
+    private Map sources = new HashMap();
+    private Evaluator evaluator = null;
+
+
+    public void init( ContextFactoryConfiguration factoryCfg, InterceptorConfiguration cfg ) throws NamingException
+    {
+        super.init( factoryCfg, cfg );
+
+        OidRegistry oidRegistry = factoryCfg.getGlobalRegistries().getOidRegistry();
+        AttributeTypeRegistry attrRegistry = factoryCfg.getGlobalRegistries().getAttributeTypeRegistry();
+        evaluator = new ExpressionEvaluator( oidRegistry, attrRegistry );
+        nexus = factoryCfg.getPartitionNexus();
+    }
+
+
+    /**
+     * Registers a NamingListener with this service for notification of change.
+     *
+     * @param ctx the context used to register on (the source)
+     * @param name the name of the base/target
+     * @param filter the filter to use for evaluating event triggering
+     * @param searchControls the search controls to use when evaluating triggering
+     * @param namingListener the naming listener to register
+     */
+    public void addNamingListener( EventContext ctx, Name name, ExprNode filter, SearchControls searchControls,
+                                   NamingListener namingListener )
+    {
+        ScopeNode scope = new ScopeNode( DerefAliasesEnum.NEVERDEREFALIASES, name.toString(),
+                searchControls.getSearchScope() );
+        BranchNode and = new BranchNode( BranchNode.AND );
+        and.addNode( scope );
+        and.addNode( filter );
+        EventSourceRecord rec = new EventSourceRecord( name, and, ctx, searchControls, namingListener );
+        Object obj = sources.get( namingListener );
+
+        if ( obj == null )
+        {
+            sources.put( namingListener, rec );
+        }
+        else if ( obj instanceof EventSourceRecord )
+        {
+            List list = new ArrayList();
+            list.add( obj );
+            list.add( rec );
+        }
+        else if ( obj instanceof List )
+        {
+            List list = ( List ) obj;
+            list.add( rec );
+        }
+    }
+
+
+    public void removeNamingListener( NamingListener namingListener )
+    {
+        sources.remove( namingListener );
+    }
+
+
+    public void add( NextInterceptor next, String upName, Name normName, Attributes entry ) throws NamingException
+    {
+        super.add( next, upName, normName, entry );
+        Set selecting = getSelectingSources( normName, entry );
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator list = selecting.iterator();
+        while ( list.hasNext() )
+        {
+            EventSourceRecord rec = ( EventSourceRecord ) list.next();
+            NamingListener listener = rec.getNamingListener();
+
+            if ( listener instanceof NamespaceChangeListener )
+            {
+                NamespaceChangeListener nclistener = ( NamespaceChangeListener ) listener;
+                Binding binding = new Binding( upName, entry, false );
+                nclistener.objectAdded( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_ADDED, null, binding, entry ) );
+            }
+            else if ( listener instanceof ObjectChangeListener )
+            {
+                ObjectChangeListener oclistener = ( ObjectChangeListener ) listener;
+                Binding binding = new Binding( upName, entry, false );
+                oclistener.objectChanged( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_ADDED, null, binding, entry ) );
+            }
+            else
+            {
+                throw new IllegalStateException( "unrecognized event listener type: " + listener.getClass() );
+            }
+        }
+    }
+
+
+    public void delete( NextInterceptor next, Name name ) throws NamingException
+    {
+        super.delete( next, name );
+        Attributes entry = nexus.lookup( name );
+        Set selecting = getSelectingSources( name, entry );
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator list = selecting.iterator();
+        while ( list.hasNext() )
+        {
+            EventSourceRecord rec = ( EventSourceRecord ) list.next();
+            NamingListener listener = rec.getNamingListener();
+
+            if ( listener instanceof NamespaceChangeListener )
+            {
+                NamespaceChangeListener nclistener = ( NamespaceChangeListener ) listener;
+                Binding binding = new Binding( name.toString(), entry, false );
+                nclistener.objectAdded( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_REMOVED, binding, null, entry ) );
+            }
+            else if ( listener instanceof ObjectChangeListener )
+            {
+                ObjectChangeListener oclistener = ( ObjectChangeListener ) listener;
+                Binding binding = new Binding( name.toString(), entry, false );
+                oclistener.objectChanged( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_REMOVED, binding, null, entry ) );
+            }
+            else
+            {
+                throw new IllegalStateException( "unrecognized event listener type: " + listener.getClass() );
+            }
+        }
+    }
+
+
+    private void notifyOnModify( Name name ) throws NamingException
+    {
+        Attributes entry = nexus.lookup( name );
+        Set selecting = getSelectingSources( name, entry );
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator list = selecting.iterator();
+        while ( list.hasNext() )
+        {
+            EventSourceRecord rec = ( EventSourceRecord ) list.next();
+            NamingListener listener = rec.getNamingListener();
+
+            if ( listener instanceof NamespaceChangeListener )
+            {
+                NamespaceChangeListener nclistener = ( NamespaceChangeListener ) listener;
+                Binding binding = new Binding( name.toString(), entry, false );
+                nclistener.objectAdded( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_CHANGED, binding, binding, entry ) );
+            }
+            else if ( listener instanceof ObjectChangeListener )
+            {
+                ObjectChangeListener oclistener = ( ObjectChangeListener ) listener;
+                Binding binding = new Binding( name.toString(), entry, false );
+                oclistener.objectChanged( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_CHANGED, binding, binding, entry ) );
+            }
+            else
+            {
+                throw new IllegalStateException( "unrecognized event listener type: " + listener.getClass() );
+            }
+        }
+    }
+
+    public void modify( NextInterceptor next, Name name, int modOp, Attributes mods ) throws NamingException
+    {
+        super.modify( next, name, modOp, mods );
+        notifyOnModify( name );
+    }
+
+
+    public void modify( NextInterceptor next, Name name, ModificationItem[] mods ) throws NamingException
+    {
+        super.modify( next, name, mods );
+        notifyOnModify( name );
+    }
+
+
+    private void notifyOnNameChange( Name oldName, Name newName ) throws NamingException
+    {
+        Attributes entry = nexus.lookup( newName );
+        Set selecting = getSelectingSources( oldName, entry );
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        Iterator list = selecting.iterator();
+        while ( list.hasNext() )
+        {
+            EventSourceRecord rec = ( EventSourceRecord ) list.next();
+            NamingListener listener = rec.getNamingListener();
+
+            if ( listener instanceof NamespaceChangeListener )
+            {
+                NamespaceChangeListener nclistener = ( NamespaceChangeListener ) listener;
+                Binding oldBinding = new Binding( oldName.toString(), entry, false );
+                Binding newBinding = new Binding( oldName.toString(), entry, false );
+                nclistener.objectAdded( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_CHANGED, oldBinding, newBinding, entry ) );
+            }
+            else if ( listener instanceof ObjectChangeListener )
+            {
+                ObjectChangeListener oclistener = ( ObjectChangeListener ) listener;
+                Binding oldBinding = new Binding( oldName.toString(), entry, false );
+                Binding newBinding = new Binding( oldName.toString(), entry, false );
+                oclistener.objectChanged( new NamingEvent( rec.getEventContext(),
+                        NamingEvent.OBJECT_CHANGED, oldBinding, newBinding, entry ) );
+            }
+            else
+            {
+                throw new IllegalStateException( "unrecognized event listener type: " + listener.getClass() );
+            }
+        }
+    }
+
+
+    public void modifyRn( NextInterceptor next, Name name, String newRn, boolean deleteOldRn ) throws NamingException
+    {
+        super.modifyRn( next, name, newRn, deleteOldRn );
+        Name newName = ( Name ) name.clone();
+        newName.remove( newName.size() - 1 );
+        newName.add( newRn );
+        notifyOnNameChange( name, newName );
+    }
+
+
+    public void move( NextInterceptor next, Name oriChildName, Name newParentName, String newRn, boolean deleteOldRn )
+            throws NamingException
+    {
+        super.move( next, oriChildName, newParentName, newRn, deleteOldRn );
+        Name newName = ( Name ) newParentName.clone();
+        newName.add( newRn );
+        notifyOnNameChange( oriChildName, newName );
+    }
+
+
+    public void move( NextInterceptor next, Name oriChildName, Name newParentName ) throws NamingException
+    {
+        super.move( next, oriChildName, newParentName );
+        Name newName = ( Name ) newParentName.clone();
+        newName.add( oriChildName.get( oriChildName.size() - 1 ) );
+        notifyOnNameChange( oriChildName, newName );
+    }
+
+
+    Set getSelectingSources( Name name, Attributes entry ) throws NamingException
+    {
+        if ( sources.isEmpty() )
+        {
+            return Collections.EMPTY_SET;
+        }
+
+        Set selecting = new HashSet();
+        Iterator list = sources.values().iterator();
+        while ( list.hasNext() )
+        {
+            Object obj = list.next();
+            if ( obj instanceof EventSourceRecord )
+            {
+                EventSourceRecord rec = ( EventSourceRecord ) obj;
+                if ( evaluator.evaluate( rec.getFilter(), name.toString(), entry ) )
+                {
+                    selecting.add( obj );
+                }
+            }
+            else if ( obj instanceof List )
+            {
+                List records = ( List ) obj;
+                for ( int ii = 0; ii < records.size(); ii++ )
+                {
+                    EventSourceRecord rec = ( EventSourceRecord ) records.get( ii );
+                    if ( evaluator.evaluate( rec.getFilter(), name.toString(), entry ) )
+                    {
+                        selecting.add( obj );
+                    }
+                }
+            }
+            else
+            {
+                throw new IllegalStateException( "Unexpected class type of " + obj.getClass() );
+            }
+        }
+
+        return selecting;
+    }
+
+
+    class EventSourceRecord
+    {
+        private Name base;
+        private SearchControls controls;
+        private ExprNode filter;
+        private EventContext context;
+        private NamingListener listener;
+
+        public EventSourceRecord( Name base, ExprNode filter, EventContext context, SearchControls controls, NamingListener listener )
+        {
+            this.filter = filter;
+            this.context = context;
+            this.base = base;
+            this.controls = controls;
+            this.listener = listener;
+        }
+
+        public NamingListener getNamingListener()
+        {
+            return listener;
+        }
+
+        public ExprNode getFilter()
+        {
+            return filter;
+        }
+
+        public EventContext getEventContext()
+        {
+            return context;
+        }
+
+        public Name getBase()
+        {
+            return base;
+        }
+
+        public SearchControls getSearchControls()
+        {
+            return controls;
+        }
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/EventService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,146 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import java.util.Iterator;
+
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.filter.BranchNode;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.schema.OidRegistry;
+
+
+/**
+ * Top level filter expression evaluator implemenation.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class ExpressionEvaluator implements Evaluator
+{
+    /** Leaf Evaluator flyweight use for leaf filter assertions */
+    private LeafEvaluator leafEvaluator;
+
+
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * Creates a top level Evaluator where leaves are delegated to a leaf node
+     * evaluator which is already provided.
+     *
+     * @param leafEvaluator handles leaf node evaluation.
+     */
+    public ExpressionEvaluator( LeafEvaluator leafEvaluator )
+    {
+        this.leafEvaluator = leafEvaluator;
+    }
+
+
+    /**
+     * Creates a top level Evaluator where leaves are delegated to a leaf node
+     * evaluator which will be created.
+     *
+     * @param oidRegistry the oid reg used for attrID to oid resolution
+     * @param attributeTypeRegistry the attribtype reg used for value comparison
+     */
+    public ExpressionEvaluator( OidRegistry oidRegistry,
+                                AttributeTypeRegistry attributeTypeRegistry ) throws NamingException
+    {
+        SubstringEvaluator substringEvaluator = null;
+        substringEvaluator = new SubstringEvaluator( oidRegistry, attributeTypeRegistry );
+        leafEvaluator = new LeafEvaluator( oidRegistry, attributeTypeRegistry, substringEvaluator );
+    }
+
+
+    /**
+     * Gets the leaf evaluator used by this top level expression evaluator.
+     *
+     * @return the leaf evaluator used by this top level expression evaluator
+     */
+    public LeafEvaluator getLeafEvaluator()
+    {
+        return leafEvaluator;
+    }
+
+
+    // ------------------------------------------------------------------------
+    // Evaluator.evaluate() implementation
+    // ------------------------------------------------------------------------
+
+
+    /**
+     * @see Evaluator#evaluate(ExprNode, String, Attributes)
+     */
+    public boolean evaluate( ExprNode node, String dn, Attributes entry )
+        throws NamingException
+    {
+        if ( node.isLeaf() ) 
+        {
+            return leafEvaluator.evaluate( node, dn, entry );
+        }
+
+        BranchNode bnode = ( BranchNode ) node;
+
+        switch( bnode.getOperator() )
+        {
+        case( BranchNode.OR ):
+            Iterator children = bnode.getChildren().iterator();
+            
+            while ( children.hasNext() ) 
+            {
+                ExprNode child = ( ExprNode ) children.next();
+                
+                if ( evaluate( child, dn, entry ) )
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        case( BranchNode.AND ):
+            children = bnode.getChildren().iterator();
+            while ( children.hasNext() ) 
+            {
+                ExprNode child = ( ExprNode ) children.next();
+
+                if ( ! evaluate( child, dn, entry ) )
+                {
+                    return false;
+                }
+            }
+
+            return true;
+        case( BranchNode.NOT ):
+            if ( null != bnode.getChild() )
+            {
+                return ! evaluate( bnode.getChild(), dn, entry );
+            }
+
+            throw new NamingException( "Negation has no child: " + node );
+        default:
+            throw new NamingException( "Unrecognized branch node operator: "
+                + bnode.getOperator() );
+        }
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ExpressionEvaluator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,336 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import java.util.Comparator;
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.NotImplementedException;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.LeafNode;
+import org.apache.ldap.common.filter.PresenceNode;
+import org.apache.ldap.common.filter.ScopeNode;
+import org.apache.ldap.common.filter.SimpleNode;
+import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.common.schema.MatchingRule;
+import org.apache.ldap.common.schema.Normalizer;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.schema.OidRegistry;
+
+
+/**
+ * Evaluates LeafNode assertions on candidates using a database.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class LeafEvaluator implements Evaluator
+{
+    /** equality matching type constant */
+    private static final int EQUALITY_MATCH = 0;
+    /** ordering matching type constant */
+    private static final int ORDERING_MATCH = 1;
+    /** substring matching type constant */
+    private static final int SUBSTRING_MATCH = 3;
+
+
+    /** Oid Registry used to translate attributeIds to OIDs */
+    private OidRegistry oidRegistry;
+    /** AttributeType registry needed for normalizing and comparing values */
+    private AttributeTypeRegistry attributeTypeRegistry;
+    /** Substring node evaluator we depend on */
+    private SubstringEvaluator substringEvaluator;
+    /** ScopeNode evaluator we depend on */
+    private ScopeEvaluator scopeEvaluator;
+
+
+    /**
+     * Creates a leaf expression node evaluator.
+     *
+     * @param substringEvaluator
+     */
+    public LeafEvaluator( OidRegistry oidRegistry,
+                          AttributeTypeRegistry attributeTypeRegistry,
+                          SubstringEvaluator substringEvaluator ) throws NamingException
+    {
+        this.oidRegistry = oidRegistry;
+        this.attributeTypeRegistry = attributeTypeRegistry;
+        this.scopeEvaluator = new ScopeEvaluator();
+        this.substringEvaluator = substringEvaluator;
+    }
+
+
+    public ScopeEvaluator getScopeEvaluator()
+    {
+        return scopeEvaluator;
+    }
+
+
+    public SubstringEvaluator getSubstringEvaluator()
+    {
+        return substringEvaluator;
+    }
+
+
+    /**
+     * @see Evaluator#evaluate(ExprNode, String, Attributes)
+     */
+    public boolean evaluate( ExprNode node, String dn, Attributes entry ) throws NamingException
+    {
+        if ( node instanceof ScopeNode )
+        {
+            return scopeEvaluator.evaluate( node, dn, entry );
+        }
+        
+        switch( ( ( LeafNode ) node ).getAssertionType() ) 
+        {
+        case( LeafNode.APPROXIMATE ):
+            return evalEquality( ( SimpleNode ) node, entry );
+        case( LeafNode.EQUALITY ):
+            return evalEquality( ( SimpleNode ) node, entry );
+        case( LeafNode.EXTENSIBLE ):
+            throw new NotImplementedException();
+        case( LeafNode.GREATEREQ ):
+            return evalGreater( ( SimpleNode ) node, entry, true );
+        case( LeafNode.LESSEQ ):
+            return evalGreater( ( SimpleNode ) node, entry, false );
+        case( LeafNode.PRESENCE ):
+            String attrId = ( ( PresenceNode ) node ).getAttribute();
+            return evalPresence( attrId, entry );
+        case( LeafNode.SUBSTRING ):
+            return substringEvaluator.evaluate( node, dn, entry );
+        default:
+            throw new NamingException( "Unrecognized leaf node type: "
+                + ( ( LeafNode ) node ).getAssertionType() );
+        }
+    }
+    
+    
+    /**
+     * Evaluates a simple greater than or less than attribute value assertion on
+     * a perspective candidate.
+     * 
+     * @param node the greater than or less than node to evaluate
+     * @param entry the perspective candidate
+     * @param isGreater true if it is a greater than or equal to comparison,
+     *      false if it is a less than or equal to comparison.
+     * @return the ava evaluation on the perspective candidate
+     * @throws javax.naming.NamingException if there is a database access failure
+     */
+    private boolean evalGreater( SimpleNode node, Attributes entry,
+        boolean isGreater ) throws NamingException
+    {
+        String attrId = node.getAttribute();
+
+        // get the attribute associated with the node
+        Attribute attr = entry.get( attrId );
+
+        // If we do not have the attribute just return false
+        if ( null == attr )
+        {
+            return false;
+        }
+        
+        /*
+         * We need to iterate through all values and for each value we normalize
+         * and use the comparator to determine if a match exists.
+         */
+        Normalizer normalizer = getNormalizer( attrId );
+        Comparator comparator = getComparator( attrId );
+        Object filterValue = normalizer.normalize( node.getValue() );
+        NamingEnumeration list = attr.getAll();
+        
+        /*
+         * Cheaper to not check isGreater in one loop - better to separate
+         * out into two loops which you choose to execute based on isGreater
+         */
+        if ( isGreater )
+        {
+            while ( list.hasMore() )
+            {
+                Object value = normalizer.normalize( list.next() );
+            
+                // Found a value that is greater than or equal to the ava value
+                if ( 0 >= comparator.compare( value, filterValue ) )
+                {
+                    return true;
+                }
+            }
+        }
+        else 
+        {    
+            while ( list.hasMore() )
+            {
+                Object value = normalizer.normalize( list.next() );
+            
+                // Found a value that is less than or equal to the ava value
+                if ( 0 <= comparator.compare( value, filterValue ) )
+                {
+                    return true;
+                }
+            }
+        }
+        
+        // no match so return false
+        return false;
+    }
+
+    
+    /**
+     * Evaluates a simple presence attribute value assertion on a perspective
+     * candidate.
+     * 
+     * @param attrId the name of the attribute tested for presence 
+     * @param entry the perspective candidate
+     * @return the ava evaluation on the perspective candidate
+     */
+    private boolean evalPresence( String attrId, Attributes entry )
+    {
+        if ( entry == null )
+        {
+            return false;
+        }
+        
+        return null != entry.get( attrId );
+    }
+
+
+    /**
+     * Evaluates a simple equality attribute value assertion on a perspective
+     * candidate.
+     *
+     * @param node the equality node to evaluate
+     * @param entry the perspective candidate
+     * @return the ava evaluation on the perspective candidate
+     * @throws javax.naming.NamingException if there is a database access failure
+     */
+    private boolean evalEquality( SimpleNode node, Attributes entry )
+        throws NamingException
+    {
+        Normalizer normalizer = getNormalizer( node.getAttribute() );
+        Comparator comparator = getComparator( node.getAttribute() );
+
+        // get the attribute associated with the node
+        Attribute attr = entry.get( node.getAttribute() );
+
+        // If we do not have the attribute just return false
+        if ( null == attr )
+        {
+            return false;
+        }
+        
+        // check if AVA value exists in attribute
+        if ( attr.contains( node.getValue() ) )
+        {
+            return true;
+        }
+
+        // get the normalized AVA filter value
+        Object filterValue = normalizer.normalize( node.getValue() );
+
+        // check if the normalized value is present
+        if ( attr.contains( filterValue ) )
+        {
+            return true;
+        }
+        
+        /*
+         * We need to now iterate through all values because we could not get
+         * a lookup to work.  For each value we normalize and use the comparator
+         * to determine if a match exists.
+         */
+        NamingEnumeration list = attr.getAll();
+        while ( list.hasMore() )
+        {
+            Object value = normalizer.normalize( list.next() );
+            
+            if ( 0 == comparator.compare( value, filterValue ) )
+            {
+                return true;
+            }
+        }
+        
+        // no match so return false
+        return false;
+    }
+
+
+    /**
+     * Gets the comparator for equality matching.
+     *
+     * @param attrId the attribute identifier
+     * @return the comparator for equality matching
+     * @throws javax.naming.NamingException if there is a failure
+     */
+    private Comparator getComparator( String attrId ) throws NamingException
+    {
+        MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
+        return mrule.getComparator();
+    }
+
+
+    /**
+     * Gets the normalizer for equality matching.
+     *
+     * @param attrId the attribute identifier
+     * @return the normalizer for equality matching
+     * @throws javax.naming.NamingException if there is a failure
+     */
+    private Normalizer getNormalizer( String attrId ) throws NamingException
+    {
+        MatchingRule mrule = getMatchingRule( attrId, EQUALITY_MATCH );
+        return mrule.getNormalizer();
+    }
+
+
+    /**
+     * Gets the matching rule for an attributeType.
+     *
+     * @param attrId the attribute identifier
+     * @return the matching rule
+     * @throws javax.naming.NamingException if there is a failure
+     */
+    private MatchingRule getMatchingRule( String attrId, int matchType )
+        throws NamingException
+    {
+        MatchingRule mrule = null;
+        String oid = oidRegistry.getOid( attrId );
+        AttributeType type = attributeTypeRegistry.lookup( oid );
+
+        switch( matchType )
+        {
+            case( EQUALITY_MATCH ):
+                mrule = type.getEquality();
+                break;
+            case( SUBSTRING_MATCH ):
+                mrule = type.getSubstr();
+                break;
+            case( ORDERING_MATCH ):
+                mrule = type.getOrdering();
+                break;
+            default:
+                throw new NamingException( "Unknown match type: " + matchType );
+        }
+
+        return mrule;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/LeafEvaluator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,72 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import javax.naming.NamingException;
+import javax.naming.Name;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.ScopeNode;
+import org.apache.ldap.common.name.DnParser;
+
+
+/**
+ * Evaluates ScopeNode assertions on candidates using a database.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class ScopeEvaluator implements Evaluator
+{
+    private DnParser parser = null;
+
+
+    public ScopeEvaluator() throws NamingException
+    {
+        parser = new DnParser();
+    }
+
+
+    /**
+     * @see Evaluator#evaluate(ExprNode, String, Attributes)
+     */
+    public boolean evaluate( ExprNode node, String dn, Attributes record )
+        throws NamingException
+    {
+        ScopeNode snode = ( ScopeNode ) node;
+
+        switch( snode.getScope() )
+        {
+        case( SearchControls.OBJECT_SCOPE ):
+            return dn.equals( snode.getBaseDn() );
+        case( SearchControls.ONELEVEL_SCOPE ):
+            if ( dn.endsWith( snode.getBaseDn() ) )
+            {
+                Name candidateDn = parser.parse( dn );
+                Name scopeDn = parser.parse( snode.getBaseDn() );
+                return ( scopeDn.size() + 1 ) == candidateDn.size();
+            }
+        case( SearchControls.SUBTREE_SCOPE ):
+            return dn.endsWith( snode.getBaseDn() );
+        default:
+            throw new NamingException( "Unrecognized search scope!" );
+        }
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/ScopeEvaluator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java?rev=279432&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java Wed Sep  7 14:52:34 2005
@@ -0,0 +1,120 @@
+/*
+ *   Copyright 2004 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.ldap.server.event;
+
+
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.SubstringNode;
+import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.common.schema.Normalizer;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.schema.OidRegistry;
+import org.apache.regexp.RE;
+import org.apache.regexp.RESyntaxException;
+
+
+/**
+ * Evaluates substring filter assertions on an entry.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$
+ */
+public class SubstringEvaluator implements Evaluator
+{
+    /** Oid Registry used to translate attributeIds to OIDs */
+    private OidRegistry oidRegistry;
+    /** AttributeType registry needed for normalizing and comparing values */
+    private AttributeTypeRegistry attributeTypeRegistry;
+
+
+    /**
+     * Creates a new SubstringEvaluator for substring expressions.
+     *
+     * @param oidRegistry the OID registry for name to OID mapping
+     * @param attributeTypeRegistry the attributeType registry
+     */
+    public SubstringEvaluator( OidRegistry oidRegistry,
+                               AttributeTypeRegistry attributeTypeRegistry )
+    {
+        this.oidRegistry = oidRegistry;
+        this.attributeTypeRegistry = attributeTypeRegistry;
+    }
+
+
+    /**
+     * @see Evaluator#evaluate(ExprNode, String, Attributes)
+     */
+    public boolean evaluate( ExprNode node, String dn, Attributes entry )
+        throws NamingException
+    {
+        RE regex = null; 
+        SubstringNode snode = ( SubstringNode ) node;
+        String oid = oidRegistry.getOid( snode.getAttribute() );
+        AttributeType type = attributeTypeRegistry.lookup( oid );
+        Normalizer normalizer = type.getSubstr().getNormalizer();
+
+        // get the attribute
+        Attribute attr = entry.get( snode.getAttribute() );
+        
+        // if the attribute does not exist just return false
+        if ( null == attr )
+        {
+            return false;
+        }
+
+        // compile the regular expression to search for a matching attribute
+        try 
+        {
+            regex = snode.getRegex( normalizer );
+        } 
+        catch ( RESyntaxException e ) 
+        {
+            NamingException ne = new NamingException( "SubstringNode '" 
+                + node + "' had " + "incorrect syntax" );
+            ne.setRootCause( e );
+            throw ne;
+        }
+        
+        /*
+         * Cycle through the attribute values testing normalized version 
+         * obtained from using the substring matching rule's normalizer.
+         * The test uses the comparator obtained from the appropriate 
+         * substring matching rule.
+         */ 
+        NamingEnumeration list = attr.getAll(); 
+        while ( list.hasMore() ) 
+        {
+            String value = ( String ) 
+                normalizer.normalize( list.next() );
+            
+            // Once match is found cleanup and return true
+            if ( regex.match( value ) ) 
+            {
+                list.close();
+                return true;
+            }
+        }
+
+        // we fell through so a match was not found - assertion was false.
+        return false;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/event/SubstringEvaluator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ContextPartitionNexusProxy.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ContextPartitionNexusProxy.java?rev=279432&r1=279431&r2=279432&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ContextPartitionNexusProxy.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ContextPartitionNexusProxy.java Wed Sep  7 14:52:34 2005
@@ -16,6 +16,7 @@
  */
 package org.apache.ldap.server.jndi;
 
+
 import java.util.Iterator;
 import java.util.Map;
 
@@ -24,6 +25,8 @@
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.ServiceUnavailableException;
+import javax.naming.event.NamingListener;
+import javax.naming.event.EventContext;
 import javax.naming.directory.Attributes;
 import javax.naming.directory.ModificationItem;
 import javax.naming.directory.SearchControls;
@@ -36,6 +39,8 @@
 import org.apache.ldap.server.invocation.InvocationStack;
 import org.apache.ldap.server.partition.ContextPartition;
 import org.apache.ldap.server.partition.ContextPartitionNexus;
+import org.apache.ldap.server.event.EventService;
+
 
 /**
  * A decorator that wraps other {@link ContextPartitionNexus} to enable
@@ -411,5 +416,33 @@
         {
             throw new ServiceUnavailableException( "ContextFactoryService is not started." );
         }
+    }
+
+
+    // -----------------------------------------------------------------------
+    // EventContext and EventDirContext notification methods
+    // -----------------------------------------------------------------------
+
+    /*
+     * All listener registration/deregistration methods can be reduced down to
+     * the following methods.  Rather then make these actual intercepted methods
+     * we use them as out of band methods to interface with the notification
+     * interceptor.
+     */
+
+    public void addNamingListener( EventContext ctx, Name name, ExprNode filter, SearchControls searchControls,
+                                   NamingListener namingListener ) throws NamingException
+    {
+        InterceptorChain chain = this.configuration.getInterceptorChain();
+        EventService interceptor = ( EventService ) chain.get( "eventService" );
+        interceptor.addNamingListener( ctx, name, filter, searchControls, namingListener );
+    }
+
+
+    public void removeNamingListener( NamingListener namingListener ) throws NamingException
+    {
+        InterceptorChain chain = this.configuration.getInterceptorChain();
+        EventService interceptor = ( EventService ) chain.get( "eventService" );
+        interceptor.removeNamingListener( namingListener );
     }
 }

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java?rev=279432&r1=279431&r2=279432&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerContext.java Wed Sep  7 14:52:34 2005
@@ -42,6 +42,7 @@
 
 import org.apache.ldap.common.exception.LdapNoPermissionException;
 import org.apache.ldap.common.filter.PresenceNode;
+import org.apache.ldap.common.filter.ExprNode;
 import org.apache.ldap.common.message.LockableAttributesImpl;
 import org.apache.ldap.common.name.LdapName;
 import org.apache.ldap.common.util.NamespaceTools;
@@ -764,21 +765,25 @@
     // ------------------------------------------------------------------------
 
 
-    public void addNamingListener( Name name, int i, NamingListener namingListener ) throws NamingException
+    public void addNamingListener( Name name, int scope, NamingListener namingListener ) throws NamingException
     {
-        // stub: does not do anything just yet
+        ExprNode filter = new PresenceNode( "objectClass" );
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( scope );
+        ( ( ContextPartitionNexusProxy ) this.nexusProxy )
+                .addNamingListener( this, buildTarget( name ), filter, controls, namingListener );
     }
 
 
-    public void addNamingListener( String s, int i, NamingListener namingListener ) throws NamingException
+    public void addNamingListener( String name, int scope, NamingListener namingListener ) throws NamingException
     {
-        // stub: does not do anything just yet
+        addNamingListener( new LdapName( name ), scope, namingListener );
     }
 
 
     public void removeNamingListener( NamingListener namingListener ) throws NamingException
     {
-        // stub: does not do anything just yet
+        ( ( ContextPartitionNexusProxy ) this.nexusProxy ).removeNamingListener( namingListener );
     }
 
 

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java?rev=279432&r1=279431&r2=279432&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/jndi/ServerDirContext.java Wed Sep  7 14:52:34 2005
@@ -668,30 +668,75 @@
     // ------------------------------------------------------------------------
 
 
-    public void addNamingListener( Name name, String s, SearchControls searchControls, NamingListener namingListener ) 
+    FilterParserImpl filterParser = new FilterParserImpl();
+
+    public void addNamingListener( Name name, String filterStr, SearchControls searchControls, NamingListener namingListener )
             throws NamingException
     {
-        // stub: does not do anything just yet
+        ExprNode filter = null;
+
+        try
+        {
+            filter = filterParser.parse( filterStr );
+        }
+        catch ( Exception e )
+        {
+            NamingException e2 = new NamingException( "could not parse filter: " + filterStr );
+            e2.setRootCause( e );
+            throw e2;
+        }
+
+        ( ( ContextPartitionNexusProxy ) getNexusProxy() )
+                .addNamingListener( this, buildTarget( name ), filter, searchControls, namingListener );
     }
 
 
-    public void addNamingListener( String s, String s1, SearchControls searchControls, NamingListener namingListener )
+    public void addNamingListener( String name, String filter, SearchControls searchControls, NamingListener namingListener )
             throws NamingException
     {
-        // stub: does not do anything just yet
+        addNamingListener( new LdapName( name ), filter, searchControls, namingListener );
     }
 
 
-    public void addNamingListener( Name name, String s, Object[] objects, SearchControls searchControls,
+    public void addNamingListener( Name name, String filterExpr, Object[] filterArgs, SearchControls searchControls,
                                    NamingListener namingListener ) throws NamingException
     {
-        // stub: does not do anything just yet
+        int start;
+
+        StringBuffer buf = new StringBuffer( filterExpr );
+
+        // Scan until we hit the end of the string buffer
+        for ( int ii = 0; ii < buf.length(); ii++ )
+        {
+            // Advance until we hit the start of a variable
+            while ( '{' != buf.charAt( ii ) )
+            {
+                ii++;
+            }
+
+            // Record start of variable at '{'
+            start = ii;
+
+            // Advance to the end of a variable at '}'
+            while ( '}' != buf.charAt( ii ) )
+            {
+                ii++;
+            }
+            
+            /*
+             * Replace the '{ i }' with the string representation of the value
+             * held in the filterArgs array at index index.
+             */
+            buf.replace( start, ii + 1, filterArgs[ii].toString() );
+        }
+
+        addNamingListener( name, buf.toString(), searchControls, namingListener );
     }
 
 
-    public void addNamingListener( String s, String s1, Object[] objects, SearchControls searchControls,
+    public void addNamingListener( String name, String filter, Object[] objects, SearchControls searchControls,
                                    NamingListener namingListener ) throws NamingException
     {
-        // stub: does not do anything just yet
+        addNamingListener( new LdapName( name ), filter, objects, searchControls, namingListener );
     }
 }

Modified: directory/apacheds/trunk/main/server.xml
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/main/server.xml?rev=279432&r1=279431&r2=279432&view=diff
==============================================================================
--- directory/apacheds/trunk/main/server.xml (original)
+++ directory/apacheds/trunk/main/server.xml Wed Sep  7 14:52:34 2005
@@ -85,6 +85,12 @@
             <bean class="org.apache.ldap.server.operational.OperationalAttributeService" />
           </property>
         </bean>
+        <bean class="org.apache.ldap.server.configuration.MutableInterceptorConfiguration">
+          <property name="name"><value>eventService</value></property>
+          <property name="interceptor">
+            <bean class="org.apache.ldap.server.event.EventService" />
+          </property>
+        </bean>
       </list>
     </property>
   </bean>