You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2005/09/26 14:04:31 UTC

svn commit: r291602 - in /directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz: ./ support/

Author: trustin
Date: Mon Sep 26 05:04:21 2005
New Revision: 291602

URL: http://svn.apache.org/viewcvs?rev=291602&view=rev
Log:
* Refactored ACDFEngine
** Extracted each tuple filtering phase into multiple ACITupleFilters.
** Moved ACDFEngine and filters into authz.support package.

Added:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java
      - copied, changed from r291569, directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/ACDFEngine.java
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java   (with props)
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java   (with props)
Removed:
    directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/ACDFEngine.java

Copied: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java (from r291569, directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/ACDFEngine.java)
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java?p2=directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java&p1=directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/ACDFEngine.java&r1=291569&r2=291602&rev=291602&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/ACDFEngine.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACDFEngine.java Mon Sep 26 05:04:21 2005
@@ -1,4 +1,6 @@
 /*
+ *   @(#) $Id$
+ *   
  *   Copyright 2004 The Apache Software Foundation
  *
  *   Licensed under the Apache License, Version 2.0 (the "License");
@@ -14,33 +16,21 @@
  *   limitations under the License.
  *
  */
-package org.apache.ldap.server.authz;
+package org.apache.ldap.server.authz.support;
 
 import java.util.ArrayList;
 import java.util.Collection;
-import java.util.HashMap;
 import java.util.Iterator;
 
 import javax.naming.Name;
-import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
-import javax.naming.directory.Attribute;
 import javax.naming.directory.Attributes;
-import javax.naming.directory.SearchControls;
 
 import org.apache.ldap.common.aci.ACIItem;
 import org.apache.ldap.common.aci.ACITuple;
 import org.apache.ldap.common.aci.AuthenticationLevel;
 import org.apache.ldap.common.aci.MicroOperation;
-import org.apache.ldap.common.aci.ProtectedItem;
-import org.apache.ldap.common.aci.UserClass;
-import org.apache.ldap.common.aci.ProtectedItem.MaxValueCountItem;
-import org.apache.ldap.common.aci.ProtectedItem.RestrictedByItem;
 import org.apache.ldap.common.exception.LdapNoPermissionException;
-import org.apache.ldap.common.filter.ExprNode;
-import org.apache.ldap.common.filter.PresenceNode;
-import org.apache.ldap.common.name.LdapName;
-import org.apache.ldap.common.subtree.SubtreeSpecification;
 import org.apache.ldap.server.event.Evaluator;
 import org.apache.ldap.server.event.ExpressionEvaluator;
 import org.apache.ldap.server.interceptor.NextInterceptor;
@@ -52,25 +42,26 @@
 
 public class ACDFEngine
 {
-    private static final LdapName ROOTDSE_NAME = new LdapName();
-
-    private final Evaluator entryEvaluator;
-    private final SubtreeEvaluator subtreeEvaluator;
-    private final RefinementEvaluator refinementEvaluator;
-    private final ExprNode childrenFilter;
-    private final SearchControls childrenSearchControls;
+    private final ACITupleFilter[] filters;
     
     public ACDFEngine( OidRegistry oidRegistry, AttributeTypeRegistry attrTypeRegistry ) throws NamingException
     {
-        entryEvaluator = new ExpressionEvaluator( oidRegistry, attrTypeRegistry );
-        subtreeEvaluator = new SubtreeEvaluator( oidRegistry );
-        refinementEvaluator = new RefinementEvaluator(
+        Evaluator entryEvaluator = new ExpressionEvaluator( oidRegistry, attrTypeRegistry );
+        SubtreeEvaluator subtreeEvaluator = new SubtreeEvaluator( oidRegistry );
+        RefinementEvaluator refinementEvaluator = new RefinementEvaluator(
                 new RefinementLeafEvaluator( oidRegistry ) );
-
         
-        childrenFilter = new PresenceNode( "objectClass" );
-        childrenSearchControls = new SearchControls();
-        childrenSearchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+        filters = new ACITupleFilter[] {
+                new RelatedUserClassFilter( subtreeEvaluator ),
+                new RelatedProtectedItemFilter( attrTypeRegistry, refinementEvaluator, entryEvaluator ),
+                new MaxValueCountFilter(),
+                new MaxImmSubFilter(),
+                new RestrictedByFilter(),
+                new MicroOperationFilter(),
+                new HighestPrecedenceFilter(),
+                new MostSpecificUserClassFilter(),
+                new MostSpecificProtectedItemFilter(),
+        };
     }
     
     /**
@@ -128,715 +119,59 @@
             Name entryName, String attrId, Object attrValue,
             Collection microOperations, Collection aciTuples ) throws NamingException
     {
-        Attributes userEntry = next.lookup( userName );
-        Attributes entry = next.lookup( entryName );
-
-        aciTuples = removeTuplesWithoutRelatedUserClasses(
-                userGroupName, userName, userEntry, authenticationLevel, entryName, aciTuples );
-        aciTuples = removeTuplesWithoutRelatedProtectedItems( userName, entryName, attrId, attrValue, entry, aciTuples );
-        
-        // Discard all tuples that include the maxValueCount, maxImmSub,
-        // restrictedBy which grant access and which don't satisfy any of these
-        // constraints.
-        aciTuples = removeTuplesWithMaxValueCount( attrId, attrValue, entry, aciTuples );
-        aciTuples = removeTuplesWithMaxImmSub( next, entryName, aciTuples );
-        aciTuples = removeTuplesWithRestrictedBy( attrId, attrValue, entry, aciTuples );
-        
-        aciTuples = removeTuplesWithoutRelatedMicroOperation( microOperations, aciTuples );
-        aciTuples = getTuplesWithHighestPrecedence( aciTuples );
-        
-        aciTuples = getTuplesWithMostSpecificUserClasses( userName, userEntry, aciTuples );
-        aciTuples = getTuplesWithMostSpecificProtectedItems( entryName, attrId, attrValue, entry, aciTuples );
-
-        if( aciTuples.size() == 0 )
-        {
-            return false;
-        }
-
-        // Grant access if and only if one or more tuples remain and
-        // all grant access. Otherwise deny access.
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            if( !tuple.isGrant() )
-            {
-                return false;
-            }
-        }
-        return true;
-    }
-    
-    private Collection removeTuplesWithoutRelatedUserClasses(
-            Name userGroupName, Name userName, Attributes userEntry,
-            AuthenticationLevel authenticationLevel,
-            Name entryName, Collection aciTuples ) throws NamingException
-    {
-        Collection filteredTuples = new ArrayList( aciTuples );
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            if( tuple.isGrant() )
-            {
-                if( !matchUserClass( userGroupName, userName, userEntry, entryName, tuple.getUserClasses() ) ||
-                        authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) < 0 )
-                {
-                    i.remove();
-                }
-            }
-            else // Denials
-            {
-                if( !matchUserClass( userGroupName, userName, userEntry, entryName, tuple.getUserClasses() ) &&
-                        authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) >= 0 )
-                {
-                    i.remove();
-                }
-            }
-        }
-        
-        return filteredTuples;
-    }
-    
-    private Collection removeTuplesWithoutRelatedProtectedItems(
-            Name userName,
-            Name entryName, String attrId, Object attrValue, Attributes entry,
-            Collection aciTuples ) throws NamingException
-    {
-        Collection filteredTuples = new ArrayList();
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            if( matchProtectedItem(
-                    userName, entryName, attrId, attrValue, entry, tuple.getProtectedItems() ) )
-            {
-                filteredTuples.add( tuple );
-            }
-        }
-        
-        return filteredTuples;
-    }
-    
-    protected Collection removeTuplesWithMaxValueCount(
-            String attrId, Object attrValue, Attributes entry, Collection aciTuples )
-    {
-        if( attrId == null || attrValue == null )
-        {
-            return aciTuples;
-        }
-        
-        Collection filteredTuples = new ArrayList( aciTuples );
-        
-        for( Iterator i = filteredTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            
-            itemLoop: for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
-            {
-                ProtectedItem item = ( ProtectedItem ) j.next();
-                if( item instanceof ProtectedItem.MaxValueCount )
-                {
-                    ProtectedItem.MaxValueCount mvc = ( ProtectedItem.MaxValueCount ) item;
-                    for( Iterator k = mvc.iterator(); k.hasNext(); )
-                    {
-                        MaxValueCountItem mvcItem = ( MaxValueCountItem ) k.next();
-                        if( attrId.equalsIgnoreCase( mvcItem.getAttributeType() ) )
-                        {
-                            Attribute attr = entry.get( attrId );
-                            if( attr != null && attr.size() >= mvcItem.getMaxCount() )
-                            {
-                                i.remove();
-                                break itemLoop;
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        
-        return filteredTuples;
-    }
-    
-    protected Collection removeTuplesWithMaxImmSub(
-            NextInterceptor next, Name entryName, Collection aciTuples ) throws NamingException
-    {
-        if( entryName.size() == 0 )
-        {
-            return aciTuples;
-        }
-        
-        int immSubCount = -1;
-        
-        Collection filteredTuples = new ArrayList( aciTuples );
-        
-        for( Iterator i = filteredTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            
-            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
-            {
-                ProtectedItem item = ( ProtectedItem ) j.next();
-                if( item instanceof ProtectedItem.MaxImmSub )
-                {
-                    if( immSubCount < 0 )
-                    {
-                        immSubCount = getImmSubCount( next, entryName );
-                    }
-
-                    ProtectedItem.MaxImmSub mis = ( ProtectedItem.MaxImmSub ) item;
-                    if( mis.getValue() >= immSubCount )
-                    {
-                        i.remove();
-                        break;
-                    }
-                }
-            }
-        }
-        
-        return filteredTuples;
-    }
-
-    private int getImmSubCount( NextInterceptor next, Name entryName ) throws NamingException
-    {
-        int cnt = 0;
-        NamingEnumeration e = null;
-        try
-        {
-            e = next.search(
-                entryName.getPrefix( 1 ), new HashMap(),
-                childrenFilter, childrenSearchControls );
-            
-            while( e.hasMore() )
-            {
-                e.next();
-                cnt ++;
-            }
-            
-        }
-        finally
-        {
-            if( e != null )
-            {
-                e.close();
-            }
-        }
-        
-        return cnt;
-    }
-    
-    protected Collection removeTuplesWithRestrictedBy(
-            String attrId, Object attrValue, Attributes entry, Collection aciTuples )
-    {
-        if( attrId == null || attrValue == null )
-        {
-            return aciTuples;
-        }
-        
-        Collection filteredTuples = new ArrayList( aciTuples );
-        
-        for( Iterator i = filteredTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            
-            itemLoop: for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
-            {
-                ProtectedItem item = ( ProtectedItem ) j.next();
-                if( item instanceof ProtectedItem.RestrictedBy )
-                {
-                    ProtectedItem.RestrictedBy rb = ( ProtectedItem.RestrictedBy ) item;
-                    for( Iterator k = rb.iterator(); k.hasNext(); )
-                    {
-                        RestrictedByItem rbItem = ( RestrictedByItem ) k.next();
-                        Attribute attr = entry.get( rbItem.getValuesIn() );
-                        if( attr == null || !attr.contains( attrValue ) )
-                        {
-                            i.remove();
-                            break itemLoop;
-                        }
-                    }
-                }
-            }
-        }
-        
-        return filteredTuples;
-    }
-
-    
-    protected Collection removeTuplesWithoutRelatedMicroOperation(
-            Collection microOperations, Collection aciTuples )
-    {
-        Collection filteredTuples = new ArrayList();
-
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            boolean retain = false;
-            for( Iterator j = microOperations.iterator(); j.hasNext(); )
-            {
-                MicroOperation microOp = ( MicroOperation ) j.next();
-                if( tuple.getMicroOperations().contains( microOp ) )
-                {
-                    retain = true;
-                    break;
-                }
-            }
-            
-            if( retain )
-            {
-                filteredTuples.add( tuple );
-            }
-        }
-        
-        return filteredTuples;
-    }
-    
-    private Collection getTuplesWithHighestPrecedence( Collection aciTuple )
-    {
-        Collection filteredTuples = new ArrayList();
-        
-        int maxPrecedence = -1;
-        for( Iterator i = aciTuple.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            if( tuple.getPrecedence() > maxPrecedence ) 
-            {
-                maxPrecedence = tuple.getPrecedence();
-            }
-        }
-        
-        for( Iterator i = aciTuple.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            if( tuple.getPrecedence() == maxPrecedence ) 
-            {
-                filteredTuples.add( tuple );
-            }            
-        }
-        
-        return filteredTuples;
-    }
-    
-    private Collection getTuplesWithMostSpecificUserClasses( Name userName, Attributes userEntry, Collection aciTuples ) throws NamingException
-    {
-        if( aciTuples.size() <= 1 )
-        {
-            return aciTuples;
-        }
-
-        Collection filteredTuples = new ArrayList();
-        
-        // If there are any tuples matching the requestor with UserClasses
-        // element name or thisEntry, discard all other tuples.
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
-            {
-                UserClass userClass = ( UserClass ) j.next();
-                if( userClass instanceof UserClass.Name ||
-                        userClass instanceof UserClass.ThisEntry )
-                {
-                    filteredTuples.add( tuple );
-                    break;
-                }
-            }
-        }
-        
-        if( filteredTuples.size() > 0 )
+        if( entryName == null )
         {
-            return filteredTuples;
+            throw new NullPointerException( "entryName" );
         }
         
-        // Otherwise if there are any tuples matching UserGroup,
-        // discard all other tuples.
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
-            {
-                UserClass userClass = ( UserClass ) j.next();
-                if( userClass instanceof UserClass.UserGroup )
-                {
-                    filteredTuples.add( tuple );
-                    break;
-                }
-            }
-        }
+        Attributes userEntry = next.lookup( userName );
+        Attributes entry = next.lookup( entryName );
         
-        if( filteredTuples.size() > 0 )
+        // Determine the scope of the requested operation.
+        OperationScope scope;
+        if( attrId == null )
         {
-            return filteredTuples;
+            scope = OperationScope.ENTRY;
         }
-
-        // Otherwise if there are any tuples matching subtree,
-        // discard all other tuples.
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
+        else if( attrValue == null )
         {
-            ACITuple tuple = ( ACITuple ) i.next();
-            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
-            {
-                UserClass userClass = ( UserClass ) j.next();
-                if( userClass instanceof UserClass.Subtree )
-                {
-                    UserClass.Subtree subtree = ( UserClass.Subtree ) userClass;
-                    if( matchUserClassSubtree( userName, userEntry, subtree ) )
-                    {
-                        filteredTuples.add( tuple );
-                        break;
-                    }
-                }
-            }
+            scope = OperationScope.ATTRIBUTE_TYPE;
         }
-        
-        if( filteredTuples.size() > 0 )
+        else
         {
-            return filteredTuples;
+            scope = OperationScope.ATTRIBUTE_TYPE_AND_VALUE;
         }
         
-        return aciTuples;
-    }
+        // Clone aciTuples in case it is unmodifiable.
+        aciTuples = new ArrayList( aciTuples );
 
-    private boolean matchUserClassSubtree( Name userName, Attributes userEntry, UserClass.Subtree subtree ) throws NamingException
-    {
-        for( Iterator k = subtree.getSubtreeSpecifications().iterator();
-             k.hasNext(); )
-        {
-            SubtreeSpecification subtreeSpec = ( SubtreeSpecification ) k.next();
-            if( subtreeEvaluator.evaluate(
-                    subtreeSpec, ROOTDSE_NAME, userName, userEntry.get( "userClass" ) ) )
-            {
-                return true;
-            }
-        }
-        
-        return false;
-    }
-    
-    private Collection getTuplesWithMostSpecificProtectedItems( Name entryName, String attrId, Object attrValue, Attributes entry, Collection aciTuples ) throws NamingException
-    {
-        if( aciTuples.size() <= 1 )
+        // Filter unrelated and invalid tuples
+        for( int i = 0; i < filters.length; i++ )
         {
-            return aciTuples;
+            ACITupleFilter filter = filters[ i ];
+            aciTuples = filter.filter(
+                    aciTuples, scope, next,
+                    userGroupName, userName, userEntry, authenticationLevel,
+                    entryName, attrId, attrValue, entry, microOperations );
         }
-
-        Collection filteredTuples = new ArrayList();
         
-        // If the protected item is an attribute and there are tuples that
-        // specify the attribute type explicitly, discard all other tuples.
-        for( Iterator i = aciTuples.iterator(); i.hasNext(); )
-        {
-            ACITuple tuple = ( ACITuple ) i.next();
-            itemLoop: for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
-            {
-                ProtectedItem item = ( ProtectedItem ) j.next();
-                if( item instanceof ProtectedItem.AttributeType )
-                {
-                    if( contains( attrId, ( ( ProtectedItem.AttributeType ) item ).iterator() ) )
-                    {
-                        filteredTuples.add( tuple );
-                        break;
-                    }
-                }
-                else if( item instanceof ProtectedItem.AllAttributeValues )
-                {
-                    if( contains( attrId, ( ( ProtectedItem.AllAttributeValues ) item ).iterator() ) )
-                    {
-                        filteredTuples.add( tuple );
-                        break;
-                    }
-                }
-                else if( item instanceof ProtectedItem.SelfValue )
-                {
-                    if( contains( attrId, ( ( ProtectedItem.SelfValue ) item ).iterator() ) )
-                    {
-                        filteredTuples.add( tuple );
-                        break;
-                    }
-                }
-                else if( item instanceof ProtectedItem.AttributeValue )
-                {
-                    if( attrId == null || attrValue == null )
-                    {
-                        continue;
-                    }
-
-                    ProtectedItem.AttributeValue av = ( ProtectedItem.AttributeValue ) item;
-                    for( Iterator k = av.iterator(); k.hasNext(); )
-                    {
-                        Attribute attr = ( Attribute ) k.next();
-                        if( attr.getID().equalsIgnoreCase( attrId ) &&
-                                attr.contains( attrValue ) )
-                        {
-                            filteredTuples.add( tuple );
-                            break itemLoop;
-                        }
-                    }
-                }
-            }
-        }
-        
-        if( filteredTuples.size() > 0 )
+        // Deny access if no tuples left.
+        if( aciTuples.size() == 0 )
         {
-            return filteredTuples;
+            return false;
         }
 
-        // If the protected item is an attribute value, and there are tuples
-        // that specify the attribute value explicitly, discard all other tuples.
-        // A protected item which is a rangeOfValues is to be treated as
-        // specifying an attribute value explicitly. 
+        // Grant access if and only if one or more tuples remain and
+        // all grant access. Otherwise deny access.
         for( Iterator i = aciTuples.iterator(); i.hasNext(); )
         {
             ACITuple tuple = ( ACITuple ) i.next();
-            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
-            {
-                ProtectedItem item = ( ProtectedItem ) j.next();
-                if( item instanceof ProtectedItem.RangeOfValues )
-                {
-                    ProtectedItem.RangeOfValues rov = ( ProtectedItem.RangeOfValues ) item;
-                    if( entryEvaluator.evaluate( rov.getFilter(), entryName.toString(), entry ) )
-                    {
-                        filteredTuples.add( tuple );
-                        break;
-                    }
-                }
-            }
-        }
-
-        if( filteredTuples.size() > 0 )
-        {
-            return filteredTuples;
-        }
-
-        return aciTuples;
-    }
-    
-
-    private boolean matchUserClass( Name userGroupName, Name userName, Attributes userEntry, Name entryName, Collection userClasses ) throws NamingException
-    {
-        for( Iterator i = userClasses.iterator(); i.hasNext(); )
-        {
-            UserClass userClass = ( UserClass ) i.next();
-            if( userClass == UserClass.ALL_USERS )
-            {
-                return true;
-            }
-            else if( userClass == UserClass.THIS_ENTRY )
-            {
-                if( userName.equals( entryName ) )
-                {
-                    return true;
-                }
-            }
-            else if( userClass instanceof UserClass.Name )
-            {
-                UserClass.Name nameUserClass = ( UserClass.Name ) userClass;
-                if( nameUserClass.getNames().contains( userName ) )
-                {
-                    return true;
-                }
-            }
-            else if( userClass instanceof UserClass.UserGroup )
-            {
-                UserClass.UserGroup userGroupUserClass = ( UserClass.UserGroup ) userClass;
-                if( userGroupName != null && userGroupUserClass.getNames().contains( userGroupName ) )
-                {
-                    return true;
-                }
-            }
-            else if( userClass instanceof UserClass.Subtree )
-            {
-                UserClass.Subtree subtree = ( UserClass.Subtree ) userClass;
-                if( matchUserClassSubtree( userName, userEntry, subtree ) )
-                {
-                    return true;
-                }
-            }
-            else
-            {
-                throw new InternalError( "Unexpected userClass: " + userClass.getClass().getName() );
-            }
-        }
-
-        return false;
-    }
-    
-    private boolean matchProtectedItem(
-            Name userName,
-            Name entryName, String attrId, Object attrValue, Attributes entry,
-            Collection protectedItems ) throws NamingException
-    {
-        for( Iterator i = protectedItems.iterator(); i.hasNext(); )
-        {
-            ProtectedItem item = ( ProtectedItem ) i.next();
-            if( item == ProtectedItem.ENTRY )
-            {
-                if( attrId == null )
-                {
-                    return true;
-                }
-            }
-            else if( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES )
-            {
-                if( attrId != null )
-                {
-                    return true;
-                }
-            }
-            else if( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES_AND_VALUES )
-            {
-                if( attrId != null && attrValue != null )
-                {
-                    return true;
-                }
-            }
-            else if( item instanceof ProtectedItem.AllAttributeValues )
-            {
-                if( attrId == null )
-                {
-                    continue;
-                }
-
-                ProtectedItem.AllAttributeValues aav = ( ProtectedItem.AllAttributeValues ) item;
-                for( Iterator j = aav.iterator(); j.hasNext(); )
-                {
-                    if( attrId.equalsIgnoreCase( ( String ) j.next() ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else if( item instanceof ProtectedItem.AttributeType )
-            {
-                if( attrId == null )
-                {
-                    continue;
-                }
-                
-                ProtectedItem.AttributeType at = ( ProtectedItem.AttributeType ) item;
-                for( Iterator j = at.iterator(); j.hasNext(); )
-                {
-                    if( attrId.equalsIgnoreCase( ( String ) j.next() ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else if( item instanceof ProtectedItem.AttributeValue )
-            {
-                if( attrId == null || attrValue == null )
-                {
-                    continue;
-                }
-                
-                ProtectedItem.AttributeValue av = ( ProtectedItem.AttributeValue ) item;
-                for( Iterator j = av.iterator(); j.hasNext(); )
-                {
-                    Attribute attr = ( Attribute ) j.next();
-                    if( attrId.equalsIgnoreCase( attr.getID() ) &&
-                            attr.contains( attrValue ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else if( item instanceof ProtectedItem.Classes )
-            {
-                ProtectedItem.Classes c = ( ProtectedItem.Classes ) item;
-                if( refinementEvaluator.evaluate(
-                        c.getClasses(), entry.get( "objectClass" ) ) )
-                {
-                    return true;
-                }
-            }
-            else if( item instanceof ProtectedItem.MaxImmSub )
-            {
-                ProtectedItem.MaxImmSub mis = ( ProtectedItem.MaxImmSub ) item;
-                if( attrId == null )
-                {
-                    return true;
-                }
-            }
-            else if( item instanceof ProtectedItem.MaxValueCount )
-            {
-                if( attrId == null )
-                {
-                    continue;
-                }
-
-                ProtectedItem.MaxValueCount mvc = ( ProtectedItem.MaxValueCount ) item;
-                for( Iterator j = mvc.iterator(); j.hasNext(); )
-                {
-                    MaxValueCountItem mvcItem = ( MaxValueCountItem ) j.next();
-                    if( attrId.equalsIgnoreCase( mvcItem.getAttributeType() ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else if( item instanceof ProtectedItem.RangeOfValues )
-            {
-                ProtectedItem.RangeOfValues rov = ( ProtectedItem.RangeOfValues ) item;
-                if( entryEvaluator.evaluate( rov.getFilter(), entryName.toString(), entry ) )
-                {
-                    return true;
-                }
-            }
-            else if( item instanceof ProtectedItem.RestrictedBy )
-            {
-                if( attrId == null )
-                {
-                    continue;
-                }
-
-                ProtectedItem.RestrictedBy rb = ( ProtectedItem.RestrictedBy ) item;
-                for( Iterator j = rb.iterator(); j.hasNext(); )
-                {
-                    RestrictedByItem rbItem = ( RestrictedByItem ) j.next();
-                    if( attrId.equalsIgnoreCase( rbItem.getAttributeType() ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else if( item instanceof ProtectedItem.SelfValue )
-            {
-                if( attrId == null || attrValue == null )
-                {
-                    continue;
-                }
-                
-                ProtectedItem.SelfValue sv = ( ProtectedItem.SelfValue ) item;
-                for( Iterator j = sv.iterator(); j.hasNext(); )
-                {
-                    Attribute attr = entry.get( String.valueOf( j.next() ) );
-                    if( attr.contains( userName ) || attr.contains( userName.toString() ) )
-                    {
-                        return true;
-                    }
-                }
-            }
-            else
+            if( !tuple.isGrant() )
             {
-                throw new InternalError( "Unexpected protectedItem: " + item.getClass().getName() );
+                return false;
             }
         }
-        
-        return false;
-    }
-    
-    private static boolean contains( Object needle, Iterator haystack )
-    {
-        if( needle == null )
-        {
-            return false;
-        }
 
-        while( haystack.hasNext() )
-        {
-            if( haystack.next().equals( needle ) )
-            {
-                return true;
-            }
-        }
-        
-        return false;
+        return true;
     }
 }

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,38 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public interface ACITupleFilter
+{
+    Collection filter(
+            Collection tuples, OperationScope scope, NextInterceptor next,
+            Name userGroupName, Name userName, Attributes userEntry,
+            AuthenticationLevel authenticationLevel,
+            Name entryName, String attrId, Object attrValue, Attributes entry,
+            Collection microOperations ) throws NamingException;
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/ACITupleFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,60 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class HighestPrecedenceFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        int maxPrecedence = -1;
+        
+        // Find the maximum precedence for all tuples.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( tuple.getPrecedence() > maxPrecedence ) 
+            {
+                maxPrecedence = tuple.getPrecedence();
+            }
+        }
+        
+        // Remove all tuples whose precedences are not the maximum one.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( tuple.getPrecedence() != maxPrecedence ) 
+            {
+                i.remove();
+            }            
+        }
+        
+        return tuples;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/HighestPrecedenceFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,123 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingEnumeration;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+import javax.naming.directory.SearchControls;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.ProtectedItem;
+import org.apache.ldap.common.filter.ExprNode;
+import org.apache.ldap.common.filter.PresenceNode;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class MaxImmSubFilter implements ACITupleFilter
+{
+    private final ExprNode childrenFilter;
+    private final SearchControls childrenSearchControls;
+
+    public MaxImmSubFilter()
+    {
+        childrenFilter = new PresenceNode( "objectClass" );
+        childrenSearchControls = new SearchControls();
+        childrenSearchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
+    }
+    
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        if( entryName.size() == 0 )
+        {
+            return tuples;
+        }
+        
+        if( scope != OperationScope.ENTRY )
+        {
+            return tuples;
+        }
+
+        int immSubCount = -1;
+        
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( !tuple.isGrant() )
+            {
+                continue;
+            }
+        
+            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
+            {
+                ProtectedItem item = ( ProtectedItem ) j.next();
+                if( item instanceof ProtectedItem.MaxImmSub )
+                {
+                    if( immSubCount < 0 )
+                    {
+                        immSubCount = getImmSubCount( next, entryName );
+                    }
+    
+                    ProtectedItem.MaxImmSub mis = ( ProtectedItem.MaxImmSub ) item;
+                    if( mis.getValue() >= immSubCount )
+                    {
+                        i.remove();
+                        break;
+                    }
+                }
+            }
+        }
+        
+        return tuples;
+    }
+    
+    private int getImmSubCount( NextInterceptor next, Name entryName ) throws NamingException
+    {
+        int cnt = 0;
+        NamingEnumeration e = null;
+        try
+        {
+            e = next.search(
+                entryName.getPrefix( 1 ), new HashMap(),
+                childrenFilter, childrenSearchControls );
+            
+            while( e.hasMore() )
+            {
+                e.next();
+                cnt ++;
+            }
+            
+        }
+        finally
+        {
+            if( e != null )
+            {
+                e.close();
+            }
+        }
+        
+        return cnt;
+    }
+
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxImmSubFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,89 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.ProtectedItem;
+import org.apache.ldap.common.aci.ProtectedItem.MaxValueCountItem;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class MaxValueCountFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+        {
+            return tuples;
+        }
+
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( !tuple.isGrant() )
+            {
+                continue;
+            }
+
+            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
+            {
+                ProtectedItem item = ( ProtectedItem ) j.next();
+                if( item instanceof ProtectedItem.MaxValueCount )
+                {
+                    ProtectedItem.MaxValueCount mvc = ( ProtectedItem.MaxValueCount ) item;
+                    if( isRemovable( mvc, attrId, entry ) )
+                    {
+                        i.remove();
+                        break;
+                    }
+                }
+            }
+        }
+        
+        return tuples;
+    }
+
+    private boolean isRemovable( ProtectedItem.MaxValueCount mvc, String attrId, Attributes entry )
+    {
+        for( Iterator k = mvc.iterator(); k.hasNext(); )
+        {
+            MaxValueCountItem mvcItem = ( MaxValueCountItem ) k.next();
+            if( attrId.equalsIgnoreCase( mvcItem.getAttributeType() ) )
+            {
+                Attribute attr = entry.get( attrId );
+                int attrCount = attr == null? 0 : attr.size();
+                if( attrCount >= mvcItem.getMaxCount() )
+                {
+                    return true;
+                }
+            }
+        }
+        
+        return false;
+    }
+
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MaxValueCountFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,60 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.MicroOperation;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class MicroOperationFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            boolean retain = false;
+            for( Iterator j = microOperations.iterator(); j.hasNext(); )
+            {
+                MicroOperation microOp = ( MicroOperation ) j.next();
+                if( tuple.getMicroOperations().contains( microOp ) )
+                {
+                    retain = true;
+                    break;
+                }
+            }
+            
+            if( !retain )
+            {
+                i.remove();
+            }
+        }
+        
+        return tuples;
+    }
+
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MicroOperationFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,137 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.ProtectedItem;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class MostSpecificProtectedItemFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        if( tuples.size() <= 1 )
+        {
+            return tuples;
+        }
+
+        Collection filteredTuples = new ArrayList();
+        
+        // If the protected item is an attribute and there are tuples that
+        // specify the attribute type explicitly, discard all other tuples.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            itemLoop: for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
+            {
+                ProtectedItem item = ( ProtectedItem ) j.next();
+                if( item instanceof ProtectedItem.AttributeType )
+                {
+                    if( contains( attrId, ( ( ProtectedItem.AttributeType ) item ).iterator() ) )
+                    {
+                        filteredTuples.add( tuple );
+                        break;
+                    }
+                }
+                else if( item instanceof ProtectedItem.AllAttributeValues )
+                {
+                    if( contains( attrId, ( ( ProtectedItem.AllAttributeValues ) item ).iterator() ) )
+                    {
+                        filteredTuples.add( tuple );
+                        break;
+                    }
+                }
+                else if( item instanceof ProtectedItem.SelfValue )
+                {
+                    if( contains( attrId, ( ( ProtectedItem.SelfValue ) item ).iterator() ) )
+                    {
+                        filteredTuples.add( tuple );
+                        break;
+                    }
+                }
+                else if( item instanceof ProtectedItem.AttributeValue )
+                {
+                    if( attrId == null || attrValue == null )
+                    {
+                        continue;
+                    }
+
+                    filteredTuples.add( tuple );
+                    break;
+                }
+            }
+        }
+        
+        if( filteredTuples.size() > 0 )
+        {
+            return filteredTuples;
+        }
+
+        // If the protected item is an attribute value, and there are tuples
+        // that specify the attribute value explicitly, discard all other tuples.
+        // A protected item which is a rangeOfValues is to be treated as
+        // specifying an attribute value explicitly. 
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            for( Iterator j = tuple.getProtectedItems().iterator(); j.hasNext(); )
+            {
+                ProtectedItem item = ( ProtectedItem ) j.next();
+                if( item instanceof ProtectedItem.RangeOfValues )
+                {
+                    filteredTuples.add( tuple );
+                }
+            }
+        }
+
+        if( filteredTuples.size() > 0 )
+        {
+            return filteredTuples;
+        }
+        
+        return tuples;
+    }
+    
+    private static boolean contains( Object needle, Iterator haystack )
+    {
+        if( needle == null )
+        {
+            return false;
+        }
+
+        while( haystack.hasNext() )
+        {
+            if( haystack.next().equals( needle ) )
+            {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificProtectedItemFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,114 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.UserClass;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class MostSpecificUserClassFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        if( tuples.size() <= 1 )
+        {
+            return tuples;
+        }
+
+        Collection filteredTuples = new ArrayList();
+        
+        // If there are any tuples matching the requestor with UserClasses
+        // element name or thisEntry, discard all other tuples.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
+            {
+                UserClass userClass = ( UserClass ) j.next();
+                if( userClass instanceof UserClass.Name ||
+                        userClass instanceof UserClass.ThisEntry )
+                {
+                    filteredTuples.add( tuple );
+                    break;
+                }
+            }
+        }
+        
+        if( filteredTuples.size() > 0 )
+        {
+            return filteredTuples;
+        }
+        
+        // Otherwise if there are any tuples matching UserGroup,
+        // discard all other tuples.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
+            {
+                UserClass userClass = ( UserClass ) j.next();
+                if( userClass instanceof UserClass.UserGroup )
+                {
+                    filteredTuples.add( tuple );
+                    break;
+                }
+            }
+        }
+        
+        if( filteredTuples.size() > 0 )
+        {
+            return filteredTuples;
+        }
+
+        // Otherwise if there are any tuples matching subtree,
+        // discard all other tuples.
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            for( Iterator j = tuple.getUserClasses().iterator(); j.hasNext(); )
+            {
+                UserClass userClass = ( UserClass ) j.next();
+                if( userClass instanceof UserClass.Subtree )
+                {
+                    filteredTuples.add( tuple );
+                    break;
+                }
+            }
+        }
+        
+        if( filteredTuples.size() > 0 )
+        {
+            tuples.clear();
+            tuples.addAll( filteredTuples );
+            return filteredTuples;
+        }
+        
+        return tuples;
+    }
+
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/MostSpecificUserClassFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,43 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+public class OperationScope
+{
+    public static final OperationScope ENTRY = new OperationScope( "Entry" );
+    public static final OperationScope ATTRIBUTE_TYPE = new OperationScope( "Attribute Type" );
+    public static final OperationScope ATTRIBUTE_TYPE_AND_VALUE = new OperationScope( "Attribute Type & Value" );
+    
+    private final String name;
+    
+    private OperationScope( String name )
+    {
+        this.name = name;
+    }
+    
+    public String getName()
+    {
+        return name;
+    }
+    
+    public String toString()
+    {
+        return name;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/OperationScope.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,257 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.ProtectedItem;
+import org.apache.ldap.common.aci.ProtectedItem.MaxValueCountItem;
+import org.apache.ldap.common.aci.ProtectedItem.RestrictedByItem;
+import org.apache.ldap.common.schema.AttributeType;
+import org.apache.ldap.server.event.Evaluator;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+import org.apache.ldap.server.schema.AttributeTypeRegistry;
+import org.apache.ldap.server.subtree.RefinementEvaluator;
+
+public class RelatedProtectedItemFilter implements ACITupleFilter
+{
+    private final AttributeTypeRegistry attrTypeRegistry;
+    private final RefinementEvaluator refinementEvaluator;
+    private final Evaluator entryEvaluator;
+
+    public RelatedProtectedItemFilter(
+            AttributeTypeRegistry attrTypeRegistry,
+            RefinementEvaluator refinementEvaluator, Evaluator entryEvaluator )
+    {
+        this.attrTypeRegistry = attrTypeRegistry;
+        this.refinementEvaluator = refinementEvaluator;
+        this.entryEvaluator = entryEvaluator;
+    }
+
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( !isRelated( tuple, scope, userName, entryName, attrId, attrValue, entry ) )
+            {
+                i.remove();
+            }
+        }
+        
+        return tuples;
+    }
+
+    private boolean isRelated( ACITuple tuple, OperationScope scope, Name userName, Name entryName, String attrId, Object attrValue, Attributes entry ) throws NamingException, InternalError
+    {
+        for( Iterator i = tuple.getProtectedItems().iterator(); i.hasNext(); )
+        {
+            ProtectedItem item = ( ProtectedItem ) i.next();
+            if( item == ProtectedItem.ENTRY )
+            {
+                if( scope == OperationScope.ENTRY )
+                {
+                    return true;
+                }
+            }
+            else if( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE )
+                {
+                    continue;
+                }
+                
+                if( isUserAttribute( attrId ) )
+                {
+                    return true;
+                }
+            }
+            else if( item == ProtectedItem.ALL_USER_ATTRIBUTE_TYPES_AND_VALUES )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE &&
+                    scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+
+                if( isUserAttribute( attrId ) )
+                {
+                    return true;
+                }
+            }
+            else if( item instanceof ProtectedItem.AllAttributeValues )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE &&
+                    scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+
+                ProtectedItem.AllAttributeValues aav = ( ProtectedItem.AllAttributeValues ) item;
+                for( Iterator j = aav.iterator(); j.hasNext(); )
+                {
+                    if( attrId.equalsIgnoreCase( ( String ) j.next() ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else if( item instanceof ProtectedItem.AttributeType )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE &&
+                    scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+                
+                ProtectedItem.AttributeType at = ( ProtectedItem.AttributeType ) item;
+                for( Iterator j = at.iterator(); j.hasNext(); )
+                {
+                    if( attrId.equalsIgnoreCase( ( String ) j.next() ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else if( item instanceof ProtectedItem.AttributeValue )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+                
+                ProtectedItem.AttributeValue av = ( ProtectedItem.AttributeValue ) item;
+                for( Iterator j = av.iterator(); j.hasNext(); )
+                {
+                    Attribute attr = ( Attribute ) j.next();
+                    if( attrId.equalsIgnoreCase( attr.getID() ) &&
+                            attr.contains( attrValue ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else if( item instanceof ProtectedItem.Classes )
+            {
+                ProtectedItem.Classes c = ( ProtectedItem.Classes ) item;
+                if( refinementEvaluator.evaluate(
+                        c.getClasses(), entry.get( "objectClass" ) ) )
+                {
+                    return true;
+                }
+            }
+            else if( item instanceof ProtectedItem.MaxImmSub )
+            {
+                return true;
+            }
+            else if( item instanceof ProtectedItem.MaxValueCount )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+
+                ProtectedItem.MaxValueCount mvc = ( ProtectedItem.MaxValueCount ) item;
+                for( Iterator j = mvc.iterator(); j.hasNext(); )
+                {
+                    MaxValueCountItem mvcItem = ( MaxValueCountItem ) j.next();
+                    if( attrId.equalsIgnoreCase( mvcItem.getAttributeType() ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else if( item instanceof ProtectedItem.RangeOfValues )
+            {
+                ProtectedItem.RangeOfValues rov = ( ProtectedItem.RangeOfValues ) item;
+                if( entryEvaluator.evaluate( rov.getFilter(), entryName.toString(), entry ) )
+                {
+                    return true;
+                }
+            }
+            else if( item instanceof ProtectedItem.RestrictedBy )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+                {
+                    continue;
+                }
+
+                ProtectedItem.RestrictedBy rb = ( ProtectedItem.RestrictedBy ) item;
+                for( Iterator j = rb.iterator(); j.hasNext(); )
+                {
+                    RestrictedByItem rbItem = ( RestrictedByItem ) j.next();
+                    if( attrId.equalsIgnoreCase( rbItem.getAttributeType() ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else if( item instanceof ProtectedItem.SelfValue )
+            {
+                if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE ||
+                    scope != OperationScope.ATTRIBUTE_TYPE )
+                {
+                    continue;
+                }
+                
+                ProtectedItem.SelfValue sv = ( ProtectedItem.SelfValue ) item;
+                for( Iterator j = sv.iterator(); j.hasNext(); )
+                {
+                    Attribute attr = entry.get( String.valueOf( j.next() ) );
+                    if( attr.contains( userName ) || attr.contains( userName.toString() ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+            else
+            {
+                throw new InternalError( "Unexpected protectedItem: " + item.getClass().getName() );
+            }
+        }
+        
+        return false;
+    }
+    
+    private final boolean isUserAttribute( String attrId )
+    {
+        try
+        {
+            AttributeType type = attrTypeRegistry.lookup( attrId );
+            if( type != null && type.isCanUserModify() )
+            {
+                return true;
+            }
+        }
+        catch( NamingException e )
+        {
+            // Ignore
+        }
+        
+        return false;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedProtectedItemFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,137 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.UserClass;
+import org.apache.ldap.common.name.LdapName;
+import org.apache.ldap.common.subtree.SubtreeSpecification;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+import org.apache.ldap.server.subtree.SubtreeEvaluator;
+
+public class RelatedUserClassFilter implements ACITupleFilter
+{
+    private static final LdapName ROOTDSE_NAME = new LdapName();
+
+    private final SubtreeEvaluator subtreeEvaluator;
+
+    public RelatedUserClassFilter( SubtreeEvaluator subtreeEvaluator )
+    {
+        this.subtreeEvaluator = subtreeEvaluator;
+    }
+    
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( tuple.isGrant() )
+            {
+                if( !isRelated( userGroupName, userName, userEntry, entryName, tuple.getUserClasses() ) ||
+                        authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) < 0 )
+                {
+                    i.remove();
+                }
+            }
+            else // Denials
+            {
+                if( !isRelated( userGroupName, userName, userEntry, entryName, tuple.getUserClasses() ) &&
+                        authenticationLevel.compareTo( tuple.getAuthenticationLevel() ) >= 0 )
+                {
+                    i.remove();
+                }
+            }
+        }
+        
+        return tuples;
+    }
+    
+    private boolean isRelated( Name userGroupName, Name userName, Attributes userEntry, Name entryName, Collection userClasses ) throws NamingException
+    {
+        for( Iterator i = userClasses.iterator(); i.hasNext(); )
+        {
+            UserClass userClass = ( UserClass ) i.next();
+            if( userClass == UserClass.ALL_USERS )
+            {
+                return true;
+            }
+            else if( userClass == UserClass.THIS_ENTRY )
+            {
+                if( userName.equals( entryName ) )
+                {
+                    return true;
+                }
+            }
+            else if( userClass instanceof UserClass.Name )
+            {
+                UserClass.Name nameUserClass = ( UserClass.Name ) userClass;
+                if( nameUserClass.getNames().contains( userName ) )
+                {
+                    return true;
+                }
+            }
+            else if( userClass instanceof UserClass.UserGroup )
+            {
+                UserClass.UserGroup userGroupUserClass = ( UserClass.UserGroup ) userClass;
+                if( userGroupName != null && userGroupUserClass.getNames().contains( userGroupName ) )
+                {
+                    return true;
+                }
+            }
+            else if( userClass instanceof UserClass.Subtree )
+            {
+                UserClass.Subtree subtree = ( UserClass.Subtree ) userClass;
+                if( matchUserClassSubtree( userName, userEntry, subtree ) )
+                {
+                    return true;
+                }
+            }
+            else
+            {
+                throw new InternalError( "Unexpected userClass: " + userClass.getClass().getName() );
+            }
+        }
+
+        return false;
+    }
+    
+    private boolean matchUserClassSubtree( Name userName, Attributes userEntry, UserClass.Subtree subtree ) throws NamingException
+    {
+        for( Iterator i = subtree.getSubtreeSpecifications().iterator();
+             i.hasNext(); )
+        {
+            SubtreeSpecification subtreeSpec = ( SubtreeSpecification ) i.next();
+            if( subtreeEvaluator.evaluate(
+                    subtreeSpec, ROOTDSE_NAME, userName, userEntry.get( "userClass" ) ) )
+            {
+                return true;
+            }
+        }
+        
+        return false;
+    }
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RelatedUserClassFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java
URL: http://svn.apache.org/viewcvs/directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java?rev=291602&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java Mon Sep 26 05:04:21 2005
@@ -0,0 +1,84 @@
+/*
+ *   @(#) $Id$
+ *   
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed under the Apache License, Version 2.0 (the "License");
+ *   you may not use this file except in compliance with the License.
+ *   You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *   Unless required by applicable law or agreed to in writing, software
+ *   distributed under the License is distributed on an "AS IS" BASIS,
+ *   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *   See the License for the specific language governing permissions and
+ *   limitations under the License.
+ *
+ */
+package org.apache.ldap.server.authz.support;
+
+import java.util.Collection;
+import java.util.Iterator;
+
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.Attributes;
+
+import org.apache.ldap.common.aci.ACITuple;
+import org.apache.ldap.common.aci.AuthenticationLevel;
+import org.apache.ldap.common.aci.ProtectedItem;
+import org.apache.ldap.common.aci.ProtectedItem.RestrictedByItem;
+import org.apache.ldap.server.interceptor.NextInterceptor;
+
+public class RestrictedByFilter implements ACITupleFilter
+{
+    public Collection filter( Collection tuples, OperationScope scope, NextInterceptor next, Name userGroupName, Name userName, Attributes userEntry, AuthenticationLevel authenticationLevel, Name entryName, String attrId, Object attrValue, Attributes entry, Collection microOperations ) throws NamingException
+    {
+        if( scope != OperationScope.ATTRIBUTE_TYPE_AND_VALUE )
+        {
+            return tuples;
+        }
+
+        for( Iterator i = tuples.iterator(); i.hasNext(); )
+        {
+            ACITuple tuple = ( ACITuple ) i.next();
+            if( !tuple.isGrant() )
+            {
+                continue;
+            }
+
+            if( isRemovable( tuple, attrValue, entry ) )
+            {
+                i.remove();
+            }
+        }
+        
+        return tuples;
+    }
+
+    public boolean isRemovable( ACITuple tuple, Object attrValue, Attributes entry )
+    {
+        for( Iterator i = tuple.getProtectedItems().iterator(); i.hasNext(); )
+        {
+            ProtectedItem item = ( ProtectedItem ) i.next();
+            if( item instanceof ProtectedItem.RestrictedBy )
+            {
+                ProtectedItem.RestrictedBy rb = ( ProtectedItem.RestrictedBy ) item;
+                for( Iterator k = rb.iterator(); k.hasNext(); )
+                {
+                    RestrictedByItem rbItem = ( RestrictedByItem ) k.next();
+                    Attribute attr = entry.get( rbItem.getValuesIn() );
+                    if( attr == null || !attr.contains( attrValue ) )
+                    {
+                        return true;
+                    }
+                }
+            }
+        }
+        
+        return false;
+    }
+
+}

Propchange: directory/apacheds/trunk/core/src/main/java/org/apache/ldap/server/authz/support/RestrictedByFilter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision