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" ) );