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 2020/03/26 07:10:59 UTC

[directory-server] branch master updated: Implemented the TreeDelete control

This is an automated email from the ASF dual-hosted git repository.

elecharny pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/directory-server.git


The following commit(s) were added to refs/heads/master by this push:
     new ec6dd38  Implemented the TreeDelete control
ec6dd38 is described below

commit ec6dd38f66aa3b8e83a66ece045d89af1fbabfd7
Author: emmanuel lecharny <em...@busit.com>
AuthorDate: Thu Mar 26 08:10:38 2020 +0100

    Implemented the TreeDelete control
---
 .../server/core/DefaultOperationManager.java       | 114 +++++++++++++++++++--
 .../api/operations/ClientDeleteRequestTest.java    |   2 +-
 2 files changed, 107 insertions(+), 9 deletions(-)

diff --git a/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java b/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java
index 4c347d0..0e091a0 100644
--- a/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java
+++ b/core/src/main/java/org/apache/directory/server/core/DefaultOperationManager.java
@@ -26,8 +26,10 @@ import java.util.List;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
 
+import org.apache.directory.api.ldap.extras.controls.ad.TreeDelete;
 import org.apache.directory.api.ldap.model.constants.Loggers;
 import org.apache.directory.api.ldap.model.constants.SchemaConstants;
+import org.apache.directory.api.ldap.model.cursor.CursorException;
 import org.apache.directory.api.ldap.model.entry.Attribute;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.entry.Value;
@@ -40,11 +42,14 @@ import org.apache.directory.api.ldap.model.exception.LdapPartialResultException;
 import org.apache.directory.api.ldap.model.exception.LdapReferralException;
 import org.apache.directory.api.ldap.model.exception.LdapServiceUnavailableException;
 import org.apache.directory.api.ldap.model.exception.LdapURLEncodingException;
+import org.apache.directory.api.ldap.model.filter.PresenceNode;
 import org.apache.directory.api.ldap.model.message.ResultCodeEnum;
 import org.apache.directory.api.ldap.model.message.SearchScope;
 import org.apache.directory.api.ldap.model.name.Dn;
 import org.apache.directory.api.ldap.model.name.Rdn;
+import org.apache.directory.api.ldap.model.schema.AttributeType;
 import org.apache.directory.api.ldap.model.url.LdapUrl;
+import org.apache.directory.server.constants.ApacheSchemaConstants;
 import org.apache.directory.server.core.api.CoreSession;
 import org.apache.directory.server.core.api.DirectoryService;
 import org.apache.directory.server.core.api.OperationManager;
@@ -99,6 +104,12 @@ public class DefaultOperationManager implements OperationManager
     /** A lock used to protect against concurrent operations */
     private ReadWriteLock rwLock = new ReentrantReadWriteLock( true );
 
+    /** A reference to the ObjectClass AT */
+    protected AttributeType objectClassAT;
+    
+    /** The nbChildren count attributeType */
+    protected AttributeType nbChildrenAT;
+    
     public DefaultOperationManager( DirectoryService directoryService )
     {
         this.directoryService = directoryService;
@@ -651,6 +662,61 @@ public class DefaultOperationManager implements OperationManager
 
         return result;
     }
+    
+    
+    private void deleteEntry( DeleteOperationContext deleteContext , Dn dn ) throws LdapException
+    {
+        DeleteOperationContext entryDeleteContext = 
+            new DeleteOperationContext( deleteContext.getSession(), dn );
+        entryDeleteContext.setTransaction( deleteContext.getTransaction() );
+
+        eagerlyPopulateFields( entryDeleteContext );
+        
+        // Call the Delete method
+        Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
+
+        head.delete( entryDeleteContext );
+    }
+    
+    
+    private void processTreeDelete( DeleteOperationContext deleteContext, Dn dn ) throws LdapException, CursorException
+    {
+        objectClassAT = directoryService.getSchemaManager().getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
+        nbChildrenAT = directoryService.getSchemaManager().getAttributeType( ApacheSchemaConstants.NB_CHILDREN_OID );
+
+        // This is a depth first recursive operation
+        PresenceNode filter = new PresenceNode( objectClassAT );
+        SearchOperationContext searchContext = new SearchOperationContext( 
+            deleteContext.getSession(), 
+            dn, 
+            SearchScope.ONELEVEL, filter,
+            ApacheSchemaConstants.NB_CHILDREN_OID );
+        searchContext.setTransaction( deleteContext.getTransaction() );
+
+        EntryFilteringCursor cursor = search( searchContext );
+        
+        cursor.beforeFirst();
+        
+        while ( cursor.next() )
+        {
+            Entry entry = cursor.get();
+            
+            if ( Integer.parseInt( entry.get( nbChildrenAT ).getString() ) == 0 )
+            {
+                // We can delete the entry
+                deleteEntry( deleteContext, entry.getDn() );
+            }
+            else
+            {
+                // Recurse
+                processTreeDelete( deleteContext, entry.getDn() );
+            }
+        }
+        
+        // Done with the children, we can delete the entry
+        // We can delete the entry
+        deleteEntry( deleteContext, dn );
+    }
 
 
     /**
@@ -748,16 +814,48 @@ public class DefaultOperationManager implements OperationManager
             
             deleteContext.setTransaction( transaction );
 
-            eagerlyPopulateFields( deleteContext );
-
-            // Call the Delete method
-            Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
-
-            head.delete( deleteContext );
+            // Check if the TreeDelete control is used
+            if ( deleteContext.hasRequestControl( TreeDelete.OID ) )
+            {
+                try
+                {
+                    processTreeDelete( deleteContext, deleteContext.getDn() );
 
-            if ( !deleteContext.getSession().hasSessionTransaction() )
+                    if ( !deleteContext.getSession().hasSessionTransaction() )
+                    {
+                        transaction.commit();
+                    }
+                }
+                catch ( CursorException ce )
+                {
+                    try
+                    {
+                        if ( transaction != null )
+                        {
+                            transaction.abort();
+                        }
+                        
+                        throw new LdapOtherException( ce.getMessage(), ce );
+                    }
+                    catch ( IOException ioe )
+                    {
+                        throw new LdapOtherException( ioe.getMessage(), ioe );
+                    }
+                }
+            }
+            else
             {
-                transaction.commit();
+                eagerlyPopulateFields( deleteContext );
+    
+                // Call the Delete method
+                Interceptor head = directoryService.getInterceptor( deleteContext.getNextInterceptor() );
+    
+                head.delete( deleteContext );
+    
+                if ( !deleteContext.getSession().hasSessionTransaction() )
+                {
+                    transaction.commit();
+                }
             }
         }
         catch ( LdapException le )
diff --git a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientDeleteRequestTest.java b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientDeleteRequestTest.java
index f80bd1c..50aed5e 100644
--- a/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientDeleteRequestTest.java
+++ b/ldap-client-test/src/test/java/org/apache/directory/shared/client/api/operations/ClientDeleteRequestTest.java
@@ -224,7 +224,7 @@ public class ClientDeleteRequestTest extends AbstractLdapTestUnit
 
 
     @Test
-    @org.junit.Ignore // See DIRSERVER-2305
+    //@org.junit.Ignore // See DIRSERVER-2305
     public void testDeleteWithControl() throws Exception
     {
         assertTrue( session.exists( "cn=parent,ou=system" ) );