Return-Path: Delivered-To: apmail-directory-commits-archive@www.apache.org Received: (qmail 25842 invoked from network); 23 Jul 2010 20:50:16 -0000 Received: from unknown (HELO mail.apache.org) (140.211.11.3) by 140.211.11.9 with SMTP; 23 Jul 2010 20:50:16 -0000 Received: (qmail 88024 invoked by uid 500); 23 Jul 2010 20:50:16 -0000 Delivered-To: apmail-directory-commits-archive@directory.apache.org Received: (qmail 87959 invoked by uid 500); 23 Jul 2010 20:50:16 -0000 Mailing-List: contact commits-help@directory.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@directory.apache.org Delivered-To: mailing list commits@directory.apache.org Received: (qmail 87952 invoked by uid 99); 23 Jul 2010 20:50:16 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 Jul 2010 20:50:16 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 23 Jul 2010 20:50:09 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id A023F23889F1; Fri, 23 Jul 2010 20:49:15 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Fri, 23 Jul 2010 20:49:15 -0000 To: commits@directory.apache.org From: kayyagari@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20100723204915.A023F23889F1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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. + + 2.2.0 + + org.apache.directory.junit @@ -116,6 +120,13 @@ org.apache.directory.client.ldap ldap-client-api + + + net.sf.ehcache + ehcache-core + ${ehcache-version} + + 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 Apache Directory Project + */ +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 Apache Directory Project + */ +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> groups = new HashMap>(); + + /** 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 EMPTY_GROUPS = new HashSet(); + + 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 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( OBJECT_CLASS_AT, new StringValue( + SchemaConstants.GROUP_OF_NAMES_OC ) ) ); + filter.addNode( new EqualityNode( 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 memberSet = new HashSet( 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 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 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 memberSet = new HashSet( 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 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 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 memberSet = ( Set ) 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 memberSet = ( Set ) 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 members = ( Set ) 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 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 memberGroups = null; + + for ( Object obj : ehCache.getKeys() ) + { + String group = ( String ) obj; + Set members = ( Set ) ehCache.get( group ).getValue(); + + if ( members == null ) + { + continue; + } + + if ( members.contains( normMember.getNormName() ) ) + { + if ( memberGroups == null ) + { + memberGroups = new HashSet(); + } + + 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 members = ( Set ) 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 @@ + + + + + + + + + + + + + + \ 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 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ 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 );