You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2011/10/15 00:36:15 UTC

svn commit: r1183537 [8/11] - in /directory/apacheds/trunk/interceptors: admin/ admin/.settings/ authn/ authn/.settings/ authz/.settings/ changelog/ changelog/src/ changelog/src/main/ changelog/src/main/java/ changelog/src/main/java/org/ changelog/src/...

Added: directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryManager.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryManager.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryManager.java (added)
+++ directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryManager.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,462 @@
+/*
+ *   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.schema;
+
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.directory.server.core.api.DnFactory;
+import org.apache.directory.server.core.api.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.api.schema.DescriptionParsers;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.entry.Modification;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.exception.LdapUnwillingToPerformException;
+import org.apache.directory.shared.ldap.model.message.ResultCodeEnum;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.DITContentRule;
+import org.apache.directory.shared.ldap.model.schema.DITStructureRule;
+import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
+import org.apache.directory.shared.ldap.model.schema.MatchingRule;
+import org.apache.directory.shared.ldap.model.schema.MatchingRuleUse;
+import org.apache.directory.shared.ldap.model.schema.NameForm;
+import org.apache.directory.shared.ldap.model.schema.ObjectClass;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.model.schema.parsers.LdapComparatorDescription;
+import org.apache.directory.shared.ldap.model.schema.parsers.NormalizerDescription;
+import org.apache.directory.shared.ldap.model.schema.parsers.SyntaxCheckerDescription;
+import org.apache.directory.shared.ldap.model.schema.registries.SchemaLoader;
+import org.apache.directory.shared.util.Strings;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+/**
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SchemaSubentryManager
+{
+    /** A logger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( SchemaSubentryManager.class );
+
+    // indices of handlers and object ids into arrays
+    private static final int COMPARATOR_INDEX = 0;
+    private static final int NORMALIZER_INDEX = 1;
+    private static final int SYNTAX_CHECKER_INDEX = 2;
+    private static final int SYNTAX_INDEX = 3;
+    private static final int MATCHING_RULE_INDEX = 4;
+    private static final int ATTRIBUTE_TYPE_INDEX = 5;
+    private static final int OBJECT_CLASS_INDEX = 6;
+    private static final int MATCHING_RULE_USE_INDEX = 7;
+    private static final int DIT_STRUCTURE_RULE_INDEX = 8;
+    private static final int DIT_CONTENT_RULE_INDEX = 9;
+    private static final int NAME_FORM_INDEX = 10;
+
+    private static final Set<String> VALID_OU_VALUES = new HashSet<String>();
+
+    /** The schemaManager */
+    private final SchemaManager schemaManager;
+    
+    private final SchemaSubentryModifier subentryModifier;
+    
+    /** The description parsers */
+    private final DescriptionParsers parsers;
+    
+    /** 
+     * Maps the OID of a subschemaSubentry operational attribute to the index of 
+     * the handler in the schemaObjectHandlers array.
+     */ 
+    private final Map<String, Integer> opAttr2handlerIndex = new HashMap<String, Integer>( 11 );
+    private static final String CASCADING_ERROR =
+            "Cascading has not yet been implemented: standard operation is in effect.";
+
+    private static AttributeType ENTRY_CSN_ATTRIBUTE_TYPE;
+    
+    static 
+    {
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.NORMALIZERS_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.COMPARATORS_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.SYNTAX_CHECKERS_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( "syntaxes" ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.MATCHING_RULES_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.MATCHING_RULE_USE_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.ATTRIBUTE_TYPES_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.OBJECT_CLASSES_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.NAME_FORMS_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.DIT_CONTENT_RULES_AT ) );
+        VALID_OU_VALUES.add( Strings.toLowerCase( SchemaConstants.DIT_STRUCTURE_RULES_AT ) );
+    }
+
+
+    public SchemaSubentryManager( SchemaManager schemaManager, SchemaLoader loader, DnFactory dnFactory )
+        throws LdapException
+    {
+        this.schemaManager = schemaManager;
+        this.subentryModifier = new SchemaSubentryModifier( schemaManager, dnFactory );
+        this.parsers = new DescriptionParsers( schemaManager );
+        
+        String comparatorsOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.COMPARATORS_AT );
+        opAttr2handlerIndex.put( comparatorsOid, COMPARATOR_INDEX );
+
+        String normalizersOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.NORMALIZERS_AT );
+        opAttr2handlerIndex.put( normalizersOid, NORMALIZER_INDEX );
+
+        String syntaxCheckersOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.SYNTAX_CHECKERS_AT );
+        opAttr2handlerIndex.put( syntaxCheckersOid, SYNTAX_CHECKER_INDEX );
+
+        String ldapSyntaxesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.LDAP_SYNTAXES_AT );
+        opAttr2handlerIndex.put( ldapSyntaxesOid, SYNTAX_INDEX );
+
+        String matchingRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.MATCHING_RULES_AT );
+        opAttr2handlerIndex.put( matchingRulesOid, MATCHING_RULE_INDEX );
+
+        String attributeTypesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.ATTRIBUTE_TYPES_AT );
+        opAttr2handlerIndex.put( attributeTypesOid, ATTRIBUTE_TYPE_INDEX );
+
+        String objectClassesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.OBJECT_CLASSES_AT );
+        opAttr2handlerIndex.put( objectClassesOid, OBJECT_CLASS_INDEX );
+
+        String matchingRuleUseOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.MATCHING_RULE_USE_AT );
+        opAttr2handlerIndex.put( matchingRuleUseOid, MATCHING_RULE_USE_INDEX );
+
+        String ditStructureRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.DIT_STRUCTURE_RULES_AT );
+        opAttr2handlerIndex.put( ditStructureRulesOid, DIT_STRUCTURE_RULE_INDEX );
+
+        String ditContentRulesOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.DIT_CONTENT_RULES_AT );
+        opAttr2handlerIndex.put( ditContentRulesOid, DIT_CONTENT_RULE_INDEX );
+
+        String nameFormsOid = schemaManager.getAttributeTypeRegistry().getOidByName( SchemaConstants.NAME_FORMS_AT );
+        opAttr2handlerIndex.put( nameFormsOid, NAME_FORM_INDEX );
+        
+        ENTRY_CSN_ATTRIBUTE_TYPE = schemaManager.getAttributeType( SchemaConstants.ENTRY_CSN_AT );
+    }
+
+    
+    /* (non-Javadoc)
+     * @see org.apache.directory.server.core.schema.SchemaChangeManager#modifySchemaSubentry(org.apache.directory.server.core.interceptor.context.ModifyOperationContext, org.apache.directory.server.core.entry.Entry, org.apache.directory.server.core.entry.Entry, boolean)
+     */
+    public void modifySchemaSubentry( ModifyOperationContext modifyContext, boolean doCascadeModify ) throws LdapException 
+    {
+        for ( Modification mod : modifyContext.getModItems() )
+        {
+            String opAttrOid = schemaManager.getAttributeTypeRegistry().getOidByName( mod.getAttribute().getId() );
+            
+            Attribute serverAttribute = mod.getAttribute();
+
+            switch ( mod.getOperation() )
+            {
+                case ADD_ATTRIBUTE :
+                    modifyAddOperation( modifyContext, opAttrOid, serverAttribute, doCascadeModify );
+                    break;
+                    
+                case REMOVE_ATTRIBUTE :
+                    modifyRemoveOperation( modifyContext, opAttrOid, serverAttribute );
+                    break; 
+                    
+                case REPLACE_ATTRIBUTE :
+                    // a hack to allow entryCSN modification
+                    if ( ENTRY_CSN_ATTRIBUTE_TYPE.equals( serverAttribute.getAttributeType() ) )
+                    {
+                        break;
+                    }
+
+                    throw new LdapUnwillingToPerformException( ResultCodeEnum.UNWILLING_TO_PERFORM,
+                        I18n.err( I18n.ERR_283 ) );
+                
+                default:
+                    throw new IllegalStateException( I18n.err( I18n.ERR_284, mod.getOperation() ) );
+            }
+        }
+    }
+    
+    
+    /**
+     * Handles the modify remove operation on the subschemaSubentry for schema entities. 
+     * 
+     * @param opAttrOid the numeric id of the operational attribute modified
+     * @param mods the attribute with the modifications
+     * to effect all dependents on the changed entity
+     * @throws Exception if there are problems updating the registries and the
+     * schema partition
+     */
+    private void modifyRemoveOperation( ModifyOperationContext modifyContext, String opAttrOid, 
+        Attribute mods ) throws LdapException
+    {
+        int index = opAttr2handlerIndex.get( opAttrOid );
+        
+        switch( index )
+        {
+            case( COMPARATOR_INDEX ):
+                LdapComparatorDescription[] comparatorDescriptions = parsers.parseComparators( mods );
+                
+                for ( LdapComparatorDescription comparatorDescription : comparatorDescriptions )
+                {
+                    subentryModifier.delete( modifyContext, comparatorDescription );
+                }
+                break;
+            case( NORMALIZER_INDEX ):
+                NormalizerDescription[] normalizerDescriptions = parsers.parseNormalizers( mods );
+                
+                for ( NormalizerDescription normalizerDescription : normalizerDescriptions )
+                {
+                    subentryModifier.delete( modifyContext, normalizerDescription );
+                }
+                
+                break;
+                
+            case( SYNTAX_CHECKER_INDEX ):
+                SyntaxCheckerDescription[] syntaxCheckerDescriptions = parsers.parseSyntaxCheckers( mods );
+                
+                for ( SyntaxCheckerDescription syntaxCheckerDescription : syntaxCheckerDescriptions )
+                {
+                    subentryModifier.delete( modifyContext, syntaxCheckerDescription );
+                }
+                
+                break;
+                
+            case( SYNTAX_INDEX ):
+                LdapSyntax[] syntaxes = parsers.parseLdapSyntaxes( mods );
+                
+                for ( LdapSyntax syntax : syntaxes )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, syntax );
+                }
+                
+                break;
+                
+            case( MATCHING_RULE_INDEX ):
+                MatchingRule[] mrs = parsers.parseMatchingRules( mods );
+                
+                for ( MatchingRule mr : mrs )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, mr );
+                }
+                
+                break;
+                
+            case( ATTRIBUTE_TYPE_INDEX ):
+                AttributeType[] ats = parsers.parseAttributeTypes( mods );
+                
+                for ( AttributeType at : ats )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, at );
+                }
+                
+                break;
+                
+            case( OBJECT_CLASS_INDEX ):
+                ObjectClass[] ocs = parsers.parseObjectClasses( mods );
+
+                for ( ObjectClass oc : ocs )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, oc );
+                }
+                
+                break;
+                
+            case( MATCHING_RULE_USE_INDEX ):
+                MatchingRuleUse[] mrus = parsers.parseMatchingRuleUses( mods );
+                
+                for ( MatchingRuleUse mru : mrus )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, mru );
+                }
+                
+                break;
+                
+            case( DIT_STRUCTURE_RULE_INDEX ):
+                DITStructureRule[] dsrs = parsers.parseDitStructureRules( mods );
+                
+                for ( DITStructureRule dsr : dsrs )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, dsr );
+                }
+                
+                break;
+                
+            case( DIT_CONTENT_RULE_INDEX ):
+                DITContentRule[] dcrs = parsers.parseDitContentRules( mods );
+                
+                for ( DITContentRule dcr : dcrs )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, dcr );
+                }
+                
+                break;
+                
+            case( NAME_FORM_INDEX ):
+                NameForm[] nfs = parsers.parseNameForms( mods );
+                
+                for ( NameForm nf : nfs )
+                {
+                    subentryModifier.deleteSchemaObject( modifyContext, nf );
+                }
+                
+                break;
+                
+            default:
+                throw new IllegalStateException( I18n.err( I18n.ERR_285, index ) );
+        }
+    }
+    
+    
+    /**
+     * Handles the modify add operation on the subschemaSubentry for schema entities. 
+     * 
+     * @param opAttrOid the numeric id of the operational attribute modified
+     * @param mods the attribute with the modifications
+     * @param doCascadeModify determines if a cascading operation should be performed
+     * to effect all dependents on the changed entity
+     * @throws Exception if there are problems updating the registries and the
+     * schema partition
+     */
+    private void modifyAddOperation( ModifyOperationContext modifyContext, String opAttrOid, 
+        Attribute mods, boolean doCascadeModify ) throws LdapException
+    {
+        if ( doCascadeModify )
+        {
+            LOG.error( CASCADING_ERROR );
+        }
+
+        int index = opAttr2handlerIndex.get( opAttrOid );
+        
+        switch( index )
+        {
+            case( COMPARATOR_INDEX ):
+                LdapComparatorDescription[] comparatorDescriptions = parsers.parseComparators( mods );
+                
+                for ( LdapComparatorDescription comparatorDescription : comparatorDescriptions )
+                {
+                    subentryModifier.add( modifyContext, comparatorDescription );
+                }
+                
+                break;
+                
+            case( NORMALIZER_INDEX ):
+                NormalizerDescription[] normalizerDescriptions = parsers.parseNormalizers( mods );
+                
+                for ( NormalizerDescription normalizerDescription : normalizerDescriptions )
+                {
+                    subentryModifier.add( modifyContext, normalizerDescription );
+                }
+                
+                break;
+                
+            case( SYNTAX_CHECKER_INDEX ):
+                SyntaxCheckerDescription[] syntaxCheckerDescriptions = parsers.parseSyntaxCheckers( mods );
+                
+                for ( SyntaxCheckerDescription syntaxCheckerDescription : syntaxCheckerDescriptions )
+                {
+                    subentryModifier.add( modifyContext, syntaxCheckerDescription );
+                }
+                
+                break;
+                
+            case( SYNTAX_INDEX ):
+                LdapSyntax[] syntaxes = parsers.parseLdapSyntaxes( mods );
+                
+                for ( LdapSyntax syntax : syntaxes )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, syntax );
+                }
+                
+                break;
+                
+            case( MATCHING_RULE_INDEX ):
+                MatchingRule[] mrs = parsers.parseMatchingRules( mods );
+                
+                for ( MatchingRule mr : mrs )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, mr );
+                }
+                
+                break;
+                
+            case( ATTRIBUTE_TYPE_INDEX ):
+                AttributeType[] ats = parsers.parseAttributeTypes( mods );
+                
+                for ( AttributeType at : ats )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, at );
+                }
+                
+                break;
+                
+            case( OBJECT_CLASS_INDEX ):
+                ObjectClass[] ocs = parsers.parseObjectClasses( mods );
+
+                for ( ObjectClass oc : ocs )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, oc );
+                }
+                
+                break;
+                
+            case( MATCHING_RULE_USE_INDEX ):
+                MatchingRuleUse[] mrus = parsers.parseMatchingRuleUses( mods );
+                
+                for ( MatchingRuleUse mru : mrus )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, mru );
+                }
+                
+                break;
+                
+            case( DIT_STRUCTURE_RULE_INDEX ):
+                DITStructureRule[] dsrs = parsers.parseDitStructureRules( mods );
+                
+                for ( DITStructureRule dsr : dsrs )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, dsr );
+                }
+                
+                break;
+                
+            case( DIT_CONTENT_RULE_INDEX ):
+                DITContentRule[] dcrs = parsers.parseDitContentRules( mods );
+                
+                for ( DITContentRule dcr : dcrs )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, dcr );
+                }
+                
+                break;
+                
+            case( NAME_FORM_INDEX ):
+                NameForm[] nfs = parsers.parseNameForms( mods );
+                
+                for ( NameForm nf : nfs )
+                {
+                    subentryModifier.addSchemaObject( modifyContext, nf );
+                }
+                
+                break;
+                
+            default:
+                throw new IllegalStateException( I18n.err( I18n.ERR_285, index ) );
+        }
+    }
+}

Added: directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryModifier.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryModifier.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryModifier.java (added)
+++ directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/SchemaSubentryModifier.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,331 @@
+/*
+ *  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.schema;
+
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.server.core.api.DnFactory;
+import org.apache.directory.server.core.api.interceptor.context.OperationContext;
+import org.apache.directory.shared.ldap.model.constants.MetaSchemaConstants;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.DefaultEntry;
+import org.apache.directory.shared.ldap.model.entry.Entry;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.exception.LdapInvalidDnException;
+import org.apache.directory.shared.ldap.model.name.Dn;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.DITContentRule;
+import org.apache.directory.shared.ldap.model.schema.DITStructureRule;
+import org.apache.directory.shared.ldap.model.schema.LdapSyntax;
+import org.apache.directory.shared.ldap.model.schema.MatchingRule;
+import org.apache.directory.shared.ldap.model.schema.MatchingRuleUse;
+import org.apache.directory.shared.ldap.model.schema.NameForm;
+import org.apache.directory.shared.ldap.model.schema.ObjectClass;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.model.schema.SchemaObject;
+import org.apache.directory.shared.ldap.model.schema.parsers.LdapComparatorDescription;
+import org.apache.directory.shared.ldap.model.schema.parsers.SyntaxCheckerDescription;
+import org.apache.directory.shared.ldap.model.schema.parsers.NormalizerDescription;
+import org.apache.directory.shared.ldap.model.schema.registries.Schema;
+import org.apache.directory.shared.util.Base64;
+
+
+/**
+ * Responsible for translating modify operations on the subschemaSubentry into 
+ * operations against entries within the schema partition.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SchemaSubentryModifier
+{
+    private static final Collection<String> BYPASS;
+    
+    static
+    {
+        Set<String> c = new HashSet<String>();
+        c.add( "AuthenticationInterceptor" );
+        c.add( "AciAuthorizationInterceptor" );
+        c.add( "DefaultAuthorizationInterceptor" );
+        c.add( "ExceptionInterceptor" );
+        c.add( "SchemaInterceptor" );
+        BYPASS = Collections.unmodifiableCollection( c );
+    }
+    
+    private AttributesFactory factory = new AttributesFactory();
+
+    /** The server schemaManager */
+    private SchemaManager schemaManager;
+
+    /** The Dn factory */
+    private DnFactory dnFactory;
+
+
+    /**
+     * 
+     * Creates a new instance of SchemaSubentryModifier.
+     *
+     * @param schemaManager The server schemaManager
+     * @param dnFactory The Dn factory
+     */
+    public SchemaSubentryModifier( SchemaManager schemaManager, DnFactory dnFactory )
+    {
+        this.schemaManager = schemaManager;
+        this.dnFactory = dnFactory;
+    }
+    
+    
+    private Dn getDn( SchemaObject obj ) throws LdapInvalidDnException
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "m-oid=" ).append( obj.getOid() ).append( ",ou=" );
+
+        if ( obj instanceof LdapSyntax )
+        {
+            buf.append( "syntaxes" );
+        }
+        else if ( obj instanceof MatchingRule )
+        {
+            buf.append( SchemaConstants.MATCHING_RULES_AT );
+        }
+        else if ( obj instanceof AttributeType )
+        {
+            buf.append( SchemaConstants.ATTRIBUTE_TYPES_AT );
+        }
+        else if ( obj instanceof ObjectClass )
+        {
+            buf.append( SchemaConstants.OBJECT_CLASSES_AT );
+        }
+        else if ( obj instanceof MatchingRuleUse )
+        {
+            buf.append( SchemaConstants.MATCHING_RULE_USE_AT );
+        }
+        else if ( obj instanceof DITStructureRule )
+        {
+            buf.append( SchemaConstants.DIT_STRUCTURE_RULES_AT );
+        }
+        else if ( obj instanceof DITContentRule )
+        {
+            buf.append( SchemaConstants.DIT_CONTENT_RULES_AT );
+        }
+        else if ( obj instanceof NameForm )
+        {
+            buf.append( SchemaConstants.NAME_FORMS_AT );
+        }
+
+        buf.append( ",cn=" ).append( obj.getSchemaName() ).append( ",ou=schema" );
+        return dnFactory.create( buf.toString() );
+    }
+    
+
+    public void add( OperationContext opContext, LdapComparatorDescription comparatorDescription ) throws LdapException
+    {
+        String schemaName = getSchema( comparatorDescription );   
+        Dn dn = dnFactory.create(
+            "m-oid=" + comparatorDescription.getOid(),
+            SchemaConstants.COMPARATORS_PATH,
+            "cn=" + schemaName,
+            SchemaConstants.OU_SCHEMA );
+        
+        Entry entry = getEntry( dn, comparatorDescription );
+
+        opContext.add( (Entry)entry, BYPASS );
+    }
+    
+    
+    public void add( OperationContext opContext, NormalizerDescription normalizerDescription ) throws LdapException
+    {
+        String schemaName = getSchema( normalizerDescription );
+        Dn dn = dnFactory.create(
+            "m-oid=" + normalizerDescription.getOid(),
+            SchemaConstants.NORMALIZERS_PATH , 
+            "cn=" + schemaName,
+            SchemaConstants.OU_SCHEMA );
+        
+        Entry entry = getEntry( dn, normalizerDescription );
+
+        opContext.add( (Entry)entry, BYPASS );
+    }
+    
+    
+    public void add( OperationContext opContext, SyntaxCheckerDescription syntaxCheckerDescription ) throws LdapException
+    {
+        String schemaName = getSchema( syntaxCheckerDescription );
+        Dn dn = dnFactory.create(
+            "m-oid=" + syntaxCheckerDescription.getOid(),
+            SchemaConstants.SYNTAX_CHECKERS_PATH,
+            "cn=" + schemaName, 
+            SchemaConstants.OU_SCHEMA );
+        
+        Entry entry = getEntry( dn, syntaxCheckerDescription );
+        opContext.add( (Entry)entry, BYPASS );
+    }
+    
+    
+    public void addSchemaObject( OperationContext opContext, SchemaObject obj ) throws LdapException
+    {
+        Schema schema = schemaManager.getLoadedSchema( obj.getSchemaName() );
+        Dn dn = getDn( obj );
+        Entry entry = factory.getAttributes( obj, schema, schemaManager );
+        entry.setDn( dn );
+
+        opContext.add( entry, BYPASS );
+    }
+
+
+    public void deleteSchemaObject( OperationContext opContext, SchemaObject obj ) throws LdapException
+    {
+        Dn dn = getDn( obj );
+        opContext.delete( dn, BYPASS );
+    }
+
+    
+    public void delete( OperationContext opContext, NormalizerDescription normalizerDescription ) throws LdapException
+    {
+        String schemaName = getSchema( normalizerDescription );
+        Dn dn = dnFactory.create(
+            "m-oid=" + normalizerDescription.getOid(),
+            SchemaConstants.NORMALIZERS_PATH,
+            "cn=" + schemaName, 
+            SchemaConstants.OU_SCHEMA );
+        
+        opContext.delete( dn, BYPASS );
+    }
+
+
+    public void delete( OperationContext opContext, SyntaxCheckerDescription syntaxCheckerDescription ) throws LdapException
+    {
+        String schemaName = getSchema( syntaxCheckerDescription );
+        Dn dn = dnFactory.create(
+            "m-oid=" + syntaxCheckerDescription.getOid(), 
+            SchemaConstants.SYNTAX_CHECKERS_PATH,
+            "cn=" + schemaName,
+            SchemaConstants.OU_SCHEMA );
+        opContext.delete( dn, BYPASS );
+    }
+
+
+    public void delete( OperationContext opContext, LdapComparatorDescription comparatorDescription ) throws LdapException
+    {
+        String schemaName = getSchema( comparatorDescription );
+        Dn dn = dnFactory.create(
+            "m-oid=" + comparatorDescription.getOid(),
+            SchemaConstants.COMPARATORS_PATH,
+            "cn=" + schemaName,
+            SchemaConstants.OU_SCHEMA );
+        
+        opContext.delete( dn, BYPASS );
+    }
+
+
+    private Entry getEntry( Dn dn, LdapComparatorDescription comparatorDescription )
+    {
+        Entry entry = new DefaultEntry( schemaManager, dn );
+        
+        entry.put( SchemaConstants.OBJECT_CLASS_AT, 
+                    SchemaConstants.TOP_OC, 
+                    MetaSchemaConstants.META_TOP_OC,
+                    MetaSchemaConstants.META_COMPARATOR_OC );
+        
+        entry.put( MetaSchemaConstants.M_OID_AT, comparatorDescription.getOid() );
+        entry.put( MetaSchemaConstants.M_FQCN_AT, comparatorDescription.getFqcn() );
+
+        if ( comparatorDescription.getBytecode() != null )
+        {
+            entry.put( MetaSchemaConstants.M_BYTECODE_AT, 
+                Base64.decode( comparatorDescription.getBytecode().toCharArray() ) );
+        }
+        
+        if ( comparatorDescription.getDescription() != null )
+        {
+            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, comparatorDescription.getDescription() );
+        }
+        
+        return entry;
+    }
+
+
+    private Entry getEntry( Dn dn, NormalizerDescription normalizerDescription )
+    {
+        Entry entry = new DefaultEntry( schemaManager, dn );
+
+        entry.put( SchemaConstants.OBJECT_CLASS_AT, 
+            SchemaConstants.TOP_OC, 
+            MetaSchemaConstants.META_TOP_OC,
+            MetaSchemaConstants.META_NORMALIZER_OC );
+        
+        entry.put( MetaSchemaConstants.M_OID_AT, normalizerDescription.getOid() );
+        entry.put( MetaSchemaConstants.M_FQCN_AT, normalizerDescription.getFqcn() );
+
+        if ( normalizerDescription.getBytecode() != null )
+        {
+            entry.put( MetaSchemaConstants.M_BYTECODE_AT, 
+                Base64.decode( normalizerDescription.getBytecode().toCharArray() ) );
+        }
+        
+        if ( normalizerDescription.getDescription() != null )
+        {
+            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, normalizerDescription.getDescription() );
+        }
+        
+        return entry;
+    }
+
+
+    private String getSchema( SchemaObject desc ) 
+    {
+        if ( desc.getExtensions().containsKey( MetaSchemaConstants.X_SCHEMA ) )
+        {
+            return desc.getExtensions().get( MetaSchemaConstants.X_SCHEMA ).get( 0 );
+        }
+        
+        return MetaSchemaConstants.SCHEMA_OTHER;
+    }
+    
+    
+    private Entry getEntry( Dn dn, SyntaxCheckerDescription syntaxCheckerDescription )
+    {
+        Entry entry = new DefaultEntry( schemaManager, dn );
+        
+        entry.put( SchemaConstants.OBJECT_CLASS_AT, 
+            SchemaConstants.TOP_OC, 
+            MetaSchemaConstants.META_TOP_OC,
+            MetaSchemaConstants.META_SYNTAX_CHECKER_OC );
+
+        entry.put( MetaSchemaConstants.M_OID_AT, syntaxCheckerDescription.getOid() );
+        entry.put( MetaSchemaConstants.M_FQCN_AT, syntaxCheckerDescription.getFqcn() );
+
+        if ( syntaxCheckerDescription.getBytecode() != null )
+        {
+            entry.put( MetaSchemaConstants.M_BYTECODE_AT,
+                Base64.decode(syntaxCheckerDescription.getBytecode().toCharArray()) );
+        }
+        
+        if ( syntaxCheckerDescription.getDescription() != null )
+        {
+            entry.put( MetaSchemaConstants.M_DESCRIPTION_AT, syntaxCheckerDescription.getDescription() );
+        }
+        
+        return entry;
+    }
+}

Added: directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/package-info.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/package-info.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/package-info.java (added)
+++ directory/apacheds/trunk/interceptors/schema/src/main/java/org/apache/directory/server/core/schema/package-info.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,55 @@
+/*
+ *  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.
+ *
+ */
+
+/**
+ * <pre>
+ * <p>
+ * Contains interfaces for schema object registry services and simple POJO
+ * implementations of these services.  Other helper interfaces and classes are
+ * included for handling monitoring of these services.
+ * </p>
+ * <p>
+ * These services and their POJO implementations are purposefully kept really
+ * simple here for a reason.  When one looks at these interfaces they stop and
+ * think why even bother having them when you can just use a map of objects
+ * somewhere.  These simple services can and will get more complex as other
+ * facilities come into play namely the object builders that populate these
+ * registries.  There might also be caching going on as well as disk based
+ * store access.  Finally dependencies become an issue and sometime bootstrap
+ * instances of these components are required by the system.  So these simple
+ * watered down interfaces and their POJO's have been pruned from previously
+ * complex environment specific versions of them.
+ * </p>
+ * <p>
+ * Some key points to apply to services and their POJO impls in this package:
+ * <ul>
+ * <li>registries only register and allow for lookups: its that simple!</li>
+ * <li>don't worry if they change over time</li>
+ * <li>don't worry about how they get populated</li>
+ * <li>don't worry who or what does the populating</li>
+ * <li>don't worry about where the information comes from</li>
+ * </ul>
+ * </p>
+ * </pre>
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+
+package org.apache.directory.server.core.schema;

Added: directory/apacheds/trunk/interceptors/schema/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/schema/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/schema/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java (added)
+++ directory/apacheds/trunk/interceptors/schema/src/test/java/org/apache/directory/server/core/schema/SchemaServiceTest.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,192 @@
+/*
+ *  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.schema;
+
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.io.File;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Set;
+
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+import org.apache.directory.shared.ldap.schemaextractor.SchemaLdifExtractor;
+import org.apache.directory.shared.ldap.schemaextractor.impl.DefaultSchemaLdifExtractor;
+import org.apache.directory.shared.ldap.schemaloader.LdifSchemaLoader;
+import org.apache.directory.shared.ldap.schemamanager.impl.DefaultSchemaManager;
+import org.apache.directory.shared.util.exception.Exceptions;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import com.mycila.junit.concurrent.Concurrency;
+import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
+
+/**
+ * Tests methods in SchemaInterceptor.
+ */
+@RunWith(ConcurrentJunitRunner.class)
+@Concurrency()
+public class SchemaServiceTest
+{
+    private static SchemaManager schemaManager;
+
+
+    @BeforeClass
+    public static void setUp() throws Exception
+    {
+        String workingDirectory = System.getProperty( "workingDirectory" );
+
+        if ( workingDirectory == null )
+        {
+            String path = SchemaServiceTest.class.getResource( "" ).getPath();
+            int targetPos = path.indexOf( "target" );
+            workingDirectory = path.substring( 0, targetPos + 6 );
+        }
+
+        File schemaRepository = new File( workingDirectory, "schema" );
+        SchemaLdifExtractor extractor = new DefaultSchemaLdifExtractor( new File( workingDirectory ) );
+        extractor.extractOrCopy( true );
+        LdifSchemaLoader loader = new LdifSchemaLoader( schemaRepository );
+        schemaManager = new DefaultSchemaManager( loader );
+
+        boolean loaded = schemaManager.loadAllEnabled();
+
+        if ( !loaded )
+        {
+            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
+        }
+
+        loaded = schemaManager.loadWithDeps( "nis" );
+
+        if ( !loaded )
+        {
+            fail( "Schema load failed : " + Exceptions.printErrors(schemaManager.getErrors()) );
+        }
+    }
+
+
+    @Test
+    public void testDescendants() throws Exception
+    {
+        Iterator<AttributeType> list = schemaManager.getAttributeTypeRegistry().descendants( "name" );
+        Set<String> nameAttrs = new HashSet<String>();
+
+        while ( list.hasNext() )
+        {
+            AttributeType type = list.next();
+            nameAttrs.add( type.getName() );
+        }
+
+        // We should only have 19 AT
+        String[] expectedNames = new String[]
+            { "sn", "generationQualifier", "ou", "c", "o", "l", "c-st", "givenName", "title", "cn", "initials",
+                "dmdName", "c-ou", "c-o", "apachePresence", "st", "c-l", "ads-serverId", "ads-indexAttributeId",
+                "ads-transportId", "ads-directoryServiceId", "ads-Id", "ads-extendedOpId", "ads-pwdId", 
+                "ads-compositeElement", "ads-replConsumerId", "ads-journalId", "ads-changeLogId", "ads-replProviderId" };
+
+        for ( String name : expectedNames )
+        {
+            if ( nameAttrs.contains( name ) )
+            {
+                nameAttrs.remove( name );
+            }
+        }
+
+        assertEquals( 0, nameAttrs.size() );
+    }
+    /*
+        public void testAlterObjectClassesBogusAttr() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "blah", "blah" );
+
+            try
+            {
+                SchemaInterceptor.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+                fail( "should not get here" );
+            }
+            catch ( LdapNamingException e )
+            {
+                assertEquals( ResultCodeEnum.OPERATIONS_ERROR, e.getResultCode() );
+            }
+
+            attr = new AttributeImpl( "objectClass" );
+            SchemaInterceptor.alterObjectClasses( attr );
+            assertEquals( 0, attr.size() );
+        }
+
+
+        public void testAlterObjectClassesNoAttrValue() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "objectClass" );
+            SchemaInterceptor.alterObjectClasses( attr );
+            assertEquals( 0, attr.size() );
+        }
+
+
+        public void testAlterObjectClassesTopAttrValue() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "objectClass", "top" );
+            SchemaInterceptor.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+            assertEquals( 0, attr.size() );
+        }
+
+
+        public void testAlterObjectClassesInetOrgPersonAttrValue() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "objectClass", "organizationalPerson" );
+            SchemaInterceptor.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+            assertEquals( 2, attr.size() );
+            assertTrue( attr.contains( "person" ) );
+            assertTrue( attr.contains( "organizationalPerson" ) );
+        }
+
+
+        public void testAlterObjectClassesOverlapping() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "objectClass", "organizationalPerson" );
+            attr.add( "residentialPerson" );
+            SchemaInterceptor.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+            assertEquals( 3, attr.size() );
+            assertTrue( attr.contains( "person" ) );
+            assertTrue( attr.contains( "organizationalPerson" ) );
+            assertTrue( attr.contains( "residentialPerson" ) );
+        }
+
+
+        public void testAlterObjectClassesOverlappingAndDsa() throws NamingException
+        {
+            Attribute attr = new AttributeImpl( "objectClass", "organizationalPerson" );
+            attr.add( "residentialPerson" );
+            attr.add( "dSA" );
+            SchemaInterceptor.alterObjectClasses( attr, registries.getObjectClassRegistry() );
+            assertEquals( 5, attr.size() );
+            assertTrue( attr.contains( "person" ) );
+            assertTrue( attr.contains( "organizationalPerson" ) );
+            assertTrue( attr.contains( "residentialPerson" ) );
+            assertTrue( attr.contains( "dSA" ) );
+            assertTrue( attr.contains( "applicationEntity" ) );
+        }
+        */
+}

Propchange: directory/apacheds/trunk/interceptors/subtree/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Fri Oct 14 22:36:08 2011
@@ -0,0 +1,11 @@
+.project
+.classpath
+.settings
+eclipse-classes
+*.log
+*.iml
+*.ipr
+dependency-reduced-pom.xml
+META-INF
+
+

Added: directory/apacheds/trunk/interceptors/subtree/pom.xml
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/subtree/pom.xml?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/subtree/pom.xml (added)
+++ directory/apacheds/trunk/interceptors/subtree/pom.xml Fri Oct 14 22:36:08 2011
@@ -0,0 +1,193 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<!--
+  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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+  <parent>
+    <groupId>org.apache.directory.server</groupId>
+    <artifactId>apacheds-interceptors</artifactId>
+    <version>2.0.0-M4-SNAPSHOT</version>
+  </parent>
+  
+  <artifactId>apacheds-interceptors-subtree</artifactId>
+  <name>ApacheDS Subtree Interceptor</name>
+  <packaging>jar</packaging>
+
+  <description>
+    Subtree interceptor
+  </description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.apache.directory.junit</groupId>
+      <artifactId>junit-addons</artifactId>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-i18n</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-api</artifactId>
+      <classifier>tests</classifier>
+      <scope>test</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-core-shared</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-interceptors-event</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>${project.groupId}</groupId>
+      <artifactId>apacheds-interceptors-normalization</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>commons-collections</groupId>
+      <artifactId>commons-collections</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>commons-lang</groupId>
+      <artifactId>commons-lang</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-client-api</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-i18n</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-codec-standalone</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-codec-core</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-extras-aci</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-extras-trigger</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-extras-util</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-model</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-schema-data</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-util</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>bouncycastle</groupId>
+      <artifactId>bcprov-jdk15</artifactId>
+    </dependency>
+    
+    <dependency>
+      <groupId>net.sf.ehcache</groupId>
+      <artifactId>ehcache-core</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>org.apache.directory.shared</groupId>
+      <artifactId>shared-ldap-extras-codec</artifactId>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-surefire-plugin</artifactId>
+        <configuration> 
+          <systemPropertyVariables>
+            <workingDirectory>${basedir}/target/server-work</workingDirectory>
+          </systemPropertyVariables>
+        </configuration>
+      </plugin>
+      
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-source-plugin</artifactId>
+        <executions>
+          <execution>
+            <id>attach-sources</id>
+            <phase>verify</phase>
+            <goals>
+              <goal>jar</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+
+    <resources>
+      <resource>
+        <directory>src/main/resources</directory>
+        <filtering>true</filtering>
+        <excludes>
+          <exclude>**/*.gif</exclude>
+        </excludes>
+      </resource>
+    </resources>
+  </build>
+</project>
+

Added: directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementEvaluator.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementEvaluator.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementEvaluator.java (added)
+++ directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementEvaluator.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,120 @@
+/*
+ *  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.subtree;
+
+
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.AndNode;
+import org.apache.directory.shared.ldap.model.filter.BranchNode;
+import org.apache.directory.shared.ldap.model.filter.ExprNode;
+import org.apache.directory.shared.ldap.model.filter.NotNode;
+import org.apache.directory.shared.ldap.model.filter.OrNode;
+import org.apache.directory.shared.ldap.model.filter.SimpleNode;
+
+
+/**
+ * The top level evaluation node for a refinement.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RefinementEvaluator
+{
+    /** Leaf Evaluator flyweight use for leaf filter assertions */
+    private RefinementLeafEvaluator leafEvaluator;
+
+
+    // ------------------------------------------------------------------------
+    // C O N S T R U C T O R S
+    // ------------------------------------------------------------------------
+
+    public RefinementEvaluator(RefinementLeafEvaluator leafEvaluator)
+    {
+        this.leafEvaluator = leafEvaluator;
+    }
+
+
+    public boolean evaluate( ExprNode node, Attribute objectClasses ) throws LdapException
+    {
+        if ( node == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_295 ) );
+        }
+        
+        if ( objectClasses == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_296 ) );
+        }
+        
+        if ( !( SchemaConstants.OBJECT_CLASS_AT_OID.equals( objectClasses.getAttributeType().getOid() ) ) )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_297 ) );
+        }
+        
+        if ( node.isLeaf() )
+        {
+            return leafEvaluator.evaluate( ( SimpleNode ) node, objectClasses );
+        }
+
+        BranchNode bnode = (BranchNode) node;
+
+        if ( node instanceof OrNode )
+        {
+            for ( ExprNode child:bnode.getChildren() )
+            {
+                if ( evaluate( child, objectClasses ) )
+                {
+                    return true;
+                }
+            }
+
+            return false;
+        }
+        else if ( node instanceof AndNode )
+        {
+            for ( ExprNode child:bnode.getChildren() )
+            {
+                if ( !evaluate( child, objectClasses ) )
+                {
+                    return false;
+                }
+            }
+
+            return true;
+            
+        }
+        else if ( node instanceof NotNode )
+        {
+            if ( null != bnode.getFirstChild() )
+            {
+                return !evaluate( bnode.getFirstChild(), objectClasses );
+            }
+
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_243, node ) );
+            
+        }
+        else
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_244, bnode ) );
+        }
+    }
+}

Added: directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementLeafEvaluator.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementLeafEvaluator.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementLeafEvaluator.java (added)
+++ directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/RefinementLeafEvaluator.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,136 @@
+/*
+ *  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.subtree;
+
+
+import java.util.Iterator;
+
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.model.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.model.entry.Attribute;
+import org.apache.directory.shared.ldap.model.exception.LdapException;
+import org.apache.directory.shared.ldap.model.filter.EqualityNode;
+import org.apache.directory.shared.ldap.model.filter.SimpleNode;
+import org.apache.directory.shared.ldap.model.schema.AttributeType;
+import org.apache.directory.shared.ldap.model.schema.SchemaManager;
+
+
+/**
+ * A refinement leaf node evaluator.  This evaluator checks to see if the
+ * objectClass attribute of a candidate entry is matched by a leaf node in
+ * a refinement filter expression tree.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class RefinementLeafEvaluator
+{
+    /** A SchemaManager instance */
+    private final SchemaManager schemaManager;
+
+    /** A storage for the ObjectClass attributeType */
+    private AttributeType OBJECT_CLASS_AT;
+
+
+    /**
+     * Creates a refinement filter's leaf node evaluator.
+     *
+     * @param schemaManager The server schemaManager
+     */
+    public RefinementLeafEvaluator( SchemaManager schemaManager)
+    {
+        this.schemaManager = schemaManager;
+        OBJECT_CLASS_AT = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+    }
+
+
+    /**
+     * Evaluates whether or not a simple leaf node of a refinement filter selects an
+     * entry based on the entry's objectClass attribute values.
+     *
+     * @param node the leaf node of the refinement filter
+     * @param objectClasses the objectClass attribute's values
+     * @return true if the leaf node selects the entry based on objectClass values, false
+     * if it rejects the entry
+     * @throws LdapException
+     */
+    public boolean evaluate( SimpleNode node, Attribute objectClasses ) throws LdapException
+    {
+        if ( node == null )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_295 ) );
+        }
+        
+        if ( !( node instanceof EqualityNode) )
+        {
+            throw new LdapException( I18n.err( I18n.ERR_301, node ) );
+        }
+        
+        if ( node.isSchemaAware() )
+        {
+            if ( !node.getAttributeType().equals( OBJECT_CLASS_AT ) )
+            {
+                throw new IllegalArgumentException( I18n.err( I18n.ERR_302, node.getAttribute() ) );
+            }
+        }
+        else if ( !node.getAttribute().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT ) &&
+                  !node.getAttribute().equalsIgnoreCase( SchemaConstants.OBJECT_CLASS_AT_OID ) )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_302, node.getAttribute() ) );
+        }
+            
+
+        if ( null == objectClasses )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_303 ) );
+        }
+        
+        if ( !(  objectClasses.isInstanceOf( OBJECT_CLASS_AT ) ) )
+        {
+            throw new IllegalArgumentException( I18n.err( I18n.ERR_304 ) );
+        }
+
+        // check if Ava value exists in attribute
+        // If the filter value for the objectClass is an OID we need to resolve a name
+        String value = node.getValue().getString();
+
+        if ( objectClasses.contains( value ) )
+        {
+            return true;
+        }
+        
+        if ( Character.isDigit( value.charAt( 0 ) ) )
+        {
+            Iterator<String> list = schemaManager.getGlobalOidRegistry().getNameSet( value ).iterator();
+            
+            while ( list.hasNext() )
+            {
+                String objectClass = list.next();
+                
+                if ( objectClasses.contains( objectClass ) )
+                {
+                    return true;
+                }
+            }
+        }
+
+        // no match so return false
+        return false;
+    }
+}

Added: directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/Subentry.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/Subentry.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/Subentry.java (added)
+++ directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/Subentry.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,129 @@
+/*
+ *  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.subtree;
+
+
+import java.util.Set;
+
+import org.apache.directory.shared.ldap.model.subtree.AdministrativeRole;
+import org.apache.directory.shared.ldap.model.subtree.SubtreeSpecification;
+
+
+/**
+ * An operational view of a subentry within the system. A Subentry can have
+ * many types (Collective, Schema, AccessControl or Trigger) but only one
+ * Subtree Specification.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Subentry
+{
+    /** The Subtree Specification associated with this subentry */
+    private SubtreeSpecification ss;
+
+    /** The administratives roles */
+    private Set<AdministrativeRole> administrativeRoles;
+
+
+    /**
+     * Stores the subtree
+     *
+     * @param ss The subtree specification
+     */
+    final void setSubtreeSpecification( SubtreeSpecification ss )
+    {
+        this.ss = ss;
+    }
+
+
+    /**
+     * @return The subtree specification
+     */
+    final SubtreeSpecification getSubtreeSpecification()
+    {
+        return ss;
+    }
+
+
+    /**
+     *
+     * TODO setAdministrativeRoles.
+     *
+     * @param administrativeRoles
+     */
+    final void setAdministrativeRoles( Set<AdministrativeRole> administrativeRoles )
+    {
+        this.administrativeRoles = administrativeRoles;
+    }
+
+
+    final Set<AdministrativeRole> getAdministrativeRoles()
+    {
+        return administrativeRoles;
+    }
+
+
+    /**
+     * Tells if the type contains the Collective attribute Administrative Role
+     */
+    final boolean isCollectiveAdminRole()
+    {
+        return administrativeRoles.contains( AdministrativeRole.CollectiveAttributeInnerArea ) ||
+        administrativeRoles.contains( AdministrativeRole.CollectiveAttributeSpecificArea );
+    }
+
+
+    /**
+     * Tells if the type contains the SubSchema Administrative Role
+     */
+    final boolean isSchemaAdminRole()
+    {
+        return administrativeRoles.contains( AdministrativeRole.SubSchemaSpecificArea );
+    }
+
+
+    /**
+     * Tells if the type contains the Access Control Administrative Role
+     */
+    final boolean isAccessControlAdminRole()
+    {
+        return administrativeRoles.contains( AdministrativeRole.AccessControlSpecificArea ) ||
+               administrativeRoles.contains( AdministrativeRole.AccessControlInnerArea );
+    }
+
+
+    /**
+     * Tells if the type contains the Triggers Administrative Role
+     */
+    final boolean isTriggersAdminRole()
+    {
+        return administrativeRoles.contains( AdministrativeRole.TriggerExecutionSpecificArea ) ||
+               administrativeRoles.contains( AdministrativeRole.TriggerExecutionInnerArea );
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        return "Subentry[" + administrativeRoles + ", " + ss + "]";
+    }
+}

Added: directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/SubentryCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/SubentryCache.java?rev=1183537&view=auto
==============================================================================
--- directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/SubentryCache.java (added)
+++ directory/apacheds/trunk/interceptors/subtree/src/main/java/org/apache/directory/server/core/subtree/SubentryCache.java Fri Oct 14 22:36:08 2011
@@ -0,0 +1,159 @@
+/*
+ *  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.subtree;
+
+
+import java.util.Iterator;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.directory.shared.ldap.model.name.Dn;
+
+
+/**
+ * A cache for subtree specifications. It associates a Subentry with a Dn,
+ * representing its position in the DIT.<br>
+ * This cache has a size limit set to 1000 at the moment. We should add a configuration
+ * parameter to manage its size.
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SubentryCache implements Iterable<Dn>
+{
+    /** The default cache size limit */
+    private static final int DEFAULT_CACHE_MAX_SIZE = 1000;
+    
+    /** The cache size limit */
+    private int cacheMaxSize = DEFAULT_CACHE_MAX_SIZE;
+    
+    /** The current cache size */
+    private AtomicInteger cacheSize;
+    
+    /** The Subentry cache */
+    private final Map<Dn, Subentry> cache;
+    
+    /**
+     * Creates a new instance of SubentryCache with a default maximum size.
+     */
+    public SubentryCache()
+    {
+        cache = new ConcurrentHashMap<Dn, Subentry>();
+        cacheSize = new AtomicInteger( 0 );
+    }
+    
+    
+    /**
+     * Creates a new instance of SubentryCache with a specific maximum size.
+     */
+    public SubentryCache( int maxSize )
+    {
+        cache = new ConcurrentHashMap<Dn, Subentry>();
+        cacheSize = new AtomicInteger( 0 );
+        cacheMaxSize = maxSize;
+    }
+    
+    
+    /**
+     * Retrieve a Subentry given a Dn. If there is none, null will be returned.
+     *
+     * @param dn The Dn we want to get the Subentry for
+     * @return The found Subentry, or null
+     */
+    final Subentry getSubentry( Dn dn )
+    {
+        return cache.get( dn );
+    }
+    
+    
+    /**
+     * Remove a Subentry for a given Dn
+     *
+     * @param dn The Dn for which we want to remove the
+     * associated Subentry
+     * @return The removed Subentry, if any
+     */
+    final Subentry removeSubentry( Dn dn )
+    {
+        Subentry oldSubentry = cache.remove( dn );
+        
+        if ( oldSubentry != null )
+        {
+            cacheSize.decrementAndGet();
+        }
+        
+        return oldSubentry;
+    }
+    
+    
+    /**
+     * Stores a new Subentry into the cache, associated with a Dn
+     *
+     * @param dn The Subentry Dn
+     * @param ss The SubtreeSpecification
+     * @param adminRoles The administrative roles for this Subentry
+     * @return The old Subentry, if any
+     */
+    /* No qualifier */ Subentry addSubentry( Dn dn, Subentry subentry )
+    {
+        if ( cacheSize.get() > cacheMaxSize )
+        {
+            // TODO : Throw an exception here
+        }
+        
+        Subentry oldSubentry = cache.put( dn, subentry );
+        
+        if ( oldSubentry == null )
+        {
+            cacheSize.getAndIncrement();
+        }
+        
+        return oldSubentry;
+    }
+    
+    
+    /**
+     * Tells if there is a Subentry associated with a Dn
+     * @param dn The Dn
+     * @return True if a Subentry is found
+     */
+    /* No qualifier */ boolean hasSubentry( Dn dn )
+    {
+        return cache.containsKey( dn );
+    }
+    
+    
+    /**
+     * @return An Iterator over the Subentry's DNs 
+     */
+    public Iterator<Dn> iterator()
+    {
+        return cache.keySet().iterator();
+    }
+    
+    
+    /**
+     * @return The number of elements in the cache
+     */
+    public int getCacheSize()
+    {
+        return cacheSize.get();
+    }
+}