Package org.apache.directory.server.core.event

Source Code of org.apache.directory.server.core.event.EventInterceptor$DefaultEventService

/*
*  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.FilterNormalizingVisitor;
import org.apache.directory.server.core.partition.ByPassConstants;
import org.apache.directory.shared.ldap.filter.ExprNode;
import org.apache.directory.shared.ldap.name.DN;
import org.apache.directory.shared.ldap.name.NameComponentNormalizer;
import org.apache.directory.shared.ldap.schema.SchemaManager;
import org.apache.directory.shared.ldap.schema.normalizers.ConcreteNameComponentNormalizer;
import org.apache.directory.shared.ldap.schema.registries.OidRegistry;
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 EventInterceptor extends BaseInterceptor
{
    private final static Logger LOG = LoggerFactory.getLogger( EventInterceptor.class );

   
    private List<RegistrationEntry> registrations = new CopyOnWriteArrayList<RegistrationEntry>();
    private DirectoryService ds;
    private FilterNormalizingVisitor 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.getSchemaManager().getGlobalOidRegistry();
        SchemaManager schemaManager = ds.getSchemaManager();
        NameComponentNormalizer ncn = new ConcreteNameComponentNormalizer( schemaManager );
        filterNormalizer = new FilterNormalizingVisitor( ncn, schemaManager );
        evaluator = new ExpressionEvaluator( oidRegistry, schemaManager );
        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;
        }

        // Get the modified entry
        ClonedServerEntry alteredEntry = opContext.lookup( opContext.getDn(), ByPassConstants.LOOKUP_BYPASS );
        opContext.setAlteredEntry( alteredEntry );

        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;
        }

        // Get the modifed entry
        ClonedServerEntry alteredEntry = opContext.lookup( opContext.getNewDn(), ByPassConstants.LOOKUP_BYPASS );
        opContext.setAlteredEntry( alteredEntry );
       
        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;
        }

        opContext.setAlteredEntry( opContext.lookup( opContext.getNewDn(), ByPassConstants.LOOKUP_BYPASS ) );
       
        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( DN 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.getSchemaManager().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( entry );
                }
            }
        }


        public List<RegistrationEntry> getRegistrationEntries()
        {
            return Collections.unmodifiableList( registrations );
        }
    }
}
TOP

Related Classes of org.apache.directory.server.core.event.EventInterceptor$DefaultEventService

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.