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 2008/06/11 10:00:04 UTC

svn commit: r666558 - in /directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core: ./ event/ interceptor/context/

Author: akarasulu
Date: Wed Jun 11 01:00:04 2008
New Revision: 666558

URL: http://svn.apache.org/viewvc?rev=666558&view=rev
Log:
New event service initial implementation

Added:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/DirectoryListener.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventType.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NewEventInterceptor.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NotificationCriteria.java
Modified:
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java
    directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/DeleteOperationContext.java

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=666558&r1=666557&r2=666558&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Wed Jun 11 01:00:04 2008
@@ -36,6 +36,7 @@
 import org.apache.directory.server.core.entry.ServerEntry;
 import org.apache.directory.server.core.entry.ServerEntryUtils;
 import org.apache.directory.server.core.event.EventInterceptor;
+import org.apache.directory.server.core.event.EventService;
 import org.apache.directory.server.core.exception.ExceptionInterceptor;
 import org.apache.directory.server.core.interceptor.Interceptor;
 import org.apache.directory.server.core.interceptor.InterceptorChain;
@@ -237,6 +238,7 @@
     private Partition systemPartition;
     private Set<Partition> partitions = new HashSet<Partition>();
     private List<? extends LdifEntry> testEntries = new ArrayList<LdifEntry>(); // List<Attributes>
+    private EventService eventService;
 
 
 
@@ -1481,4 +1483,16 @@
             return null;
         }
     }
+
+
+    public EventService getEventService()
+    {
+        return eventService;
+    }
+
+
+    public void setEventService( EventService eventService )
+    {
+        this.eventService = eventService;
+    }
 }

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java?rev=666558&r1=666557&r2=666558&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/DirectoryService.java Wed Jun 11 01:00:04 2008
@@ -24,6 +24,7 @@
 import org.apache.directory.server.core.changelog.ChangeLog;
 import org.apache.directory.server.core.entry.ServerEntry;
 import org.apache.directory.server.core.entry.ServerEntryFactory;
+import org.apache.directory.server.core.event.EventService;
 import org.apache.directory.server.core.interceptor.Interceptor;
 import org.apache.directory.server.core.interceptor.InterceptorChain;
 import org.apache.directory.server.core.jndi.AbstractContextFactory;
@@ -106,6 +107,12 @@
 
 
     void setSchemaService( SchemaService schemaService );
+    
+    
+    EventService getEventService();
+    
+    
+    void setEventService( EventService eventService );
 
 
     /**

Added: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/DirectoryListener.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/DirectoryListener.java?rev=666558&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/DirectoryListener.java (added)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/DirectoryListener.java Wed Jun 11 01:00:04 2008
@@ -0,0 +1,85 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.event;
+
+
+import org.apache.directory.server.core.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
+
+
+/**
+ * A listener which is notified of changes to the directory service.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface DirectoryListener
+{
+    /**
+     * Called when an entry has been added.
+     *
+     * @param opContext the add operation context responsible for the change
+     */
+    void entryAdded( AddOperationContext opContext ); 
+    
+    
+    /**
+     * Called when an entry has been deleted.
+     *
+     * @param opContext the delete operation context responsible for the change
+     */
+    void entryDeleted( DeleteOperationContext opContext );
+    
+    
+    /**
+     * Called when an entry has been modified.
+     *
+     * @param opContext the modify operation context responsible for the change
+     */
+    void entryModified( ModifyOperationContext opContext );
+    
+    
+    /**
+     * Called when an entry has been renamed.
+     *
+     * @param opContext the rename operation context responsible for the change
+     */
+    void entryRenamed( RenameOperationContext opContext );
+    
+    
+    /**
+     * Called when an entry is moved.
+     *
+     * @param opContext the move operation context responsible for the change
+     */
+    void entryMoved( MoveOperationContext opContext );
+    
+    
+    /**
+     * Called when an entry is moved and renamed at the same time.
+     *
+     * @param opContext the move/rename operation context responsible for the change
+     */
+    void entryMovedAndRenamed( MoveAndRenameOperationContext opContext );
+}

Added: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventService.java?rev=666558&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventService.java (added)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventService.java Wed Jun 11 01:00:04 2008
@@ -0,0 +1,59 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.event;
+
+
+/**
+ * Interface used by the DirectoryService to manage subscriptions for DIT 
+ * change notifications.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public interface EventService
+{
+    /**
+     * Registers a DirectoryListener for notification on any and all change 
+     * events on the DIT.
+     *
+     * @param listener the DirectoryListener to deliver notifications to
+     */
+    void addListener( DirectoryListener listener );
+
+    
+    /**
+     * Registers a DirectoryListener for notification on change events on the 
+     * DIT matching some notification criteria.
+     *
+     * @param listener the DirectoryListener to deliver notifications to
+     * @param criteria the parameterized criteria for delivering change events
+     * @throws Exception 
+     */
+    void addListener( DirectoryListener listener, NotificationCriteria criteria ) throws Exception;
+    
+    
+    /**
+     * Removes the listener from this EventService preventing all events 
+     * registered from being delivered to it.
+     *
+     * @param listener the DirectoryListener to stop delivering notifications to
+     */
+    void removeListener( DirectoryListener listener );
+}

Added: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventType.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventType.java?rev=666558&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventType.java (added)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/EventType.java Wed Jun 11 01:00:04 2008
@@ -0,0 +1,146 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.event;
+
+
+/**
+ * The different kinds of events a {@link DirectoryListener} may register for 
+ * notification on using the {@link EventService}.  Sometimes an entry is 
+ * moved and renamed at the same time.  These notifications are sent when 
+ * either RENAME or MOVE notifications are enabled.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public enum EventType
+{
+    ADD(1), DELETE(2), MODIFY(4), RENAME(8), MOVE(16);
+    
+    
+    public static final int ALL_EVENT_TYPES_MASK = getAllEventTypesMask();
+    public static final int MOVE_OR_RENAME_MASK = MOVE.mask | RENAME.mask;
+    
+    
+    private int mask;
+    
+    
+    private EventType( int mask )
+    {
+        this.mask = mask;
+    }
+    
+    
+    public int getMask()
+    {
+        return mask;
+    }
+    
+    
+    private static int getAllEventTypesMask()
+    {
+        int allTypes = 0;
+        
+        for ( EventType type : values() )
+        {
+            allTypes |= type.getMask();
+        }
+        
+        return allTypes;
+    }
+    
+    
+    public static boolean isAdd( int mask )
+    {
+        if ( ( mask & ADD.mask ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static boolean isDelete( int mask )
+    {
+        if ( ( mask & DELETE.mask ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static boolean isModify( int mask )
+    {
+        if ( ( mask & MODIFY.mask ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static boolean isMove( int mask )
+    {
+        if ( ( mask & MOVE.mask ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static boolean isRename( int mask )
+    {
+        if ( ( mask & RENAME.mask ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static boolean isMoveAndRename( int mask )
+    {
+        if ( ( mask & MOVE_OR_RENAME_MASK ) > 0 )
+        {
+            return true;
+        }
+        
+        return false;
+    }
+    
+    
+    public static int getMask( EventType ...eventTypes )
+    {
+        int mask = 0;
+        
+        for ( EventType type : eventTypes )
+        {
+            mask |= type.getMask();
+        }
+        
+        return mask;
+    }
+}

Added: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NewEventInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NewEventInterceptor.java?rev=666558&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NewEventInterceptor.java (added)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NewEventInterceptor.java Wed Jun 11 01:00:04 2008
@@ -0,0 +1,380 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you 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.directory.server.core.event;
+
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.ArrayBlockingQueue;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
+import org.apache.directory.server.core.entry.ServerEntry;
+import org.apache.directory.server.core.interceptor.BaseInterceptor;
+import org.apache.directory.server.core.interceptor.NextInterceptor;
+import org.apache.directory.server.core.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.interceptor.context.OperationContext;
+import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.normalization.NormalizingVisitor;
+import org.apache.directory.server.core.partition.ByPassConstants;
+import org.apache.directory.server.schema.ConcreteNameComponentNormalizer;
+import org.apache.directory.server.schema.registries.AttributeTypeRegistry;
+import org.apache.directory.server.schema.registries.OidRegistry;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.name.LdapDN;
+import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * An {@link Interceptor} based service for notifying {@link 
+ * DirectoryListener}s of changes to the DIT.
+ *
+ * @org.apache.xbean.XBean
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev: 666516 $
+ */
+public class NewEventInterceptor extends BaseInterceptor
+{
+    private final static Logger LOG = LoggerFactory.getLogger( NewEventInterceptor.class );
+
+    
+    private List<RegistrationEntry> registrations = new CopyOnWriteArrayList<RegistrationEntry>();
+    private DirectoryService ds;
+    private NormalizingVisitor filterNormalizer;
+    private Evaluator evaluator;
+    private ExecutorService executor;
+    
+    
+    @Override
+    public void init( DirectoryService ds ) throws Exception
+    {
+        LOG.info( "Initializing ..." );
+        super.init( ds );
+        
+        this.ds = ds;
+        OidRegistry oidRegistry = ds.getRegistries().getOidRegistry();
+        AttributeTypeRegistry attributeRegistry = ds.getRegistries().getAttributeTypeRegistry();
+        NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( attributeRegistry, oidRegistry );
+        filterNormalizer = new NormalizingVisitor( ncn, ds.getRegistries() );
+        evaluator = new ExpressionEvaluator( oidRegistry, attributeRegistry );
+        executor = new ThreadPoolExecutor( 1, 10, 1000, TimeUnit.MILLISECONDS, 
+            new ArrayBlockingQueue<Runnable>( 100 ) );
+        
+        this.ds.setEventService( new DefaultEventService() );
+        LOG.info( "Initialization complete." );
+    }
+
+    
+    private void fire( final OperationContext opContext, EventType type, final DirectoryListener listener )
+    {
+        switch ( type )
+        {
+            case ADD:
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        listener.entryAdded( ( AddOperationContext ) opContext );
+                    }
+                });
+                break;
+            case DELETE:
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        listener.entryDeleted( ( DeleteOperationContext ) opContext );
+                    }
+                });
+                break;
+            case MODIFY:
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        listener.entryModified( ( ModifyOperationContext ) opContext );
+                    }
+                });
+                break;
+            case MOVE:
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        listener.entryMoved( ( MoveOperationContext ) opContext );
+                    }
+                });
+                break;
+            case RENAME:
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        listener.entryRenamed( ( RenameOperationContext ) opContext );
+                    }
+                });
+                break;
+        }
+    }
+    
+    
+    public void add( NextInterceptor next, final AddOperationContext opContext ) throws Exception
+    {
+        next.add( opContext );
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), opContext.getEntry() );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isAdd( registration.getCriteria().getEventMask() ) )
+            {
+                fire( opContext, EventType.ADD, registration.getListener() );
+            }
+        }
+    }
+
+
+    public void delete( NextInterceptor next, final DeleteOperationContext opContext ) throws Exception
+    {
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), opContext.getEntry() );
+        next.delete( opContext );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isDelete( registration.getCriteria().getEventMask() ) )
+            {
+                fire( opContext, EventType.DELETE, registration.getListener() );
+            }
+        }
+    }
+
+
+    public void modify( NextInterceptor next, final ModifyOperationContext opContext ) throws Exception
+    {
+        ClonedServerEntry oriEntry = opContext.lookup( opContext.getDn(), ByPassConstants.LOOKUP_BYPASS );
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), oriEntry );
+        next.modify( opContext );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isModify( registration.getCriteria().getEventMask() ) )
+            {
+                fire( opContext, EventType.MODIFY, registration.getListener() );
+            }
+        }
+    }
+
+
+    public void rename( NextInterceptor next, RenameOperationContext opContext ) throws Exception
+    {
+        ClonedServerEntry oriEntry = opContext.lookup( opContext.getDn(), ByPassConstants.LOOKUP_BYPASS );
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), oriEntry );
+        next.rename( opContext );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isRename( registration.getCriteria().getEventMask() ) )
+            {
+                fire( opContext, EventType.RENAME, registration.getListener() );
+            }
+        }
+    }
+
+
+    public void moveAndRename( NextInterceptor next, final MoveAndRenameOperationContext opContext ) throws Exception
+    {
+        ClonedServerEntry oriEntry = opContext.lookup( opContext.getDn(), ByPassConstants.LOOKUP_BYPASS );
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), oriEntry );
+        next.moveAndRename( opContext );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isMoveAndRename( registration.getCriteria().getEventMask() ) )
+            {
+                executor.execute( new Runnable() 
+                {
+                    public void run()
+                    {
+                        registration.getListener().entryMovedAndRenamed( opContext );
+                    }
+                });
+            }
+        }
+    }
+
+
+    public void move( NextInterceptor next, MoveOperationContext opContext ) throws Exception
+    {
+        ClonedServerEntry oriEntry = opContext.lookup( opContext.getDn(), ByPassConstants.LOOKUP_BYPASS );
+        List<RegistrationEntry> selecting = getSelectingRegistrations( opContext.getDn(), oriEntry );
+        next.move( opContext );
+
+        if ( selecting.isEmpty() )
+        {
+            return;
+        }
+
+        for ( final RegistrationEntry registration : selecting )
+        {
+            if ( EventType.isMove( registration.getCriteria().getEventMask() ) )
+            {
+                fire( opContext, EventType.MOVE, registration.getListener() );
+            }
+        }
+    }
+    
+    
+    List<RegistrationEntry> getSelectingRegistrations( LdapDN name, ServerEntry entry ) throws Exception
+    {
+        if ( registrations.isEmpty() )
+        {
+            return Collections.emptyList();
+        }
+
+        List<RegistrationEntry> selecting = new ArrayList<RegistrationEntry>();
+        
+        for ( RegistrationEntry registration : registrations )
+        {
+            NotificationCriteria criteria = registration.getCriteria();
+            if ( evaluator.evaluate( criteria.getFilter(), criteria.getBase().toNormName(), entry ) )
+            {
+                selecting.add( registration );
+            }
+        }
+
+        return selecting;
+    }
+    
+    
+    // -----------------------------------------------------------------------
+    // EventService Inner Class
+    // -----------------------------------------------------------------------
+    
+    
+    class DefaultEventService implements EventService
+    {
+        /*
+         * Does not need normalization since default values in criteria is used.
+         */
+        public void addListener( DirectoryListener listener )
+        {
+            registrations.add( new RegistrationEntry( listener ) );
+        }
+
+        
+        /*
+         * Normalizes the criteria filter and the base.
+         */
+        public void addListener( DirectoryListener listener, NotificationCriteria criteria ) throws Exception
+        {
+            criteria.getBase().normalize( ds.getRegistries().getAttributeTypeRegistry().getNormalizerMapping() );
+            ExprNode result = ( ExprNode ) criteria.getFilter().accept( filterNormalizer );
+            criteria.setFilter( result );
+            registrations.add( new RegistrationEntry( listener, criteria ) );
+        }
+
+        
+        public void removeListener( DirectoryListener listener )
+        {
+            for ( RegistrationEntry entry : registrations )
+            {
+                if ( entry.getListener() == listener )
+                {
+                    registrations.remove( listener );
+                }
+            }
+        }
+    }
+    
+    
+    class RegistrationEntry
+    {
+        private final DirectoryListener listener;
+        private final NotificationCriteria criteria;
+
+        
+        RegistrationEntry( DirectoryListener listener )
+        {
+            this( listener, new NotificationCriteria() );
+        }
+
+        
+        RegistrationEntry( DirectoryListener listener, NotificationCriteria criteria )
+        {
+            this.listener = listener;
+            this.criteria = criteria;
+        }
+
+
+        /**
+         * @return the criteria
+         */
+        NotificationCriteria getCriteria()
+        {
+            return criteria;
+        }
+
+
+        /**
+         * @return the listener
+         */
+        DirectoryListener getListener()
+        {
+            return listener;
+        }
+    }
+}

Added: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NotificationCriteria.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NotificationCriteria.java?rev=666558&view=auto
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NotificationCriteria.java (added)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/event/NotificationCriteria.java Wed Jun 11 01:00:04 2008
@@ -0,0 +1,168 @@
+/*
+ *   Licensed to the Apache Software Foundation (ASF) under one
+ *   or more contributor license agreements.  See the NOTICE file
+ *   distributed with this work for additional information
+ *   regarding copyright ownership.  The ASF licenses this file
+ *   to you 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.directory.server.core.event;
+
+
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.filter.FilterParser;
+import org.apache.directory.shared.ldap.filter.PresenceNode;
+import org.apache.directory.shared.ldap.filter.SearchScope;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.name.LdapDN;
+
+
+/**
+ * Contains the set of notification criteria required for triggering the 
+ * delivery of change notifications notifications to {@link DirectoryListener}s.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ * @version $Rev$, $Date$
+ */
+public class NotificationCriteria
+{
+    public static final SearchScope DEFAULT_SCOPE = SearchScope.ONELEVEL;
+    public static final AliasDerefMode DEFAULT_ALIAS_DEREF_MODE = AliasDerefMode.DEREF_ALWAYS;
+    public static final LdapDN DEFAULT_BASE = new LdapDN();
+    public static final ExprNode DEFAULT_FILTER = new PresenceNode( SchemaConstants.OBJECT_CLASS_AT_OID );
+    
+    private SearchScope scope = DEFAULT_SCOPE;
+    private AliasDerefMode aliasDerefMode = DEFAULT_ALIAS_DEREF_MODE;
+    private LdapDN base = DEFAULT_BASE;
+    private ExprNode filter = DEFAULT_FILTER;
+    private int eventMask = EventType.ALL_EVENT_TYPES_MASK;
+    
+    
+    /**
+     * @param scope the scope to set
+     */
+    public void setScope( SearchScope scope )
+    {
+        this.scope = scope;
+    }
+    
+    
+    /**
+     * @return the scope
+     */
+    public SearchScope getScope()
+    {
+        return scope;
+    }
+
+
+    /**
+     * @param aliasDerefMode the aliasDerefMode to set
+     */
+    public void setAliasDerefMode( AliasDerefMode aliasDerefMode )
+    {
+        this.aliasDerefMode = aliasDerefMode;
+    }
+
+
+    /**
+     * @return the aliasDerefMode
+     */
+    public AliasDerefMode getAliasDerefMode()
+    {
+        return aliasDerefMode;
+    }
+
+
+    /**
+     * @param base the base to set
+     */
+    public void setBase( LdapDN base )
+    {
+        this.base = base;
+    }
+
+
+    /**
+     * @param base the base to set
+     */
+    public void setBase( String base ) throws Exception
+    {
+        this.base = new LdapDN( base );
+    }
+
+
+    /**
+     * @return the base
+     */
+    public LdapDN getBase()
+    {
+        return base;
+    }
+
+
+    /**
+     * @param filter the filter to set
+     */
+    public void setFilter( ExprNode filter )
+    {
+        this.filter = filter;
+    }
+
+
+    /**
+     * @param filter the filter to set
+     */
+    public void setFilter( String filter ) throws Exception
+    {
+        this.filter = FilterParser.parse( filter );
+    }
+
+
+    /**
+     * @return the filter
+     */
+    public ExprNode getFilter()
+    {
+        return filter;
+    }
+
+
+    /**
+     * @param eventMask the eventMask to set
+     */
+    public void setEventMask( int eventMask )
+    {
+        this.eventMask = eventMask;
+    }
+
+
+    /**
+     * @param eventMask the eventMask to set
+     */
+    public void setEventMask( EventType ...eventTypes )
+    {
+        this.eventMask = EventType.getMask( eventTypes );
+    }
+
+
+    /**
+     * @return the eventMask
+     */
+    public int getEventMask()
+    {
+        return eventMask;
+    }
+}

Modified: directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/DeleteOperationContext.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/DeleteOperationContext.java?rev=666558&r1=666557&r2=666558&view=diff
==============================================================================
--- directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/DeleteOperationContext.java (original)
+++ directory/apacheds/branches/bigbang/core/src/main/java/org/apache/directory/server/core/interceptor/context/DeleteOperationContext.java Wed Jun 11 01:00:04 2008
@@ -21,6 +21,8 @@
 
 
 import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.entry.ClonedServerEntry;
+import org.apache.directory.server.core.partition.ByPassConstants;
 import org.apache.directory.shared.ldap.message.DeleteRequest;
 import org.apache.directory.shared.ldap.message.MessageTypeEnum;
 import org.apache.directory.shared.ldap.name.LdapDN;
@@ -36,6 +38,13 @@
 public class DeleteOperationContext extends AbstractOperationContext
 {
     /**
+     * An optimization added to prevent redundant lookups of the deleted 
+     * entry.
+     */
+    private ClonedServerEntry entry;
+    
+    
+    /**
      * Creates a new instance of DeleteOperationContext.
      */
     public DeleteOperationContext( CoreSession session )
@@ -79,4 +88,30 @@
     {
         return "DeleteContext for DN '" + getDn().getUpName() + "'";
     }
+
+
+    /**
+     * @param entry the entry to set
+     */
+    public void setEntry( ClonedServerEntry entry )
+    {
+        this.entry = entry;
+    }
+
+
+    /**
+     * Gets the deleted entry if cached.  Must be called before deleting the 
+     * entry when the entry member is null or this call will fail.  
+     * 
+     * @return the entry
+     */
+    public ClonedServerEntry getEntry() throws Exception
+    {
+        if ( entry == null )
+        {
+            entry = lookup( getDn(), ByPassConstants.LOOKUP_BYPASS );
+        }
+        
+        return entry;
+    }
 }