You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by ka...@apache.org on 2010/07/23 22:49:15 UTC

svn commit: r967256 - in /directory/apacheds/branches/apacheds-cache-experiment: core-api/ core-api/src/main/java/org/apache/directory/server/core/ core-api/src/main/java/org/apache/directory/server/core/cache/ core-api/src/main/resources/ core-api/src...

Author: kayyagari
Date: Fri Jul 23 20:49:14 2010
New Revision: 967256

URL: http://svn.apache.org/viewvc?rev=967256&view=rev
Log:
o added ehcache based cache service
o moved GroupCache to core-api
o added a new method to DirectoryService interface to get the cache service
o added a default cache configuration file
o updated AciAuthorizationInterceptor to use the new ehcache based GroupCache
o added dependency on ehcache-core

Added:
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/CacheService.java
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/GroupCache.java
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/directory-cacheservice.xml
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/ehcache.xsd
Removed:
    directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/GroupCache.java
Modified:
    directory/apacheds/branches/apacheds-cache-experiment/core-api/pom.xml
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/DirectoryService.java
    directory/apacheds/branches/apacheds-cache-experiment/core-api/src/test/java/org/apache/directory/server/core/MockDirectoryService.java
    directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java

Modified: directory/apacheds/branches/apacheds-cache-experiment/core-api/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/pom.xml?rev=967256&r1=967255&r2=967256&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/pom.xml (original)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/pom.xml Fri Jul 23 20:49:14 2010
@@ -35,6 +35,10 @@
     Contains interfaces and helper classes that are part of the ApacheDS Core API.
   </description>
 
+  <properties>
+    <ehcache-version>2.2.0</ehcache-version>
+  </properties>
+  
   <dependencies>
     <dependency>
       <groupId>org.apache.directory.junit</groupId>
@@ -116,6 +120,13 @@
       <groupId>org.apache.directory.client.ldap</groupId>
       <artifactId>ldap-client-api</artifactId>
     </dependency>
+        
+    <dependency>
+       <groupId>net.sf.ehcache</groupId>
+       <artifactId>ehcache-core</artifactId>
+       <version>${ehcache-version}</version>
+   </dependency>
+   
   </dependencies>
 
   <build>

Modified: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/DirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/DirectoryService.java?rev=967256&r1=967255&r2=967256&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/DirectoryService.java (original)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/DirectoryService.java Fri Jul 23 20:49:14 2010
@@ -24,6 +24,7 @@ import java.io.File;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.directory.server.core.cache.CacheService;
 import org.apache.directory.server.core.changelog.ChangeLog;
 import org.apache.directory.server.core.entry.ServerEntryFactory;
 import org.apache.directory.server.core.event.EventService;
@@ -517,4 +518,9 @@ public interface DirectoryService extend
      * @return the syncPeriodMillis
      */
     long getSyncPeriodMillis();
+
+    /**
+     * @return the cache service
+     */
+    CacheService getCacheService();
 }

Added: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/CacheService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/CacheService.java?rev=967256&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/CacheService.java (added)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/CacheService.java Fri Jul 23 20:49:14 2010
@@ -0,0 +1,131 @@
+/*
+ *   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.cache;
+
+
+import java.io.File;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.CacheManager;
+import net.sf.ehcache.Status;
+
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A ehcache based cache service to be used for various caching requirement in the server. 
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CacheService
+{
+
+    private static final Logger LOG = LoggerFactory.getLogger( CacheService.class );
+
+    /** the ehcache configuration file */
+    private File configFile;
+
+    /** the ehcache cache manager */
+    private CacheManager cacheManager;
+
+    /** directory service */
+    private DirectoryService dirService;
+
+    /** group cache */
+    private GroupCache groupCache;
+
+
+    public CacheService()
+    {
+    }
+
+
+    public void initialize( DirectoryService dirService )
+    {
+        if ( ( cacheManager != null ) && ( cacheManager.getStatus() == Status.STATUS_ALIVE ) )
+        {
+            LOG.warn( "cache service was already initialized and is alive" );
+            return;
+        }
+
+        if ( configFile == null || !configFile.exists() )
+        {
+            LOG.info( "no custom cache configuration was set, loading the default cache configuration" );
+
+            cacheManager = new CacheManager( getClass().getClassLoader().getResource( "directory-cacheservice.xml" ) );
+        }
+        else
+        {
+            LOG.info( "loading cache configuration from the file {}", configFile );
+
+            cacheManager = new CacheManager( configFile.getAbsolutePath() );
+        }
+
+        this.dirService = dirService;
+    }
+
+
+    public void destroy()
+    {
+        if( cacheManager.getStatus() == Status.STATUS_ALIVE )
+        {
+            LOG.info( "destroying the cache service" );
+            
+            groupCache = null;
+            
+            cacheManager.removalAll();
+            
+            cacheManager.shutdown();
+        }
+    }
+
+
+    public GroupCache getGroupCache() throws LdapException
+    {
+        if ( groupCache != null )
+        {
+            LOG.info( "returning the old group cache" );
+            return groupCache;
+        }
+
+        Cache ehCache = cacheManager.getCache( "groupCache" );
+        LOG.info( "creating a new group cache {}", ehCache.getStatus() );
+
+        groupCache = new GroupCache( dirService.getAdminSession(), ehCache );
+
+        return groupCache;
+    }
+
+
+    public void setConfigFile( File configFile )
+    {
+        if ( configFile == null )
+        {
+            throw new IllegalArgumentException( "invalid configuration file, null" );
+        }
+
+        this.configFile = configFile;
+    }
+
+}

Added: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/GroupCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/GroupCache.java?rev=967256&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/GroupCache.java (added)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/java/org/apache/directory/server/core/cache/GroupCache.java Fri Jul 23 20:49:14 2010
@@ -0,0 +1,582 @@
+/*
+ *  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.cache;
+
+
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.directory.SearchControls;
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Modification;
+import org.apache.directory.shared.ldap.entry.ModificationOperation;
+import org.apache.directory.shared.ldap.entry.StringValue;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.exception.LdapOperationException;
+import org.apache.directory.shared.ldap.filter.BranchNode;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.OrNode;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ * A cache for tracking static group membership.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class GroupCache
+{
+    /** the logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( GroupCache.class );
+
+    /** Speedup for logs */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** String key for the DN of a group to a Set (HashSet) for the Strings of member DNs */
+//    private final Map<String, Set<String>> groups = new HashMap<String, Set<String>>();
+
+    /** a handle on the partition nexus */
+    private final PartitionNexus nexus;
+
+    /** A storage for the ObjectClass attributeType */
+    private AttributeType OBJECT_CLASS_AT;
+
+    /** A storage for the member attributeType */
+    private AttributeType MEMBER_AT;
+
+    /** A storage for the uniqueMember attributeType */
+    private AttributeType UNIQUE_MEMBER_AT;
+
+    /**
+     * the schema manager
+     */
+    private SchemaManager schemaManager;
+
+    /** the normalized dn of the administrators group */
+    private DN administratorsGroupDn;
+
+    private static final Set<DN> EMPTY_GROUPS = new HashSet<DN>();
+
+    private Cache ehCache;
+
+    /**
+     * Creates a static group cache.
+     *
+     * @param directoryService the directory service core
+     * @throws LdapException if there are failures on initialization 
+     */
+    protected GroupCache( CoreSession session, Cache ehCache ) throws LdapException
+    {
+        schemaManager = session.getDirectoryService().getSchemaManager();
+        nexus = session.getDirectoryService().getPartitionNexus();
+        OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+        MEMBER_AT = schemaManager.getAttributeType( SchemaConstants.MEMBER_AT );
+        UNIQUE_MEMBER_AT = schemaManager.getAttributeType( SchemaConstants.UNIQUE_MEMBER_AT );
+
+        // stuff for dealing with the admin group
+        administratorsGroupDn = parseNormalized( ServerDNConstants.ADMINISTRATORS_GROUP_DN );
+
+        this.ehCache = ehCache;
+        
+        initialize( session );
+    }
+
+
+    private DN parseNormalized( String name ) throws LdapException
+    {
+        DN dn = new DN( name, schemaManager );
+        return dn;
+    }
+
+
+    private void initialize( CoreSession session ) throws LdapException
+    {
+        // search all naming contexts for static groups and generate
+        // normalized sets of members to cache within the map
+
+        Set<String> suffixes = nexus.listSuffixes();
+
+        for ( String suffix:suffixes )
+        {
+            // moving the filter creation to inside loop to fix DIRSERVER-1121
+            // didn't use clone() cause it is creating List objects, which IMO is not worth calling
+            // in this initialization phase
+            BranchNode filter = new OrNode();
+            filter.addNode( new EqualityNode<String>( OBJECT_CLASS_AT, new StringValue(
+                SchemaConstants.GROUP_OF_NAMES_OC ) ) );
+            filter.addNode( new EqualityNode<String>( OBJECT_CLASS_AT, new StringValue(
+                SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC ) ) );
+
+            DN baseDn = new DN( suffix, schemaManager );
+            SearchControls ctls = new SearchControls();
+            ctls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+            
+            SearchOperationContext searchOperationContext = new SearchOperationContext( session,
+                baseDn, filter, ctls );
+            searchOperationContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
+            EntryFilteringCursor results = nexus.search( searchOperationContext );
+
+            try
+            {
+                while ( results.next() )
+                {
+                    Entry result = results.get();
+                    DN groupDn = result.getDn().normalize( schemaManager.getNormalizerMapping() );
+                    EntryAttribute members = getMemberAttribute( result );
+    
+                    if ( members != null )
+                    {
+                        Set<String> memberSet = new HashSet<String>( members.size() );
+                        addMembers( memberSet, members );
+                        
+                        Element cacheElement = new Element( groupDn.getNormName(), memberSet );
+                        ehCache.put( cacheElement );
+                    }
+                    else
+                    {
+                        LOG.warn( "Found group '{}' without any member or uniqueMember attributes", groupDn.getName() );
+                    }
+                }
+    
+                results.close();
+            }
+            catch ( Exception e )
+            {
+                LdapOperationException le = new LdapOperationException( e.getMessage() );
+                le.initCause( e );
+                throw le;
+            }
+        }
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "group cache contents on startup:\n {}", ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+        }
+    }
+
+
+    /**
+     * Gets the member attribute regardless of whether groupOfNames or
+     * groupOfUniqueNames is used.
+     *
+     * @param entry the entry inspected for member attributes
+     * @return the member attribute
+     */
+    private EntryAttribute getMemberAttribute( Entry entry ) throws LdapException
+    {
+        EntryAttribute oc = entry.get( OBJECT_CLASS_AT );
+
+        if ( oc == null )
+        {
+            EntryAttribute member = entry.get( MEMBER_AT );
+
+            if ( member != null )
+            {
+                return member;
+            }
+
+            EntryAttribute uniqueMember = entry.get( UNIQUE_MEMBER_AT );
+
+            if ( uniqueMember != null )
+            {
+                return uniqueMember;
+            }
+
+            return null;
+        }
+
+        if ( oc.contains( SchemaConstants.GROUP_OF_NAMES_OC ) || oc.contains( SchemaConstants.GROUP_OF_NAMES_OC_OID ) )
+        {
+            return entry.get( MEMBER_AT );
+        }
+
+        if ( oc.contains( SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC )
+            || oc.contains( SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC_OID ) )
+        {
+            return entry.get( UNIQUE_MEMBER_AT );
+        }
+
+        return null;
+    }
+
+
+    /**
+     * Adds normalized member DNs to the set of normalized member names.
+     *
+     * @param memberSet the set of member Dns (Strings)
+     * @param members the member attribute values being added
+     * @throws LdapException if there are problems accessing the attr values
+     */
+    private void addMembers( Set<String> memberSet, EntryAttribute members ) throws LdapException
+    {
+        for ( Value<?> value : members )
+        {
+
+            // get and normalize the DN of the member
+            String memberDn = value.getString();
+
+            try
+            {
+                memberDn = parseNormalized( memberDn ).getNormName();
+            }
+            catch ( LdapException e )
+            {
+                LOG.warn( "Malformed member DN in groupOf[Unique]Names entry.  Member not added to GroupCache.", e );
+            }
+
+            memberSet.add( memberDn );
+        }
+    }
+
+
+    /**
+     * Removes a set of member names from an existing set.
+     *
+     * @param memberSet the set of normalized member DNs
+     * @param members the set of member values
+     * @throws LdapException if there are problems accessing the attr values
+     */
+    private void removeMembers( Set<String> memberSet, EntryAttribute members ) throws LdapException
+    {
+        for ( Value<?> value : members )
+        {
+            // get and normalize the DN of the member
+            String memberDn = value.getString();
+
+            try
+            {
+                memberDn = parseNormalized( memberDn ).getNormName();
+            }
+            catch ( LdapException e )
+            {
+                LOG.warn( "Malformed member DN in groupOf[Unique]Names entry.  Member not removed from GroupCache.", e );
+            }
+
+            memberSet.remove( memberDn );
+        }
+    }
+
+
+    /**
+     * Adds a groups members to the cache.  Called by interceptor to account for new
+     * group additions.
+     *
+     * @param name the user provided name for the group entry
+     * @param entry the group entry's attributes
+     * @throws LdapException if there are problems accessing the attr values
+     */
+    public void groupAdded( DN name, Entry entry ) throws LdapException
+    {
+        EntryAttribute members = getMemberAttribute( entry );
+
+        if ( members == null )
+        {
+            return;
+        }
+
+        Set<String> memberSet = new HashSet<String>( members.size() );
+        addMembers( memberSet, members );
+        
+        Element cacheElement = new Element( name.getNormName(), memberSet );
+        ehCache.put( cacheElement );
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "group cache contents after adding '{}' :\n {}", name.getName(), ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+        }
+    }
+
+
+    /**
+     * Deletes a group's members from the cache.  Called by interceptor to account for
+     * the deletion of groups.
+     *
+     * @param name the normalized DN of the group entry
+     * @param entry the attributes of entry being deleted
+     */
+    public void groupDeleted( DN name, Entry entry ) throws LdapException
+    {
+        EntryAttribute members = getMemberAttribute( entry );
+
+        if ( members == null )
+        {
+            return;
+        }
+
+        ehCache.remove( name.getNormName() );
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "group cache contents after deleting '{}' :\n {}", name.getName(), ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+        }
+    }
+
+
+    /**
+     * Utility method to modify a set of member names based on a modify operation
+     * that changes the members of a group.
+     *
+     * @param memberSet the set of members to be altered
+     * @param modOp the type of modify operation being performed
+     * @param members the members being added, removed or replaced
+     * @throws LdapException if there are problems accessing attribute values
+     */
+    private void modify( Set<String> memberSet, ModificationOperation modOp, EntryAttribute members )
+        throws LdapException
+    {
+
+        switch ( modOp )
+        {
+            case ADD_ATTRIBUTE:
+                addMembers( memberSet, members );
+                break;
+
+            case REPLACE_ATTRIBUTE:
+                if ( members.size() > 0 )
+                {
+                    memberSet.clear();
+                    addMembers( memberSet, members );
+                }
+
+                break;
+
+            case REMOVE_ATTRIBUTE:
+                removeMembers( memberSet, members );
+                break;
+
+            default:
+                throw new InternalError( I18n.err( I18n.ERR_235, modOp ) );
+        }
+    }
+
+
+    /**
+     * Modifies the cache to reflect changes via modify operations to the group entries.
+     * Called by the interceptor to account for modify ops on groups.
+     *
+     * @param name the normalized name of the group entry modified
+     * @param mods the modification operations being performed
+     * @param entry the group entry being modified
+     * @throws LdapException if there are problems accessing attribute  values
+     */
+    public void groupModified( DN name, List<Modification> mods, Entry entry, SchemaManager schemaManager )
+        throws LdapException
+    {
+        EntryAttribute members = null;
+        String memberAttrId = null;
+        EntryAttribute oc = entry.get( OBJECT_CLASS_AT );
+
+        if ( oc.contains( SchemaConstants.GROUP_OF_NAMES_OC ) )
+        {
+            members = entry.get( MEMBER_AT );
+            memberAttrId = SchemaConstants.MEMBER_AT;
+        }
+
+        if ( oc.contains( SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC ) )
+        {
+            members = entry.get( UNIQUE_MEMBER_AT );
+            memberAttrId = SchemaConstants.UNIQUE_MEMBER_AT;
+        }
+
+        if ( members == null )
+        {
+            return;
+        }
+
+        for ( Modification modification : mods )
+        {
+            if ( memberAttrId.equalsIgnoreCase( modification.getAttribute().getId() ) )
+            {
+                Set<String> memberSet = ( Set<String> ) ehCache.get( name.getNormName() ).getValue();
+
+                if ( memberSet != null )
+                {
+                    modify( memberSet, modification.getOperation(), modification.getAttribute() );
+                }
+
+                break;
+            }
+        }
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "group cache contents after modifying '{}' :\n {}", name.getName(), ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+        }
+    }
+
+
+    /**
+     * Modifies the cache to reflect changes via modify operations to the group entries.
+     * Called by the interceptor to account for modify ops on groups.
+     *
+     * @param name the normalized name of the group entry modified
+     * @param modOp the modify operation being performed
+     * @param mods the modifications being performed
+     * @throws LdapException if there are problems accessing attribute  values
+     */
+    public void groupModified( DN name, ModificationOperation modOp, Entry mods ) throws LdapException
+    {
+        EntryAttribute members = getMemberAttribute( mods );
+
+        if ( members == null )
+        {
+            return;
+        }
+
+        Set<String> memberSet = ( Set<String> ) ehCache.get( name.getNormName() ).getValue();
+
+        if ( memberSet != null )
+        {
+            modify( memberSet, modOp, members );
+        }
+
+        if ( IS_DEBUG )
+        {
+            LOG.debug( "group cache contents after modifying '{}' :\n {}", name.getName(), ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+        }
+    }
+
+
+    /**
+     * An optimization.  By having this method here we can directly access the group
+     * membership information and lookup to see if the principalDn is contained within.
+     * 
+     * @param principalDn the normalized DN of the user to check if they are an admin
+     * @return true if the principal is an admin or the admin
+     */
+    public final boolean isPrincipalAnAdministrator( DN principalDn )
+    {
+        if ( principalDn.getNormName().equals( ServerDNConstants.ADMIN_SYSTEM_DN_NORMALIZED ) )
+        {
+            return true;
+        }
+
+        Set<String> members = ( Set<String> ) ehCache.get( administratorsGroupDn.getNormName() ).getValue();
+
+        if ( members == null )
+        {
+            LOG.warn( "What do you mean there is no administrators group? This is bad news." );
+            return false;
+        }
+
+        return members.contains( principalDn.getNormName() );
+    }
+
+
+    /**
+     * Gets the set of groups a user is a member of.  The groups are returned
+     * as normalized Name objects within the set.
+     *
+     * @param member the member (user) to get the groups for
+     * @return a Set of Name objects representing the groups
+     * @throws LdapException if there are problems accessing attribute  values
+     */
+    public Set<DN> getGroups( String member ) throws LdapException
+    {
+        DN normMember;
+
+        try
+        {
+            normMember = parseNormalized( member );
+        }
+        catch ( LdapException e )
+        {
+            LOG
+                .warn(
+                    "Malformed member DN.  Could not find groups for member '{}' in GroupCache. Returning empty set for groups!",
+                    member, e );
+            return EMPTY_GROUPS;
+        }
+
+        Set<DN> memberGroups = null;
+
+        for ( Object obj : ehCache.getKeys() )
+        {
+            String group = ( String ) obj;
+            Set<String> members = ( Set<String> ) ehCache.get( group ).getValue();
+
+            if ( members == null )
+            {
+                continue;
+            }
+
+            if ( members.contains( normMember.getNormName() ) )
+            {
+                if ( memberGroups == null )
+                {
+                    memberGroups = new HashSet<DN>();
+                }
+
+                memberGroups.add( parseNormalized( group ) );
+            }
+        }
+
+        if ( memberGroups == null )
+        {
+            return EMPTY_GROUPS;
+        }
+
+        return memberGroups;
+    }
+
+
+    public boolean groupRenamed( DN oldName, DN newName )
+    {
+        Element membersElement = ehCache.get( oldName.getNormName() );
+        
+        if ( membersElement != null )
+        {
+            Set<String> members = ( Set<String> ) membersElement.getValue();
+            
+            ehCache.remove( oldName.getNormName() );
+            
+            Element cacheElement = new Element( newName.getNormName(), members );
+            ehCache.put( cacheElement );
+
+            if ( IS_DEBUG )
+            {
+                LOG.debug( "group cache contents after renaming '{}' :\n{}", oldName.getName(), ehCache.getAllWithLoader( ehCache.getKeys(), null ) );
+            }
+
+            return true;
+        }
+
+        return false;
+    }
+}

Added: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/directory-cacheservice.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/directory-cacheservice.xml?rev=967256&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/directory-cacheservice.xml (added)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/directory-cacheservice.xml Fri Jul 23 20:49:14 2010
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>       
+<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:noNamespaceSchemaLocation="ehcache.xsd"
+         updateCheck="false" monitoring="autodetect"
+         dynamicConfig="true" >
+   
+    <diskStore path="java.io.tmpdir"/>
+
+    <cacheManagerEventListenerFactory class="" properties=""/>
+
+    <!--
+    Mandatory Default Cache configuration. These settings will be applied to caches
+    created programmtically using CacheManager.add(String cacheName).
+
+    The defaultCache has an implicit name "default" which is a reserved cache name.
+    -->
+    <defaultCache
+           maxElementsInMemory="0"
+           eternal="false"
+           overflowToDisk="true"
+           timeToIdleSeconds="1200"
+           timeToLiveSeconds="1200">
+    </defaultCache>
+
+    <!--
+    Sample cache named sampleCache1
+    This cache contains a maximum in memory of 10000 elements, and will expire
+    an element if it is idle for more than 5 minutes and lives for more than
+    10 minutes.
+
+    If there are more than 10000 elements it will overflow to the
+    disk cache, which in this configuration will go to wherever java.io.tmp is
+    defined on your system. On a standard Linux system this will be /tmp"
+    -->
+    <cache name="groupCache"
+           maxElementsInMemory="10000"
+           maxElementsOnDisk="1000"
+           eternal="true"
+           overflowToDisk="true"
+           diskSpoolBufferSizeMB="20"
+           timeToIdleSeconds="300"
+           timeToLiveSeconds="600"/>
+</ehcache>
\ No newline at end of file

Added: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/ehcache.xsd
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/ehcache.xsd?rev=967256&view=auto
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/ehcache.xsd (added)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/main/resources/ehcache.xsd Fri Jul 23 20:49:14 2010
@@ -0,0 +1,263 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" version="1.7">
+
+    <xs:element name="ehcache">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="1" minOccurs="0" ref="diskStore"/>
+                <xs:element maxOccurs="1" minOccurs="0" ref="transactionManagerLookup"/>
+                <xs:element maxOccurs="1" minOccurs="0" ref="cacheManagerEventListenerFactory"/>
+                <xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerProviderFactory"/>
+                <xs:element maxOccurs="unbounded" minOccurs="0" ref="cacheManagerPeerListenerFactory"/>
+                <xs:element maxOccurs="1" minOccurs="0" ref="terracottaConfig"/>
+                <xs:element ref="defaultCache"/>
+                <xs:element maxOccurs="unbounded" minOccurs="0" ref="cache"/>
+            </xs:sequence>
+            <xs:attribute name="name" use="optional"/>
+            <xs:attribute default="true" name="updateCheck" type="xs:boolean" use="optional"/>
+            <xs:attribute default="autodetect" name="monitoring" type="monitoringType" use="optional"/>
+            <xs:attribute default="true" name="dynamicConfig" type="xs:boolean" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="diskStore">
+        <xs:complexType>
+            <xs:attribute name="path" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+     <xs:element name="transactionManagerLookup">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheManagerEventListenerFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheManagerPeerProviderFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheManagerPeerListenerFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="terracottaConfig">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element maxOccurs="1" minOccurs="0" name="tc-config">
+                    <xs:complexType>
+                        <xs:sequence>
+                            <xs:any maxOccurs="unbounded" minOccurs="0" processContents="skip"/>
+                        </xs:sequence>
+                    </xs:complexType>
+                </xs:element>
+            </xs:sequence>
+            <xs:attribute default="localhost:9510" name="url" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <!-- add clone support for addition of cacheExceptionHandler. Important! -->
+    <xs:element name="defaultCache">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/>
+            </xs:sequence>
+            <xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/>
+            <xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/>
+            <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
+            <xs:attribute name="eternal" type="xs:boolean" use="required"/>
+            <xs:attribute name="maxElementsInMemory" type="xs:integer" use="required"/>
+            <xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/>
+            <xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/>
+            <xs:attribute name="overflowToDisk" type="xs:boolean" use="required"/>
+            <xs:attribute name="timeToIdleSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="timeToLiveSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="maxElementsOnDisk" type="xs:integer" use="optional"/>
+            <xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/>
+            <xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/>
+            <xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/>
+            <xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cache">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheEventListenerFactory"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheExtensionFactory"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheLoaderFactory"/>
+                <xs:element minOccurs="0" maxOccurs="unbounded" ref="cacheDecoratorFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="bootstrapCacheLoaderFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cacheExceptionHandlerFactory"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="terracotta"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriter"/>
+                <xs:element minOccurs="0" maxOccurs="1" ref="copyStrategy"/>
+            </xs:sequence>
+            <xs:attribute name="diskExpiryThreadIntervalSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="diskSpoolBufferSizeMB" type="xs:integer" use="optional"/>
+            <xs:attribute name="diskPersistent" type="xs:boolean" use="optional"/>
+            <xs:attribute name="diskAccessStripes" type="xs:integer" use="optional" default="1"/>
+            <xs:attribute name="eternal" type="xs:boolean" use="required"/>
+            <xs:attribute name="maxElementsInMemory" type="xs:integer" use="required"/>
+            <xs:attribute name="memoryStoreEvictionPolicy" type="xs:string" use="optional"/>
+            <xs:attribute name="clearOnFlush" type="xs:boolean" use="optional"/>
+            <xs:attribute name="name" type="xs:string" use="required"/>
+            <xs:attribute name="overflowToDisk" type="xs:boolean" use="required"/>
+            <xs:attribute name="timeToIdleSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="timeToLiveSeconds" type="xs:integer" use="optional"/>
+            <xs:attribute name="maxElementsOnDisk" type="xs:integer" use="optional"/>
+            <xs:attribute name="transactionalMode" type="transactionalMode" use="optional" default="off"/>
+            <xs:attribute name="statistics" type="xs:boolean" use="optional" default="false"/>
+            <xs:attribute name="copyOnRead" type="xs:boolean" use="optional" default="false"/>
+            <xs:attribute name="copyOnWrite" type="xs:boolean" use="optional" default="false"/>
+            <xs:attribute name="logging" type="xs:boolean" use="optional" default="false"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheEventListenerFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+            <xs:attribute name="listenFor" use="optional" type="notificationScope" default="all"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="bootstrapCacheLoaderFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheExtensionFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheExceptionHandlerFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheLoaderFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="cacheDecoratorFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:element name="terracotta">
+        <xs:complexType>
+            <xs:attribute name="clustered" use="optional" type="xs:boolean" default="true"/>
+            <xs:attribute name="valueMode" use="optional" type="terracottaCacheValueType" default="serialization"/>
+            <xs:attribute name="coherentReads" use="optional" type="xs:boolean" default="true"/>
+            <xs:attribute name="localKeyCache" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="localKeyCacheSize" use="optional" type="xs:positiveInteger" default="300000"/>
+            <xs:attribute name="orphanEviction" use="optional" type="xs:boolean" default="true"/>
+            <xs:attribute name="orphanEvictionPeriod" use="optional" type="xs:positiveInteger" default="4"/>
+            <xs:attribute name="copyOnRead" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="coherent" use="optional" type="xs:boolean" default="true"/>
+            <xs:attribute name="synchronousWrites" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="storageStrategy" use="optional" type="storageStrategyType" default="classic"/>
+            <xs:attribute name="concurrency" use="optional" type="xs:nonNegativeInteger" default="0"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:simpleType name="monitoringType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="autodetect"/>
+            <xs:enumeration value="on"/>
+            <xs:enumeration value="off"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="terracottaCacheValueType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="serialization"/>
+            <xs:enumeration value="identity"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:simpleType name="storageStrategyType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="classic"/>
+            <xs:enumeration value="DCV2"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:simpleType name="transactionalMode">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="off"/>
+            <xs:enumeration value="xa"/>
+        </xs:restriction>
+    </xs:simpleType>
+
+    <xs:element name="cacheWriter">
+        <xs:complexType>
+            <xs:sequence>
+                <xs:element minOccurs="0" maxOccurs="1" ref="cacheWriterFactory"/>
+            </xs:sequence>
+            <xs:attribute name="writeMode" use="optional" type="writeModeType" default="write-through"/>
+            <xs:attribute name="notifyListenersOnException" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="minWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/>
+            <xs:attribute name="maxWriteDelay" use="optional" type="xs:nonNegativeInteger" default="1"/>
+            <xs:attribute name="rateLimitPerSecond" use="optional" type="xs:nonNegativeInteger" default="0"/>
+            <xs:attribute name="writeCoalescing" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="writeBatching" use="optional" type="xs:boolean" default="false"/>
+            <xs:attribute name="writeBatchSize" use="optional" type="xs:positiveInteger" default="1"/>
+            <xs:attribute name="retryAttempts" use="optional" type="xs:nonNegativeInteger" default="0"/>
+            <xs:attribute name="retryAttemptDelaySeconds" use="optional" type="xs:nonNegativeInteger" default="1"/>
+        </xs:complexType>
+    </xs:element>
+    <xs:simpleType name="writeModeType">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="write-through"/>
+            <xs:enumeration value="write-behind"/>
+        </xs:restriction>
+    </xs:simpleType>
+    <xs:element name="cacheWriterFactory">
+        <xs:complexType>
+            <xs:attribute name="class" use="required"/>
+            <xs:attribute name="properties" use="optional"/>
+            <xs:attribute name="propertySeparator" use="optional"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:element name="copyStrategy">
+        <xs:complexType>
+            <xs:attribute name="class" use="required" type="xs:string"/>
+        </xs:complexType>
+    </xs:element>
+
+    <xs:simpleType name="notificationScope">
+        <xs:restriction base="xs:string">
+            <xs:enumeration value="local"/>
+            <xs:enumeration value="remote"/>
+            <xs:enumeration value="all"/>
+        </xs:restriction>
+    </xs:simpleType>
+</xs:schema>
\ No newline at end of file

Modified: directory/apacheds/branches/apacheds-cache-experiment/core-api/src/test/java/org/apache/directory/server/core/MockDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core-api/src/test/java/org/apache/directory/server/core/MockDirectoryService.java?rev=967256&r1=967255&r2=967256&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core-api/src/test/java/org/apache/directory/server/core/MockDirectoryService.java (original)
+++ directory/apacheds/branches/apacheds-cache-experiment/core-api/src/test/java/org/apache/directory/server/core/MockDirectoryService.java Fri Jul 23 20:49:14 2010
@@ -27,6 +27,7 @@ import java.util.Set;
 
 import javax.naming.ldap.LdapContext;
 
+import org.apache.directory.server.core.cache.CacheService;
 import org.apache.directory.server.core.changelog.ChangeLog;
 import org.apache.directory.server.core.event.EventService;
 import org.apache.directory.server.core.interceptor.Interceptor;
@@ -485,4 +486,10 @@ public class MockDirectoryService implem
         // TODO Auto-generated method stub
         
     }
+    
+
+    public CacheService getCacheService()
+    {
+        return null;
+    }
 }

Modified: directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=967256&r1=967255&r2=967256&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Fri Jul 23 20:49:14 2010
@@ -28,7 +28,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashSet;
 import java.util.List;
-import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
@@ -38,6 +37,7 @@ import org.apache.directory.server.const
 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
+import org.apache.directory.server.core.cache.CacheService;
 import org.apache.directory.server.core.changelog.ChangeLog;
 import org.apache.directory.server.core.changelog.ChangeLogEvent;
 import org.apache.directory.server.core.changelog.ChangeLogInterceptor;
@@ -92,7 +92,6 @@ import org.apache.directory.shared.ldap.
 import org.apache.directory.shared.ldap.name.DN;
 import org.apache.directory.shared.ldap.name.RDN;
 import org.apache.directory.shared.ldap.schema.SchemaManager;
-import org.apache.directory.shared.ldap.schema.normalizers.OidNormalizer;
 import org.apache.directory.shared.ldap.util.DateUtils;
 import org.apache.directory.shared.ldap.util.StringTools;
 import org.slf4j.Logger;
@@ -232,6 +231,9 @@ public class DefaultDirectoryService imp
     /** the value of last successful add/update operation's CSN */
     private String contextCsn;
     
+    /** the ehcache based cache service */
+    private CacheService cacheService;
+    
     /**
      * The synchronizer thread. It flush data on disk periodically.
      */
@@ -998,6 +1000,7 @@ public class DefaultDirectoryService imp
         // And shutdown the server
         // --------------------------------------------------------------------
         interceptorChain.destroy();
+        cacheService.destroy();
         started = false;
         setDefaultInterceptorConfigurations();
     }
@@ -1410,6 +1413,9 @@ public class DefaultDirectoryService imp
         
         firstStart = createBootstrapEntries();
 
+        cacheService = new CacheService();
+        cacheService.initialize( this );
+        
         interceptorChain = new InterceptorChain();
         interceptorChain.init( this );
 
@@ -1698,4 +1704,10 @@ public class DefaultDirectoryService imp
     {
         this.contextCsn = lastKnownCsn;
     }
+
+
+    public CacheService getCacheService()
+    {
+        return cacheService;
+    }
 }

Modified: directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java?rev=967256&r1=967255&r2=967256&view=diff
==============================================================================
--- directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java (original)
+++ directory/apacheds/branches/apacheds-cache-experiment/core/src/main/java/org/apache/directory/server/core/authz/AciAuthorizationInterceptor.java Fri Jul 23 20:49:14 2010
@@ -37,6 +37,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.LdapPrincipal;
 import org.apache.directory.server.core.authz.support.ACDFEngine;
 import org.apache.directory.server.core.authz.support.AciContext;
+import org.apache.directory.server.core.cache.GroupCache;
 import org.apache.directory.server.core.entry.ClonedServerEntry;
 import org.apache.directory.server.core.entry.ServerEntryUtils;
 import org.apache.directory.server.core.filtering.EntryFilter;
@@ -197,7 +198,7 @@ public class AciAuthorizationInterceptor
 
         // Create the caches
         tupleCache = new TupleCache( adminSession );
-        groupCache = new GroupCache( adminSession );
+        groupCache = directoryService.getCacheService().getGroupCache();
 
         // look up some constant information
         OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );