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 2010/07/29 00:38:17 UTC

svn commit: r980257 [1/2] - in /directory/apacheds/trunk: core-api/src/main/java/org/apache/directory/server/core/interceptor/ core/src/main/java/org/apache/directory/server/core/ core/src/main/java/org/apache/directory/server/core/admin/ core/src/main...

Author: elecharny
Date: Wed Jul 28 22:38:17 2010
New Revision: 980257

URL: http://svn.apache.org/viewvc?rev=980257&view=rev
Log:
Added the AdminInterceptor

Added:
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/AdministrativeInterceptor.java
Modified:
    directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/ACDFEngine.java
    directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/MaxImmSubFilter.java
    directory/apacheds/trunk/interceptor-kerberos/src/main/java/org/apache/directory/server/core/kerberos/KeyDerivationInterceptor.java

Modified: directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java (original)
+++ directory/apacheds/trunk/core-api/src/main/java/org/apache/directory/server/core/interceptor/InterceptorChain.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core.interceptor;
 
@@ -549,8 +549,8 @@ public class InterceptorChain
 
 
     /**
-     * Eagerly populates fields of operation contexts so multiple Interceptors 
-     * in the processing pathway can reuse this value without performing a 
+     * Eagerly populates fields of operation contexts so multiple Interceptors
+     * in the processing pathway can reuse this value without performing a
      * redundant lookup operation.
      *
      * @param opContext the operation context to populate with cached fields
@@ -559,19 +559,19 @@ public class InterceptorChain
     @SuppressWarnings("PMD.EmptyCatchBlock")
     private void eagerlyPopulateFields( OperationContext opContext ) throws LdapException
     {
-        // If the entry field is not set for ops other than add for example 
+        // If the entry field is not set for ops other than add for example
         // then we set the entry but don't freak if we fail to do so since it
         // may not exist in the first place
 
         if ( opContext.getEntry() == null )
         {
             // We have to use the admin session here, otherwise we may have
-            // trouble reading the entry due to insufficient access rights 
+            // trouble reading the entry due to insufficient access rights
             CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();
-            
+
             Entry foundEntry = adminSession.lookup( opContext.getDn(),
                 SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES_ARRAY );
-            
+
             if ( foundEntry != null )
             {
                 if ( foundEntry instanceof DefaultEntry )
@@ -597,12 +597,12 @@ public class InterceptorChain
     private Entry getOriginalEntry( OperationContext opContext ) throws LdapException
     {
         // We have to use the admin session here, otherwise we may have
-        // trouble reading the entry due to insufficient access rights 
+        // trouble reading the entry due to insufficient access rights
         CoreSession adminSession = opContext.getSession().getDirectoryService().getAdminSession();
-        
+
         Entry foundEntry = adminSession.lookup( opContext.getDn(),
             SchemaConstants.ALL_OPERATIONAL_ATTRIBUTES_ARRAY );
-        
+
         if ( foundEntry != null )
         {
             return foundEntry;
@@ -616,7 +616,7 @@ public class InterceptorChain
         }
     }
 
-    
+
     public void delete( DeleteOperationContext deleteContext ) throws LdapException
     {
         Element entry = getStartingEntry();
@@ -818,7 +818,7 @@ public class InterceptorChain
         Interceptor head = entry.interceptor;
         NextInterceptor next = entry.nextInterceptor;
         eagerlyPopulateFields( renameContext );
-        
+
         try
         {
             head.rename( next, renameContext );
@@ -840,7 +840,7 @@ public class InterceptorChain
         Interceptor head = entry.interceptor;
         NextInterceptor next = entry.nextInterceptor;
         Entry originalEntry = getOriginalEntry( moveContext );
-        
+
         moveContext.setOriginalEntry( originalEntry );
 
         try
@@ -924,14 +924,14 @@ public class InterceptorChain
                     }
 
                     OperationContext opContext = InvocationStack.getInstance().peek();
-                    
+
                     if ( !opContext.hasBypass() )
                     {
                         return Element.this.nextEntry;
                     }
 
                     Element next = Element.this.nextEntry;
-                    
+
                     while ( next != tail )
                     {
                         if ( opContext.isBypassed( next.getName() ) )

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/DefaultDirectoryService.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core;
 
@@ -38,6 +38,7 @@ import java.util.UUID;
 import javax.naming.directory.Attributes;
 
 import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.admin.AdministrativeInterceptor;
 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
@@ -103,22 +104,22 @@ import org.slf4j.LoggerFactory;
 
 /**
  * Default implementation of {@link DirectoryService}.
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class DefaultDirectoryService implements DirectoryService
 {
     /** The logger */
     private static final Logger LOG = LoggerFactory.getLogger( DefaultDirectoryService.class );
-    
+
     private SchemaService schemaService;
-    
+
     /** A reference on the SchemaManager */
     private SchemaManager schemaManager;
-    
+
     /** the root nexus */
     private DefaultPartitionNexus partitionNexus;
-    
+
     /** whether or not server is started for the first time */
     private boolean firstStart;
 
@@ -130,34 +131,34 @@ public class DefaultDirectoryService imp
 
     /** the change log service */
     private ChangeLog changeLog;
-    
+
     /** the journal service */
     private Journal journal;
-    
-    /** 
-     * the interface used to perform various operations on this 
+
+    /**
+     * the interface used to perform various operations on this
      * DirectoryService
      */
     private OperationManager operationManager = new DefaultOperationManager( this );
 
     /** the distinguished name of the administrative user */
     private DN adminDn;
-    
+
     /** session used as admin for internal operations */
     private CoreSession adminSession;
-    
+
     /** The referral manager */
     private ReferralManager referralManager;
-    
+
     /** A flag to tell if the userPassword attribute's value must be hidden */
     private boolean passwordHidden = false;
-    
+
     /** The service's CSN factory */
     private CsnFactory csnFactory;
-    
+
     /** The directory instance replication ID */
     private int replicaId;
-    
+
     /** The replication configuration structure */
     private ReplicationConfiguration replicationConfig;
 
@@ -168,20 +169,20 @@ public class DefaultDirectoryService imp
             "changes are made by the admin user.\n Furthermore the used controls are not at " +
             "all taken into account";
 
-    
+
     /** The delay to wait between each sync on disk */
     private long syncPeriodMillis;
-    
+
     /** The default delay to wait between sync on disk : 15 seconds */
     private static final long DEFAULT_SYNC_PERIOD = 15000;
 
     /** */
     private Thread workerThread;
-    
+
     /** The sync worker thread */
     private SynchWorker worker = new SynchWorker();
 
-   
+
     /** The default timeLimit : 100 entries */
     public static final int MAX_SIZE_LIMIT_DEFAULT = 100;
 
@@ -190,62 +191,62 @@ public class DefaultDirectoryService imp
 
     /** The instance Id */
     private String instanceId;
-    
+
     /** The server working directory */
     private File workingDirectory = new File( "server-work" );
-    
-    /** 
+
+    /**
      * A flag used to shutdown the VM when stopping the server. Useful
      * when the server is standalone. If the server is embedded, we don't
      * want to shutdown the VM
      */
     private boolean exitVmOnShutdown = true; // allow by default
-    
+
     /** A flag used to indicate that a shutdown hook has been installed */
     private boolean shutdownHookEnabled = true; // allow by default
-    
+
     /** Manage anonymous access to entries other than the RootDSE */
     private boolean allowAnonymousAccess = true; // allow by default
-    
+
     /** Manage the basic access control checks */
     private boolean accessControlEnabled; // off by default
-    
+
     /** Manage the operational attributes denormalization */
     private boolean denormalizeOpAttrsEnabled; // off by default
-    
+
     /** The list of declared interceptors */
     private List<Interceptor> interceptors;
-    
+
     /** The System partition */
     private Partition systemPartition;
-    
+
     /** The set of all declared partitions */
     private Set<Partition> partitions = new HashSet<Partition>();
-    
+
     /** A list of LDIF entries to inject at startup */
     private List<? extends LdifEntry> testEntries = new ArrayList<LdifEntry>(); // List<Attributes>
-    
+
     /** The event service */
     private EventService eventService;
-    
+
     /** The maximum size for an incoming PDU */
     private int maxPDUSize = Integer.MAX_VALUE;
 
     /** the value of last successful add/update operation's CSN */
     private String contextCsn;
-    
+
     /** lock file for directory service's working directory */
     private RandomAccessFile lockFile = null;
-    
+
     private static final String LOCK_FILE_NAME = ".dirservice.lock";
-    
+
     /**
      * The synchronizer thread. It flush data on disk periodically.
      */
     class SynchWorker implements Runnable
     {
         final Object lock = new Object();
-        
+
         /** A flag to stop the thread */
         boolean stop;
 
@@ -280,13 +281,13 @@ public class DefaultDirectoryService imp
             }
         }
     }
-    
-    
+
+
     // ------------------------------------------------------------------------
     // Constructor
     // ------------------------------------------------------------------------
-    
-    
+
+
     /**
      * Creates a new instance of the directory service.
      */
@@ -304,8 +305,8 @@ public class DefaultDirectoryService imp
     // ------------------------------------------------------------------------
     // C O N F I G U R A T I O N   M E T H O D S
     // ------------------------------------------------------------------------
-    
-    
+
+
     public void setInstanceId( String instanceId )
     {
         this.instanceId = instanceId;
@@ -341,16 +342,16 @@ public class DefaultDirectoryService imp
         Set<Partition> cloned = new HashSet<Partition>();
         cloned.addAll( partitions );
         Set<String> names = new HashSet<String>();
-        
+
         for ( Partition partition : cloned )
         {
             String id = partition.getId();
-            
+
             if ( names.contains( id ) )
             {
                 LOG.warn( "Encountered duplicate partition {} identifier.", id );
             }
-            
+
             names.add( id );
         }
 
@@ -425,14 +426,14 @@ public class DefaultDirectoryService imp
      *
      * @param interceptors the interceptors to be used in the server.
      */
-    public void setInterceptors( List<Interceptor> interceptors ) 
+    public void setInterceptors( List<Interceptor> interceptors )
     {
         Set<String> names = new HashSet<String>();
-        
+
         for ( Interceptor interceptor : interceptors )
         {
             String name = interceptor.getName();
-            
+
             if ( names.contains( name ) )
             {
                 LOG.warn( "Encountered duplicate definitions for {} interceptor", interceptor.getName() );
@@ -630,6 +631,7 @@ public class DefaultDirectoryService imp
         list.add( new ReferralInterceptor() );
         list.add( new AciAuthorizationInterceptor() );
         list.add( new DefaultAuthorizationInterceptor() );
+        list.add( new AdministrativeInterceptor() );
         list.add( new ExceptionInterceptor() );
         list.add( new ChangeLogInterceptor() );
         list.add( new OperationalAttributeInterceptor() );
@@ -643,25 +645,25 @@ public class DefaultDirectoryService imp
         setInterceptors( list );
     }
 
-    
+
     public CoreSession getAdminSession()
     {
         return adminSession;
     }
-    
-    
-    public CoreSession getSession() 
+
+
+    public CoreSession getSession()
     {
         return new DefaultCoreSession( new LdapPrincipal(), this );
     }
-    
-    
+
+
     public CoreSession getSession( LdapPrincipal principal )
     {
         return new DefaultCoreSession( principal, this );
     }
-    
-    
+
+
     public CoreSession getSession( DN principalDn, byte[] credentials ) throws LdapException
     {
         if ( ! started )
@@ -673,12 +675,12 @@ public class DefaultDirectoryService imp
         bindContext.setCredentials( credentials );
         bindContext.setDn( principalDn );
         operationManager.bind( bindContext );
-        
+
         return bindContext.getSession();
     }
-    
-    
-    public CoreSession getSession( DN principalDn, byte[] credentials, String saslMechanism, String saslAuthId ) 
+
+
+    public CoreSession getSession( DN principalDn, byte[] credentials, String saslMechanism, String saslAuthId )
         throws Exception
     {
         if ( ! started )
@@ -691,7 +693,7 @@ public class DefaultDirectoryService imp
         bindContext.setDn( principalDn );
         bindContext.setSaslMechanism( saslMechanism );
         operationManager.bind( bindContext );
-        
+
         return bindContext.getSession();
     }
 
@@ -704,7 +706,7 @@ public class DefaultDirectoryService imp
         }
 
         Tag latest = changeLog.getLatest();
-        
+
         if ( null != latest )
         {
             if ( latest.getRevision() < changeLog.getCurrentRevision() )
@@ -723,7 +725,7 @@ public class DefaultDirectoryService imp
 
 
     /**
-     * We handle the ModDN/ModRDN operation for the revert here. 
+     * We handle the ModDN/ModRDN operation for the revert here.
      */
     private void moddn( DN oldDn, DN newDn, boolean delOldRdn ) throws LdapException
     {
@@ -747,7 +749,7 @@ public class DefaultDirectoryService imp
          * RDN name change or a move operation.  If the two names are the same
          * except for the RDN then it is a simple modifyRdn operation.  If the
          * names differ in size or have a different baseDN then the operation is
-         * a move operation.  Furthermore if the RDN in the move operation 
+         * a move operation.  Furthermore if the RDN in the move operation
          * changes it is both an RDN change and a move operation.
          */
         if ( ( oldDn.size() == newDn.size() ) && oldBase.equals( newBase ) )
@@ -769,8 +771,8 @@ public class DefaultDirectoryService imp
             }
         }
     }
-    
-    
+
+
     public long revert( long revision ) throws LdapException
     {
         if ( changeLog == null || ! changeLog.isEnabled() )
@@ -801,7 +803,7 @@ public class DefaultDirectoryService imp
          *
          * First of all just stop using JNDI and construct the operations to
          * feed into the interceptor pipeline.
-         * 
+         *
          * TODO review this code.
          */
 
@@ -809,42 +811,42 @@ public class DefaultDirectoryService imp
         {
             LOG.warn( PARTIAL_IMPL_WARNING );
             cursor.afterLast();
-            
+
             while ( cursor.previous() ) // apply ldifs in reverse order
             {
                 ChangeLogEvent event = cursor.get();
                 List<LdifEntry> reverses = event.getReverseLdifs();
-                
+
                 for ( LdifEntry reverse:reverses )
                 {
                     switch( reverse.getChangeType().getChangeType() )
                     {
                         case ChangeType.ADD_ORDINAL :
-                            adminSession.add( 
-                                new DefaultEntry( schemaManager, reverse.getEntry() ), true ); 
+                            adminSession.add(
+                                new DefaultEntry( schemaManager, reverse.getEntry() ), true );
                             break;
-                            
+
                         case ChangeType.DELETE_ORDINAL :
                             adminSession.delete( reverse.getDn(), true );
                             break;
-                            
+
                         case ChangeType.MODIFY_ORDINAL :
                             List<Modification> mods = reverse.getModificationItems();
-    
+
                             adminSession.modify( reverse.getDn(), mods, true );
                             break;
-                            
+
                         case ChangeType.MODDN_ORDINAL :
                             // NO BREAK - both ModDN and ModRDN handling is the same
-                        
+
                         case ChangeType.MODRDN_ORDINAL :
                             DN forwardDn = event.getForwardLdif().getDn();
                             DN reverseDn = reverse.getDn();
-                            
+
                             moddn( reverseDn, forwardDn, reverse.isDeleteOldRdn() );
-    
+
                             break;
-                            
+
                         default:
                             LOG.error( I18n.err( I18n.ERR_75 ) );
                             throw new NotImplementedException( I18n.err( I18n.ERR_76, reverse.getChangeType() ) );
@@ -860,18 +862,19 @@ public class DefaultDirectoryService imp
         }
         catch ( Exception e )
         {
+            e.printStackTrace();
             throw new LdapOperationException( e.getMessage() );
         }
 
         return changeLog.getCurrentRevision();
     }
 
-    
+
     public OperationManager getOperationManager()
     {
         return operationManager;
     }
-    
+
 
     /**
      * @throws Exception if the LDAP server cannot be started
@@ -884,7 +887,7 @@ public class DefaultDirectoryService imp
         }
 
         lockWorkDir();
-        
+
         if ( shutdownHookEnabled )
         {
             Runtime.getRuntime().addShutdownHook( new Thread( new Runnable()
@@ -913,7 +916,7 @@ public class DefaultDirectoryService imp
 
         initialize();
         showSecurityWarnings();
-        
+
         // Start the sync thread if required
         if ( syncPeriodMillis > 0 )
         {
@@ -926,7 +929,7 @@ public class DefaultDirectoryService imp
         loc.setDn( systemPartition.getSuffix() );
         loc.setAttrsId( new String[]{ "+" } );
         ClonedServerEntry entry = systemPartition.lookup( loc );
-        
+
         EntryAttribute cntextCsnAt = entry.get( SchemaConstants.CONTEXT_CSN_AT );
         if( cntextCsnAt != null )
         {
@@ -967,7 +970,7 @@ public class DefaultDirectoryService imp
         // --------------------------------------------------------------------
         changeLog.sync();
         changeLog.destroy();
-        
+
         // --------------------------------------------------------------------
         // Shutdown the journal if enabled
         // --------------------------------------------------------------------
@@ -982,19 +985,19 @@ public class DefaultDirectoryService imp
 
         partitionNexus.sync();
         partitionNexus.destroy();
-        
+
         // --------------------------------------------------------------------
         // Shutdown the sync thread
         // --------------------------------------------------------------------
         if ( workerThread != null )
         {
             worker.stop = true;
-            
+
             synchronized ( worker.lock )
             {
                 worker.lock.notify();
             }
-    
+
             while ( workerThread.isAlive() )
             {
                 LOG.info( "Waiting for SynchWorkerThread to die." );
@@ -1002,12 +1005,12 @@ public class DefaultDirectoryService imp
             }
         }
 
-        
+
         // --------------------------------------------------------------------
         // And shutdown the server
         // --------------------------------------------------------------------
         interceptorChain.destroy();
-        
+
         if ( lockFile != null )
         {
             try
@@ -1020,12 +1023,12 @@ public class DefaultDirectoryService imp
                 LOG.warn( "couldn't delete the lock file {}", LOCK_FILE_NAME );
             }
         }
-        
+
         started = false;
         setDefaultInterceptorConfigurations();
     }
 
-    
+
     /**
      * @return The referral manager
      */
@@ -1042,8 +1045,8 @@ public class DefaultDirectoryService imp
     {
         this.referralManager = referralManager;
     }
-    
-    
+
+
     /**
      * @return the SchemaManager
      */
@@ -1051,8 +1054,8 @@ public class DefaultDirectoryService imp
     {
         return schemaManager;
     }
-    
-    
+
+
     /**
      * Set the SchemaManager instance.
      *
@@ -1100,11 +1103,11 @@ public class DefaultDirectoryService imp
     }
 
 
-    public Entry newEntry( DN dn ) 
+    public Entry newEntry( DN dn )
     {
         return new DefaultEntry( schemaManager, dn );
     }
-    
+
 
     /**
      * Returns true if we had to create the bootstrap entries on the first
@@ -1117,7 +1120,7 @@ public class DefaultDirectoryService imp
     private boolean createBootstrapEntries() throws Exception
     {
         boolean firstStart = false;
-        
+
         // -------------------------------------------------------------------
         // create admin entry
         // -------------------------------------------------------------------
@@ -1130,8 +1133,8 @@ public class DefaultDirectoryService imp
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, adminDn );
-            
-            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, 
+
+            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
                                 SchemaConstants.TOP_OC,
                                 SchemaConstants.PERSON_OC,
                                 SchemaConstants.ORGANIZATIONAL_PERSON_OC,
@@ -1157,14 +1160,14 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN userDn = new DN( ServerDNConstants.USERS_SYSTEM_DN, schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, userDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, userDn );
-            
-            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, 
+
+            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
                                 SchemaConstants.TOP_OC,
                                 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
 
@@ -1182,14 +1185,14 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN groupDn = new DN( ServerDNConstants.GROUPS_SYSTEM_DN, schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, groupDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, groupDn );
-            
-            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, 
+
+            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
                                 SchemaConstants.TOP_OC,
                                 SchemaConstants.ORGANIZATIONAL_UNIT_OC );
 
@@ -1207,14 +1210,14 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN name = new DN( ServerDNConstants.ADMINISTRATORS_GROUP_DN, schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, name ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, name );
-            
-            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, 
+
+            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
                                 SchemaConstants.TOP_OC,
                                 SchemaConstants.GROUP_OF_UNIQUE_NAMES_OC );
 
@@ -1233,7 +1236,7 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN configurationDn = new DN( "ou=configuration,ou=system", schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, configurationDn ) ) )
         {
             firstStart = true;
@@ -1255,7 +1258,7 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN partitionsDn = new DN( "ou=partitions,ou=configuration,ou=system", schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, partitionsDn ) ) )
         {
             firstStart = true;
@@ -1276,7 +1279,7 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN servicesDn = new DN( "ou=services,ou=configuration,ou=system", schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, servicesDn ) ) )
         {
             firstStart = true;
@@ -1298,7 +1301,7 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN interceptorsDn = new DN( "ou=interceptors,ou=configuration,ou=system", schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, interceptorsDn ) ) )
         {
             firstStart = true;
@@ -1320,14 +1323,14 @@ public class DefaultDirectoryService imp
         // -------------------------------------------------------------------
 
         DN sysPrefRootDn = new DN( ServerDNConstants.SYSPREFROOT_SYSTEM_DN, schemaManager );
-        
+
         if ( !partitionNexus.hasEntry( new EntryOperationContext( adminSession, sysPrefRootDn ) ) )
         {
             firstStart = true;
 
             Entry serverEntry = new DefaultEntry( schemaManager, sysPrefRootDn );
-            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT, 
-                SchemaConstants.TOP_OC, 
+            serverEntry.put( SchemaConstants.OBJECT_CLASS_AT,
+                SchemaConstants.TOP_OC,
                 SchemaConstants.ORGANIZATIONAL_UNIT_OC,
                 SchemaConstants.EXTENSIBLE_OBJECT_OC );
 
@@ -1354,11 +1357,11 @@ public class DefaultDirectoryService imp
         boolean needToChangeAdminPassword = false;
 
         DN adminDn = new DN( ServerDNConstants.ADMIN_SYSTEM_DN, schemaManager );
-        
+
         Entry adminEntry = partitionNexus.lookup( new LookupOperationContext( adminSession, adminDn ) );
         Value<?> userPassword = adminEntry.get( SchemaConstants.USER_PASSWORD_AT ).get();
         needToChangeAdminPassword = Arrays.equals( PartitionNexus.ADMIN_PASSWORD_BYTES, userPassword.getBytes() );
-        
+
         if ( needToChangeAdminPassword )
         {
             LOG.warn( "You didn't change the admin password of directory service " + "instance '" + instanceId + "'.  "
@@ -1371,7 +1374,7 @@ public class DefaultDirectoryService imp
      * Adds test entries into the core.
      *
      * @todo this may no longer be needed when JNDI is not used for bootstrapping
-     * 
+     *
      * @throws Exception if the creation of test entries fails.
      */
     private void createTestEntries() throws Exception
@@ -1386,7 +1389,7 @@ public class DefaultDirectoryService imp
 
                 try
                 {
-                    getAdminSession().add( new DefaultEntry( schemaManager, entry ) ); 
+                    getAdminSession().add( new DefaultEntry( schemaManager, entry ) );
                 }
                 catch ( Exception e )
                 {
@@ -1421,7 +1424,7 @@ public class DefaultDirectoryService imp
 
         adminDn = new DN( ServerDNConstants.ADMIN_SYSTEM_DN, schemaManager );
         adminSession = new DefaultCoreSession( new LdapPrincipal( adminDn, AuthenticationLevel.STRONG ), this );
-        
+
         // @TODO - NOTE: Need to find a way to instantiate without dependency on DPN
         partitionNexus = new DefaultPartitionNexus( new DefaultEntry( schemaManager, DN.EMPTY_DN ) );
         partitionNexus.setDirectoryService( this );
@@ -1430,7 +1433,7 @@ public class DefaultDirectoryService imp
         // --------------------------------------------------------------------
         // Create all the bootstrap entries before initializing chain
         // --------------------------------------------------------------------
-        
+
         firstStart = createBootstrapEntries();
 
         interceptorChain = new InterceptorChain();
@@ -1439,18 +1442,18 @@ public class DefaultDirectoryService imp
         // --------------------------------------------------------------------
         // Initialize the changeLog if it's enabled
         // --------------------------------------------------------------------
-        
+
         if ( changeLog.isEnabled() )
         {
             changeLog.init( this );
-            
+
             if( changeLog.isExposed() && changeLog.isTagSearchSupported() )
             {
                 String clSuffix = ( ( TaggableSearchableChangeLogStore ) changeLog.getChangeLogStore() ).getPartition().getSuffix().getName();
                 partitionNexus.getRootDSE( null ).add( SchemaConstants.CHANGELOG_CONTEXT_AT, clSuffix );
             }
         }
-        
+
         // --------------------------------------------------------------------
         // Initialize the journal if it's enabled
         // --------------------------------------------------------------------
@@ -1464,11 +1467,11 @@ public class DefaultDirectoryService imp
             LOG.debug( "<--- DefaultDirectoryService initialized" );
         }
     }
-    
-    
+
+
     /**
      * Read an entry (without DN)
-     * 
+     *
      * @param text The ldif format file
      * @return An entry.
      */
@@ -1534,10 +1537,10 @@ public class DefaultDirectoryService imp
         return entry;
     }
 
-    
+
     /**
      * Create a new Entry
-     * 
+     *
      * @param ldif The String representing the attributes, as a LDIF file
      * @param dn The DN for this new entry
      */
@@ -1547,9 +1550,9 @@ public class DefaultDirectoryService imp
         {
             Entry entry = readEntry( ldif );
             DN newDn = new DN( dn );
-            
+
             entry.setDn( newDn );
-            
+
             // TODO Let's get rid of this Attributes crap
             Entry serverEntry = new DefaultEntry( schemaManager, entry );
             return serverEntry;
@@ -1573,8 +1576,8 @@ public class DefaultDirectoryService imp
     {
         this.eventService = eventService;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
@@ -1582,8 +1585,8 @@ public class DefaultDirectoryService imp
     {
         return passwordHidden;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
@@ -1603,7 +1606,7 @@ public class DefaultDirectoryService imp
 
 
     /**
-     * Set the maximum allowed size for an incoming PDU 
+     * Set the maximum allowed size for an incoming PDU
      * @param maxPDUSize A positive number of bytes for the PDU. A negative or
      * null value will be transformed to {@link Integer#MAX_VALUE}
      */
@@ -1613,11 +1616,11 @@ public class DefaultDirectoryService imp
         {
             maxPDUSize = Integer.MAX_VALUE;
         }
-        
+
         this.maxPDUSize = maxPDUSize;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
@@ -1630,7 +1633,7 @@ public class DefaultDirectoryService imp
                 return interceptor;
             }
         }
-        
+
         return null;
     }
 
@@ -1674,10 +1677,10 @@ public class DefaultDirectoryService imp
     public void setReplicationConfiguration( ReplicationConfiguration replicationConfig )
     {
         this.replicationConfig = replicationConfig;
-        
+
     }
-    
-    
+
+
     /**
      * @return the replication configuration for this DirectoryService
      */
@@ -1685,8 +1688,8 @@ public class DefaultDirectoryService imp
     {
         return replicationConfig;
     }
-    
-    
+
+
     /**
      * {@inheritDoc}
      */
@@ -1721,8 +1724,8 @@ public class DefaultDirectoryService imp
     {
         this.contextCsn = lastKnownCsn;
     }
-    
-    
+
+
     /**
      * checks if the working directory is already in use by some other directory service, if yes
      * then throws a runtime exception else will obtain the lock on the working directory
@@ -1730,7 +1733,7 @@ public class DefaultDirectoryService imp
     private void lockWorkDir()
     {
         FileLock fileLock = null;
-        
+
         try
         {
             lockFile = new RandomAccessFile( workingDirectory.getAbsolutePath() + File.separator + LOCK_FILE_NAME, "rw" );
@@ -1753,13 +1756,13 @@ public class DefaultDirectoryService imp
             // shouldn't happen, but log anyway
             LOG.error( "failed to lock the work directory", e );
         }
-        
+
         if ( ( fileLock == null ) || ( !fileLock.isValid() ) )
         {
             String message = "the working directory " + workingDirectory + " has been locked by another directory service.";
             LOG.error( message );
             throw new RuntimeException( message );
         }
-        
+
     }
 }

Added: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/AdministrativeInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/AdministrativeInterceptor.java?rev=980257&view=auto
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/AdministrativeInterceptor.java (added)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/admin/AdministrativeInterceptor.java Wed Jul 28 22:38:17 2010
@@ -0,0 +1,509 @@
+/*
+ *  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.admin;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+
+import javax.naming.directory.SearchControls;
+
+import org.apache.directory.server.constants.ServerDNConstants;
+import org.apache.directory.server.core.CoreSession;
+import org.apache.directory.server.core.DefaultCoreSession;
+import org.apache.directory.server.core.DirectoryService;
+import org.apache.directory.server.core.LdapPrincipal;
+import org.apache.directory.server.core.authn.Authenticator;
+import org.apache.directory.server.core.filtering.EntryFilteringCursor;
+import org.apache.directory.server.core.interceptor.BaseInterceptor;
+import org.apache.directory.server.core.interceptor.NextInterceptor;
+import org.apache.directory.server.core.interceptor.context.AddOperationContext;
+import org.apache.directory.server.core.interceptor.context.DeleteOperationContext;
+import org.apache.directory.server.core.interceptor.context.ModifyOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveAndRenameOperationContext;
+import org.apache.directory.server.core.interceptor.context.MoveOperationContext;
+import org.apache.directory.server.core.interceptor.context.RenameOperationContext;
+import org.apache.directory.server.core.interceptor.context.SearchOperationContext;
+import org.apache.directory.server.core.partition.PartitionNexus;
+import org.apache.directory.server.i18n.I18n;
+import org.apache.directory.shared.ldap.constants.AuthenticationLevel;
+import org.apache.directory.shared.ldap.constants.SchemaConstants;
+import org.apache.directory.shared.ldap.entry.DefaultEntryAttribute;
+import org.apache.directory.shared.ldap.entry.Entry;
+import org.apache.directory.shared.ldap.entry.EntryAttribute;
+import org.apache.directory.shared.ldap.entry.Modification;
+import org.apache.directory.shared.ldap.entry.StringValue;
+import org.apache.directory.shared.ldap.entry.Value;
+import org.apache.directory.shared.ldap.exception.LdapAttributeInUseException;
+import org.apache.directory.shared.ldap.exception.LdapException;
+import org.apache.directory.shared.ldap.exception.LdapInvalidAttributeValueException;
+import org.apache.directory.shared.ldap.exception.LdapNoSuchAttributeException;
+import org.apache.directory.shared.ldap.exception.LdapOperationException;
+import org.apache.directory.shared.ldap.exception.LdapUnwillingToPerformException;
+import org.apache.directory.shared.ldap.filter.EqualityNode;
+import org.apache.directory.shared.ldap.filter.ExprNode;
+import org.apache.directory.shared.ldap.message.AliasDerefMode;
+import org.apache.directory.shared.ldap.message.ResultCodeEnum;
+import org.apache.directory.shared.ldap.name.DN;
+import org.apache.directory.shared.ldap.schema.AttributeType;
+import org.apache.directory.shared.ldap.schema.SchemaManager;
+import org.apache.directory.shared.ldap.util.StringTools;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * An interceptor to manage the Administrative model
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class AdministrativeInterceptor extends BaseInterceptor
+{
+    /** A ogger for this class */
+    private static final Logger LOG = LoggerFactory.getLogger( AdministrativeInterceptor.class );
+
+    /**
+     * Speedup for logs
+     */
+    private static final boolean IS_DEBUG = LOG.isDebugEnabled();
+
+    /** A reference to the DirectoryService instance */
+    private DirectoryService directoryService;
+
+    /** A reference to the SchemaManager instance */
+    private SchemaManager schemaManager;
+
+    /** A reference to the nexus for direct backend operations */
+    private PartitionNexus nexus;
+
+    /** A reference to the AdministrativeRole AT */
+    private static AttributeType ADMINISTRATIVE_ROLE_AT;
+
+    /** The possible roles */
+    private static final Set<String> ROLES = new HashSet<String>();
+
+    static
+    {
+        ROLES.add( SchemaConstants.AUTONOMOUS_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.AUTONOMOUS_AREA_OID );
+        ROLES.add( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA_OID );
+        ROLES.add( SchemaConstants.ACCESS_CONTROL_INNER_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.ACCESS_CONTROL_INNER_AREA_OID );
+        ROLES.add( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA_OID );
+        ROLES.add( SchemaConstants.COLLECTIVE_ATTRIBUTE_INNER_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.COLLECTIVE_ATTRIBUTE_INNER_AREA_OID );
+        ROLES.add( SchemaConstants.SUB_SCHEMA_ADMIN_SPECIFIC_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.SUB_SCHEMA_ADMIN_SPECIFIC_AREA_OID );
+        ROLES.add( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA_OID );
+        ROLES.add( SchemaConstants.TRIGGER_EXECUTION_INNER_AREA.toLowerCase() );
+        ROLES.add( SchemaConstants.TRIGGER_EXECUTION_INNER_AREA_OID );
+    }
+
+    /**
+     * Creates an Administrative service interceptor.
+     */
+    public AdministrativeInterceptor()
+    {
+    }
+
+    //-------------------------------------------------------------------------------------------
+    // Helper methods
+    //-------------------------------------------------------------------------------------------
+    private List<Entry> getAdministrativePoints( String adminRoleType ) throws LdapException
+    {
+        List<Entry> entries = new ArrayList<Entry>();
+
+        DN adminDn = new DN( ServerDNConstants.ADMIN_SYSTEM_DN, schemaManager );
+
+        CoreSession adminSession = new DefaultCoreSession(
+            new LdapPrincipal( adminDn, AuthenticationLevel.STRONG ), directoryService );
+
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        controls.setReturningAttributes(
+            new String[]
+                {
+                    SchemaConstants.ADMINISTRATIVE_ROLE_AT,
+                    SchemaConstants.ENTRY_UUID_AT
+                } );
+
+        ExprNode filter = new EqualityNode<String>( ADMINISTRATIVE_ROLE_AT, new StringValue(
+            adminRoleType ) );
+
+        SearchOperationContext searchOperationContext = new SearchOperationContext( adminSession, DN.EMPTY_DN, filter,
+            controls );
+        searchOperationContext.setAliasDerefMode( AliasDerefMode.NEVER_DEREF_ALIASES );
+
+        EntryFilteringCursor results = nexus.search( searchOperationContext );
+
+        try
+        {
+            while ( results.next() )
+            {
+                Entry entry = results.get();
+
+                entries.add( entry );
+            }
+        }
+        catch ( Exception e )
+        {
+            throw new LdapOperationException( e.getMessage() );
+        }
+
+        return entries;
+    }
+
+
+    /**
+     * Tells if a given role is a valid administrative role. We check the lower cased
+     * and trimmed value, and also the OID value.
+     */
+    private boolean isValidRole( String role )
+    {
+        return ROLES.contains( StringTools.toLowerCase( StringTools.trim( role ) ) );
+    }
+
+
+    //-------------------------------------------------------------------------------------------
+    // Interceptor initialization
+    //-------------------------------------------------------------------------------------------
+    /**
+     * Registers and initializes all {@link Authenticator}s to this service.
+     */
+    public void init( DirectoryService directoryService ) throws LdapException
+    {
+        LOG.debug( "Initializing the AdministrativeInterceptor" );
+
+        this.directoryService = directoryService;
+
+        schemaManager = directoryService.getSchemaManager();
+        nexus = directoryService.getPartitionNexus();
+
+        ADMINISTRATIVE_ROLE_AT = schemaManager.getAttributeType( SchemaConstants.ADMINISTRATIVE_ROLE_AT );
+
+        // Load all the AdministratvePoint :
+        // Autonomous Administrative Point first, then Specific
+        // administrative point, finally the Inner administrative Point
+        DN adminDn = new DN( ServerDNConstants.ADMIN_SYSTEM_DN, schemaManager );
+
+        CoreSession adminSession = new DefaultCoreSession(
+            new LdapPrincipal( adminDn, AuthenticationLevel.STRONG ), directoryService );
+
+        SearchControls controls = new SearchControls();
+        controls.setSearchScope( SearchControls.SUBTREE_SCOPE );
+        controls.setReturningAttributes( new String[] { SchemaConstants.ADMINISTRATIVE_ROLE_AT } );
+
+        // get the list of all the AAPs
+        List<Entry> autonomousSAPs = getAdministrativePoints( SchemaConstants.AUTONOMOUS_AREA );
+
+        // get the list of all the specific APs
+        List<Entry> accessControlSAPs = getAdministrativePoints( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA );
+        List<Entry> collectiveAttributeSAPs = getAdministrativePoints( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA );
+        List<Entry> subSchemaSAPs = getAdministrativePoints( SchemaConstants.SUB_SCHEMA_ADMIN_SPECIFIC_AREA );
+        List<Entry> triggerExecutionSAPs = getAdministrativePoints( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA );
+
+        // get the list of all the inner APs
+        List<Entry> accessControlIAPs = getAdministrativePoints( SchemaConstants.ACCESS_CONTROL_INNER_AREA );
+        List<Entry> collectiveAttributeIAPs = getAdministrativePoints( SchemaConstants.COLLECTIVE_ATTRIBUTE_INNER_AREA );
+        List<Entry> triggerExecutionIAPs = getAdministrativePoints( SchemaConstants.TRIGGER_EXECUTION_INNER_AREA );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void destroy()
+    {
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void add( NextInterceptor next, AddOperationContext addContext ) throws LdapException
+    {
+        Entry entry = addContext.getEntry();
+
+        // Check if we are adding an Administrative Point
+        EntryAttribute adminPoint = entry.get( ADMINISTRATIVE_ROLE_AT );
+
+        if ( adminPoint == null )
+        {
+            // Nope, go on.
+            next.add( addContext );
+
+            LOG.debug( "Exit from Administrative Interceptor" );
+
+            return;
+        }
+
+        LOG.debug( "Addition of an administrative point at {} for the role {}", entry.getDn(), adminPoint );
+
+        // Now we are trying to add an Administrative point. We have to check that the added
+        // AP is correct if it's a AAP : it has to have all the required SAP
+        // Note :
+        if ( adminPoint.contains( SchemaConstants.AUTONOMOUS_AREA ) )
+        {
+            if ( ( adminPoint.contains( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA ) ||
+                   adminPoint.contains( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA_OID ) ) &&
+                 ( adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA ) ||
+                   adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA_OID ) ) &&
+                 ( adminPoint.contains( SchemaConstants.SUB_SCHEMA_ADMIN_SPECIFIC_AREA ) ||
+                   adminPoint.contains( SchemaConstants.SUB_SCHEMA_ADMIN_SPECIFIC_AREA_OID ) ) &&
+                 ( adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA ) ||
+                   adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA_OID ) ) )
+            {
+                // Ok, we have all the four needed specific area, we can add the AAP
+                LOG.debug( "Adding an Autonomous Administrative Point at {}", entry.getDn() );
+
+                next.add( addContext );
+
+                LOG.debug( "Added an Autonomous Administrative Point at {}", entry.getDn() );
+
+                return;
+            }
+            else
+            {
+                String message = "Cannot add an Autonomous Administratve Point when some of the" +
+                    " specific areas are missing : " + adminPoint;
+                LOG.error( message );
+                throw new LdapUnwillingToPerformException( message );
+            }
+        }
+
+        // check that we can't mix Inner and Specific areas
+        if ( ( ( adminPoint.contains( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA ) ||
+                 adminPoint.contains( SchemaConstants.ACCESS_CONTROL_SPECIFIC_AREA_OID ) ) &&
+               ( adminPoint.contains( SchemaConstants.ACCESS_CONTROL_INNER_AREA ) ||
+                 adminPoint.contains( SchemaConstants.ACCESS_CONTROL_INNER_AREA_OID ) ) ) ||
+             ( ( adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA ) ||
+                 adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_SPECIFIC_AREA_OID ) ) &&
+               ( adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_INNER_AREA ) ||
+                 adminPoint.contains( SchemaConstants.COLLECTIVE_ATTRIBUTE_INNER_AREA_OID ) ) ) ||
+             ( ( adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA ) ||
+                 adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_SPECIFIC_AREA_OID ) ) &&
+               ( adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_INNER_AREA ) ||
+                 adminPoint.contains( SchemaConstants.TRIGGER_EXECUTION_INNER_AREA_OID ) ) ) )
+        {
+            // This is inconsistant
+            String message = "Cannot add a specific Administratve Point and the same" +
+                " inner Administrative point at the same time : " + adminPoint;
+            LOG.error( message );
+            throw new LdapUnwillingToPerformException( message );
+        }
+
+        // Ok, we are golden.
+        next.add( addContext );
+
+        LOG.debug( "Added an Autonomous Administrative Point at {}", entry.getDn() );
+
+        return;
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void delete( NextInterceptor next, DeleteOperationContext deleteContext ) throws LdapException
+    {
+        next.delete( deleteContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void modify( NextInterceptor next, ModifyOperationContext modifyContext ) throws LdapException
+    {
+        // We have to check that the modification is acceptable
+        List<Modification> modifications = modifyContext.getModItems();
+
+        EntryAttribute modifiedAdminRole = (modifyContext.getEntry()).getOriginalEntry().get( ADMINISTRATIVE_ROLE_AT );
+
+        for ( Modification modification : modifications )
+        {
+            EntryAttribute attribute = modification.getAttribute();
+
+            if ( attribute.getAttributeType() != ADMINISTRATIVE_ROLE_AT )
+            {
+                continue;
+            }
+
+            // Ok, we have a modification impacting the administrative role
+            // Apply it to a virtual AdministrativeRole attribute
+            switch ( modification.getOperation() )
+            {
+                case ADD_ATTRIBUTE :
+                    if ( modifiedAdminRole == null )
+                    {
+                        // Create the attribute
+                        modifiedAdminRole = new DefaultEntryAttribute( ADMINISTRATIVE_ROLE_AT, attribute.get() );
+                        break;
+                    }
+
+                    for ( Value<?> value : attribute )
+                    {
+                        if ( !isValidRole( value.getString() ) )
+                        {
+                            // Not a valid role : we will throw an exception
+                            String msg = "Invalid role : " + value.getString();
+                            LOG.error( msg );
+                            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
+                        }
+
+                        // At this point, we know that the attribute's syntax is correct
+                        // We just have to check that the current attribute does not
+                        // contains the value already
+                        if ( modifiedAdminRole.contains( value ) )
+                        {
+                            // This is an error.
+                            String msg = I18n.err( I18n.ERR_54, value );
+                            LOG.error( msg );
+                            throw new LdapAttributeInUseException( msg );
+                        }
+
+                        // Add the role to the modified attribute
+                        modifiedAdminRole.add( value );
+                    }
+
+                    break;
+
+                case REMOVE_ATTRIBUTE :
+                    if ( modifiedAdminRole == null )
+                    {
+                        // We can't remove a value when the attribute does not exist.
+                        String msg = "Cannot remove the administrative role, it does not exist";
+                        LOG.error( msg );
+                        throw new LdapNoSuchAttributeException( msg );
+                    }
+
+                    // It may be a complete removal
+                    if ( attribute.size() == 0 )
+                    {
+                        // Complete removal
+                        modifiedAdminRole = null;
+                        break;
+                    }
+
+                    // Now deal with the values to remove
+                    for ( Value<?> value : attribute )
+                    {
+                        if ( !isValidRole( value.getString() ) )
+                        {
+                            // Not a valid role : we will throw an exception
+                            String msg = "Invalid role : " + value.getString();
+                            LOG.error( msg );
+                            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
+                        }
+
+                        if ( !modifiedAdminRole.contains( value ) )
+                        {
+                            // We can't remove a value if it does not exist !
+                            String msg = "Cannot remove the administrative role value" + value + ", it does not exist";
+                            LOG.error( msg );
+                            throw new LdapNoSuchAttributeException( msg );
+                        }
+
+                        modifiedAdminRole.remove( value );
+                    }
+
+                    break;
+
+                case REPLACE_ATTRIBUTE :
+                    if ( modifiedAdminRole == null )
+                    {
+                        // We have to create the attribute
+                        // We can't remove a value when the attribute does not exist.
+                        String msg = "Cannot remove the administrative role, it does not exist";
+                        LOG.error( msg );
+                        throw new LdapNoSuchAttributeException( msg );
+                    }
+
+                    // It may be a complete removal
+                    if ( attribute.size() == 0 )
+                    {
+                        // Complete removal
+                        modifiedAdminRole = null;
+                        break;
+                    }
+
+                    // Now replace the existing attributes with the new ones if they are valid
+                    modifiedAdminRole.clear();
+
+                    for ( Value<?> value : attribute )
+                    {
+                        if ( !isValidRole( value.getString() ) )
+                        {
+                            // Not a valid role : we will throw an exception
+                            String msg = "Invalid role : " + value.getString();
+                            LOG.error( msg );
+                            throw new LdapInvalidAttributeValueException( ResultCodeEnum.INVALID_ATTRIBUTE_SYNTAX, msg );
+                        }
+
+                        if ( modifiedAdminRole.contains( value ) )
+                        {
+                            // We can't add a value if it already exists !
+                            String msg = "Cannot add the administrative role value" + value + ", it already exists";
+                            LOG.error( msg );
+                            throw new LdapAttributeInUseException( msg );
+                        }
+
+                        modifiedAdminRole.add( value );
+                    }
+
+                    break;
+            }
+        }
+
+        next.modify( modifyContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void move( NextInterceptor next, MoveOperationContext moveContext ) throws LdapException
+    {
+        next.move( moveContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void moveAndRename( NextInterceptor next, MoveAndRenameOperationContext moveAndRenameContext )
+        throws LdapException
+    {
+        next.moveAndRename( moveAndRenameContext );
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    public void rename( NextInterceptor next, RenameOperationContext renameContext )
+        throws LdapException
+    {
+        next.rename( renameContext );
+    }
+}

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/AuthenticationInterceptor.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core.authn;
 
@@ -51,6 +51,7 @@ import org.apache.directory.server.core.
 import org.apache.directory.server.core.DefaultCoreSession;
 import org.apache.directory.server.core.DirectoryService;
 import org.apache.directory.server.core.LdapPrincipal;
+import org.apache.directory.server.core.admin.AdministrativeInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
 import org.apache.directory.server.core.collective.CollectiveAttributeInterceptor;
@@ -128,10 +129,12 @@ public class AuthenticationInterceptor e
     private Set<Authenticator> authenticators;
     private final Map<AuthenticationLevel, Collection<Authenticator>> authenticatorsMapByType = new HashMap<AuthenticationLevel, Collection<Authenticator>>();
 
+    /** A reference to the DirectoryService instance */
     private DirectoryService directoryService;
 
     private PasswordPolicyConfiguration policyConfig;
 
+    /** A reference to the SchemaManager instance */
     private SchemaManager schemaManager;
 
     private CoreSession adminSession;
@@ -164,7 +167,9 @@ public class AuthenticationInterceptor e
         c.add( NormalizationInterceptor.class.getName() );
         c.add( AuthenticationInterceptor.class.getName() );
         c.add( AciAuthorizationInterceptor.class.getName() );
+        c.add( AdministrativeInterceptor.class.getName() );
         c.add( DefaultAuthorizationInterceptor.class.getName() );
+        c.add( AdministrativeInterceptor.class.getName() );
         c.add( ExceptionInterceptor.class.getName() );
         c.add( OperationalAttributeInterceptor.class.getName() );
         c.add( SchemaInterceptor.class.getName() );
@@ -341,7 +346,7 @@ public class AuthenticationInterceptor e
                     addContext.addResponseControl( responseControl );
                 }
 
-                // throw exception if userPassword quality checks fail 
+                // throw exception if userPassword quality checks fail
                 throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION, e.getMessage() );
             }
 
@@ -564,7 +569,7 @@ public class AuthenticationInterceptor e
                         modifyContext.addResponseControl( responseControl );
                     }
 
-                    // throw exception if userPassword quality checks fail 
+                    // throw exception if userPassword quality checks fail
                     throw new LdapOperationException( ResultCodeEnum.CONSTRAINT_VIOLATION, e.getMessage() );
                 }
             }
@@ -1216,7 +1221,7 @@ public class AuthenticationInterceptor e
 
     /**
      * The password does not contain three letter (or more) tokens from the user's account name.
-     * 
+     *
      * If the account name is less than three characters long, this check is not performed
      * because the rate at which passwords would be rejected is too high. For each token that is
      * three or more characters long, that token is searched for in the password; if it is present,
@@ -1282,7 +1287,7 @@ public class AuthenticationInterceptor e
 
     /**
      * checks if the password is too young
-     * 
+     *
      * @param userEntry the user's entry
      * @return true if the password is young, false otherwise
      * @throws LdapException

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authn/SimpleAuthenticator.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core.authn;
 
@@ -23,7 +23,6 @@ package org.apache.directory.server.core
 import java.io.UnsupportedEncodingException;
 import java.security.MessageDigest;
 import java.security.NoSuchAlgorithmException;
-import java.security.SecureRandom;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
@@ -35,6 +34,7 @@ import javax.naming.Context;
 import org.apache.commons.collections.map.LRUMap;
 import org.apache.commons.lang.ArrayUtils;
 import org.apache.directory.server.core.LdapPrincipal;
+import org.apache.directory.server.core.admin.AdministrativeInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
 import org.apache.directory.server.core.collective.CollectiveAttributeInterceptor;
@@ -68,9 +68,9 @@ import org.apache.directory.shared.ldap.
  * contained within the <code>userPassword</code> attribute in DIT. If the
  * password is stored with a one-way encryption applied (e.g. SHA), the password
  * is hashed the same way before comparison.
- * 
+ *
  * We use a cache to speedup authentication, where the DN/password are stored.
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class SimpleAuthenticator extends AbstractAuthenticator
@@ -86,19 +86,19 @@ public class SimpleAuthenticator extends
 
     /**
      * A cache to store passwords. It's a speedup, we will be able to avoid backend lookups.
-     * 
-     * Note that the backend also use a cache mechanism, but for performance gain, it's good 
+     *
+     * Note that the backend also use a cache mechanism, but for performance gain, it's good
      * to manage a cache here. The main problem is that when a user modify his password, we will
      * have to update it at three different places :
      * - in the backend,
      * - in the partition cache,
      * - in this cache.
-     * 
+     *
      * The update of the backend and partition cache is already correctly handled, so we will
      * just have to offer an access to refresh the local cache.
-     * 
+     *
      * We need to be sure that frequently used passwords be always in cache, and not discarded.
-     * We will use a LRU cache for this purpose. 
+     * We will use a LRU cache for this purpose.
      */
     private final LRUMap credentialCache;
 
@@ -118,6 +118,7 @@ public class SimpleAuthenticator extends
         c.add( AuthenticationInterceptor.class.getName() );
         c.add( AciAuthorizationInterceptor.class.getName() );
         c.add( DefaultAuthorizationInterceptor.class.getName() );
+        c.add( AdministrativeInterceptor.class.getName() );
         c.add( ExceptionInterceptor.class.getName() );
         c.add( OperationalAttributeInterceptor.class.getName() );
         c.add( SchemaInterceptor.class.getName() );
@@ -154,19 +155,19 @@ public class SimpleAuthenticator extends
     /**
      * A private class to store all informations about the existing
      * password found in the cache or get from the backend.
-     * 
+     *
      * This is necessary as we have to compute :
      * - the used algorithm
      * - the salt if any
      * - the password itself.
-     * 
-     * If we have a on-way encrypted password, it is stored using this 
+     *
+     * If we have a on-way encrypted password, it is stored using this
      * format :
      * {<algorithm>}<encrypted password>
      * where the encrypted password format can be :
      * - MD5/SHA : base64([<salt (4 or 8 bytes)>]<password>)
-     * - crypt : <salt (2 btytes)><password> 
-     * 
+     * - crypt : <salt (2 btytes)><password>
+     *
      * Algorithm are currently MD5, SMD5, SHA, SSHA, CRYPT and empty
      */
     private class EncryptionMethod
@@ -360,10 +361,10 @@ public class SimpleAuthenticator extends
     /**
      * Decompose the stored password in an algorithm, an eventual salt
      * and the password itself.
-     * 
+     *
      * If the algorithm is SHA, SSHA, MD5 or SMD5, the part following the algorithm
      * is base64 encoded
-     * 
+     *
      * @param encryptionMethod The structure to feed
      * @return The password
      * @param credentials the credentials to split
@@ -387,14 +388,14 @@ public class SimpleAuthenticator extends
                 }
                 catch ( UnsupportedEncodingException uee )
                 {
-                    // do nothing 
+                    // do nothing
                     return credentials;
                 }
 
             case HASH_METHOD_SMD5:
                 try
                 {
-                    // The password is associated with a salt. Decompose it 
+                    // The password is associated with a salt. Decompose it
                     // in two parts, after having decoded the password.
                     // The salt will be stored into the EncryptionMethod structure
                     // The salt is at the end of the credentials, and is 8 bytes long
@@ -410,14 +411,14 @@ public class SimpleAuthenticator extends
                 }
                 catch ( UnsupportedEncodingException uee )
                 {
-                    // do nothing 
+                    // do nothing
                     return credentials;
                 }
 
             case HASH_METHOD_SSHA:
                 try
                 {
-                    // The password is associated with a salt. Decompose it 
+                    // The password is associated with a salt. Decompose it
                     // in two parts, after having decoded the password.
                     // The salt will be stored into the EncryptionMethod structure
                     // The salt is at the end of the credentials, and is 8 bytes long
@@ -433,12 +434,12 @@ public class SimpleAuthenticator extends
                 }
                 catch ( UnsupportedEncodingException uee )
                 {
-                    // do nothing 
+                    // do nothing
                     return credentials;
                 }
 
             case HASH_METHOD_CRYPT:
-                // The password is associated with a salt. Decompose it 
+                // The password is associated with a salt. Decompose it
                 // in two parts, storing the salt into the EncryptionMethod structure.
                 // The salt comes first, not like for SSHA and SMD5, and is 2 bytes long
                 encryptionMethod.salt = new byte[2];
@@ -469,7 +470,7 @@ public class SimpleAuthenticator extends
         try
         {
             /*
-             * NOTE: at this point the BindOperationContext does not has a 
+             * NOTE: at this point the BindOperationContext does not has a
              * null session since the user has not yet authenticated so we
              * cannot use lookup() yet.  This is a very special
              * case where we cannot rely on the bindContext to perform a new
@@ -479,7 +480,7 @@ public class SimpleAuthenticator extends
                 bindContext.getDn() );
             lookupContext.setByPassed( USERLOOKUP_BYPASS );
             lookupContext.setAttrsId( new String[]{ "+" } );
-            
+
             userEntry = getDirectoryService().getOperationManager().lookup( lookupContext );
 
             if ( userEntry == null )
@@ -505,7 +506,7 @@ public class SimpleAuthenticator extends
         EntryAttribute userPasswordAttr = userEntry.get( SchemaConstants.USER_PASSWORD_AT );
 
         bindContext.setEntry( new ClonedServerEntry( userEntry ) );
-        
+
         // ---- assert that credentials match
         if ( userPasswordAttr == null )
         {
@@ -525,7 +526,7 @@ public class SimpleAuthenticator extends
      * The method returns null, if the argument is not in this form. It returns
      * XYZ, if XYZ is an algorithm known to the MessageDigest class of
      * java.security.
-     * 
+     *
      * @param password a byte[]
      * @return included message digest alorithm, if any
      * @throws IllegalArgumentException if the algorithm cannot be identified
@@ -568,16 +569,16 @@ public class SimpleAuthenticator extends
      * encoded. The method returns a String which looks like "{XYZ}bbbbbbb",
      * whereas XYZ is the name of the algorithm, and bbbbbbb is the Base64
      * encoded value of XYZ applied to the password.
-     * 
+     *
      * @param algorithm
      *            an algorithm which is supported by
      *            java.security.MessageDigest, e.g. SHA
      * @param password
      *            password value, a byte[]
-     * 
+     *
      * @return a digested password, which looks like
      *         {SHA}LhkDrSoM6qr0fW6hzlfOJQW61tc=
-     * 
+     *
      * @throws IllegalArgumentException
      *             if password is neither a String nor a byte[], or algorithm is
      *             not known to java.security.MessageDigest class

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/ACDFEngine.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/ACDFEngine.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/ACDFEngine.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/ACDFEngine.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core.authz.support;
 
@@ -25,6 +25,7 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.HashSet;
 
+import org.apache.directory.server.core.admin.AdministrativeInterceptor;
 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
@@ -65,7 +66,7 @@ import org.apache.directory.shared.ldap.
  * <p>
  * Operation is determined to be permitted if and only if there is at least one
  * tuple left and all of them grants the access. (18.8.4. X.501)
- * 
+ *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
 public class ACDFEngine
@@ -75,10 +76,10 @@ public class ACDFEngine
 
     /**
      * Creates a new instance.
-     * 
+     *
      * @param oidRegistry an OID registry to be used by internal components
-     * @param attrTypeRegistry an attribute type registry to be used by internal components 
-     * 
+     * @param attrTypeRegistry an attribute type registry to be used by internal components
+     *
      * @throws LdapException if failed to initialize internal components
      */
     public ACDFEngine( SchemaManager schemaManager )
@@ -104,7 +105,7 @@ public class ACDFEngine
      * Checks the user with the specified name can access the specified resource
      * (entry, attribute type, or attribute value) and throws {@link LdapNoPermissionException}
      * if the user doesn't have any permission to perform the specified grants.
-     * 
+     *
      * @param proxy the proxy to the partition nexus
      * @param userGroupNames the collection of the group DNs the user who is trying to access the resource belongs
      * @param username the DN of the user who is trying to access the resource
@@ -135,6 +136,7 @@ public class ACDFEngine
 //        c.add( ReferralInterceptor.class.getName() );
         c.add( AciAuthorizationInterceptor.class.getName() );
         c.add( DefaultAuthorizationInterceptor.class.getName() );
+        c.add( AdministrativeInterceptor.class.getName() );
 //        c.add( ExceptionInterceptor.class.getName() );
         c.add( OperationalAttributeInterceptor.class.getName() );
         c.add( SchemaInterceptor.class.getName() );
@@ -150,7 +152,7 @@ public class ACDFEngine
      * Returns <tt>true</tt> if the user with the specified name can access the specified resource
      * (entry, attribute type, or attribute value) and throws {@link LdapNoPermissionException}
      * if the user doesn't have any permission to perform the specified grants.
-     * 
+     *
      * @param proxy the proxy to the partition nexus
      * @param userGroupNames the collection of the group DNs the user who is trying to access the resource belongs
      * @param userName the DN of the user who is trying to access the resource
@@ -174,7 +176,7 @@ public class ACDFEngine
 
         // Determine the scope of the requested operation.
         OperationScope scope;
-        
+
         if ( aciContext.getAttributeType() == null )
         {
             scope = OperationScope.ENTRY;
@@ -190,7 +192,7 @@ public class ACDFEngine
 
         // Clone aciTuples in case it is unmodifiable.
         aciContext.setAciTuples( new ArrayList<ACITuple>( aciContext.getAciTuples() ) );
-        
+
         // Filter unrelated and invalid tuples
         for ( ACITupleFilter filter : filters )
         {
@@ -199,7 +201,7 @@ public class ACDFEngine
                 // No need to continue filtering
                 return false;
             }
-            
+
             aciContext.setAciTuples( filter.filter( aciContext, scope, userEntry ) );
         }
 

Modified: directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/MaxImmSubFilter.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/MaxImmSubFilter.java?rev=980257&r1=980256&r2=980257&view=diff
==============================================================================
--- directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/MaxImmSubFilter.java (original)
+++ directory/apacheds/trunk/core/src/main/java/org/apache/directory/server/core/authz/support/MaxImmSubFilter.java Wed Jul 28 22:38:17 2010
@@ -6,16 +6,16 @@
  *  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. 
- *  
+ *  under the License.
+ *
  */
 package org.apache.directory.server.core.authz.support;
 
@@ -27,6 +27,7 @@ import java.util.Iterator;
 
 import javax.naming.directory.SearchControls;
 
+import org.apache.directory.server.core.admin.AdministrativeInterceptor;
 import org.apache.directory.server.core.authn.AuthenticationInterceptor;
 import org.apache.directory.server.core.authz.AciAuthorizationInterceptor;
 import org.apache.directory.server.core.authz.DefaultAuthorizationInterceptor;
@@ -70,7 +71,7 @@ public class MaxImmSubFilter implements 
     public MaxImmSubFilter( SchemaManager schemaManager )
     {
         AttributeType objectClassAt = null;
-        
+
         try
         {
             objectClassAt = schemaManager.lookupAttributeTypeRegistry( SchemaConstants.OBJECT_CLASS_AT );
@@ -79,7 +80,7 @@ public class MaxImmSubFilter implements 
         {
             // Do nothing
         }
-        
+
         childrenFilter = new PresenceNode( objectClassAt );
         childrenSearchControls = new SearchControls();
         childrenSearchControls.setSearchScope( SearchControls.ONELEVEL_SCOPE );
@@ -111,7 +112,7 @@ public class MaxImmSubFilter implements 
         for ( Iterator<ACITuple> i = aciContext.getAciTuples().iterator(); i.hasNext(); )
         {
             ACITuple tuple = i.next();
-            
+
             if ( !tuple.isGrant() )
             {
                 continue;
@@ -127,7 +128,7 @@ public class MaxImmSubFilter implements 
                     }
 
                     MaxImmSubItem mis = ( MaxImmSubItem ) item;
-                    
+
                     if ( immSubCount >= mis.getValue() )
                     {
                         i.remove();
@@ -148,6 +149,7 @@ public class MaxImmSubFilter implements 
         c.add( AuthenticationInterceptor.class.getName() );
         c.add( AciAuthorizationInterceptor.class.getName() );
         c.add( DefaultAuthorizationInterceptor.class.getName() );
+        c.add( AdministrativeInterceptor.class.getName() );
         c.add( OperationalAttributeInterceptor.class.getName() );
         c.add( SchemaInterceptor.class.getName() );
         c.add( SubentryInterceptor.class.getName() );
@@ -160,14 +162,14 @@ public class MaxImmSubFilter implements 
     {
         int cnt = 0;
         EntryFilteringCursor results = null;
-        
+
         try
         {
-            SearchOperationContext searchContext = new SearchOperationContext( opContext.getSession(), 
-                ( DN ) entryName.getPrefix( 1 ), childrenFilter, childrenSearchControls );
+            SearchOperationContext searchContext = new SearchOperationContext( opContext.getSession(),
+                entryName.getPrefix( 1 ), childrenFilter, childrenSearchControls );
             searchContext.setByPassed( SEARCH_BYPASS );
             searchContext.setAliasDerefMode( AliasDerefMode.DEREF_ALWAYS );
-            
+
             results = opContext.getSession().getDirectoryService().getOperationManager().search( searchContext );
 
             try