o Fix for DIRSERVER-2133
o Injected the structuralObjectclaas Op Attrs in entries
(DIRSERVER-2132)
diff --git a/core-api/src/main/java/org/apache/directory/server/core/api/AttributeTypeProvider.java b/core-api/src/main/java/org/apache/directory/server/core/api/AttributeTypeProvider.java
index bb55288..f79ae21 100644
--- a/core-api/src/main/java/org/apache/directory/server/core/api/AttributeTypeProvider.java
+++ b/core-api/src/main/java/org/apache/directory/server/core/api/AttributeTypeProvider.java
@@ -42,20 +42,21 @@
private final AttributeType entryCSN;
private final AttributeType entryDN;
private final AttributeType entryUUID;
+ private final AttributeType hasSubordinates;
private final AttributeType member;
private final AttributeType modifiersName;
private final AttributeType modifyTimestamp;
+ private final AttributeType nbChildren;
+ private final AttributeType nbSubordinates;
private final AttributeType objectClass;
private final AttributeType prescriptiveACI;
+ private final AttributeType structuralObjectClass;
private final AttributeType subentryACI;
private final AttributeType subschemaSubentry;
private final AttributeType subtreeSpecification;
private final AttributeType triggerExecutionSubentries;
private final AttributeType uniqueMember;
private final AttributeType userPassword;
- private final AttributeType nbChildren;
- private final AttributeType nbSubordinates;
- private final AttributeType hasSubordinates;
private final AttributeType[] subentryOperationalAttributes;
@@ -73,11 +74,15 @@
entryCSN = schemaManager.getAttributeType( SchemaConstants.ENTRY_CSN_AT );
entryDN = schemaManager.getAttributeType( SchemaConstants.ENTRY_DN_AT );
entryUUID = schemaManager.getAttributeType( SchemaConstants.ENTRY_UUID_AT );
+ hasSubordinates = schemaManager.getAttributeType( SchemaConstants.HAS_SUBORDINATES_AT );
member = schemaManager.getAttributeType( SchemaConstants.MEMBER_AT );
modifiersName = schemaManager.getAttributeType( SchemaConstants.MODIFIERS_NAME_AT );
modifyTimestamp = schemaManager.getAttributeType( SchemaConstants.MODIFY_TIMESTAMP_AT );
+ nbChildren = schemaManager.getAttributeType( ApacheSchemaConstants.NB_CHILDREN_OID );
+ nbSubordinates = schemaManager.getAttributeType( ApacheSchemaConstants.NB_SUBORDINATES_OID );
objectClass = schemaManager.getAttributeType( SchemaConstants.OBJECT_CLASS_AT );
prescriptiveACI = schemaManager.getAttributeType( SchemaConstants.PRESCRIPTIVE_ACI_AT );
+ structuralObjectClass = schemaManager.getAttributeType( SchemaConstants.STRUCTURAL_OBJECT_CLASS_AT );
subentryACI = schemaManager.getAttributeType( SchemaConstants.SUBENTRY_ACI_AT_OID );
subschemaSubentry = schemaManager.getAttributeType( SchemaConstants.SUBSCHEMA_SUBENTRY_AT );
subtreeSpecification = schemaManager.getAttributeType( SchemaConstants.SUBTREE_SPECIFICATION_AT );
@@ -85,9 +90,6 @@
.getAttributeType( ApacheSchemaConstants.TRIGGER_EXECUTION_SUBENTRIES_AT );
uniqueMember = schemaManager.getAttributeType( SchemaConstants.UNIQUE_MEMBER_AT_OID );
userPassword = schemaManager.getAttributeType( SchemaConstants.USER_PASSWORD_AT_OID );
- nbChildren = schemaManager.getAttributeType( ApacheSchemaConstants.NB_CHILDREN_OID );
- nbSubordinates = schemaManager.getAttributeType( ApacheSchemaConstants.NB_SUBORDINATES_OID );
- hasSubordinates = schemaManager.getAttributeType( SchemaConstants.HAS_SUBORDINATES_AT );
subentryOperationalAttributes = new AttributeType[]
{
@@ -189,6 +191,15 @@
}
+ /**
+ * @return the <code>hasSubordinates</code> {@link AttributeType}.
+ */
+ public AttributeType getHasSubordinates()
+ {
+ return hasSubordinates;
+ }
+
+
/**
* @return the <code>member</code> {@link AttributeType}.
*/
@@ -216,6 +227,24 @@
}
+ /**
+ * @return the <code>nbChildren</code> {@link AttributeType}.
+ */
+ public AttributeType getNbChildren()
+ {
+ return nbChildren;
+ }
+
+
+ /**
+ * @return the <code>nbSubordinates</code> {@link AttributeType}.
+ */
+ public AttributeType getNbSubordinates()
+ {
+ return nbSubordinates;
+ }
+
+
/**
* @return the <code>objectClass</code> {@link AttributeType}.
*/
@@ -235,6 +264,15 @@
/**
+ * @return the <code>structuralObjectClass</code> {@link AttributeType}.
+ */
+ public AttributeType getStructuralObjectClass()
+ {
+ return structuralObjectClass;
+ }
+
+
+ /**
* @return the <code>subentryACI</code> {@link AttributeType}.
*/
public AttributeType getSubentryACI()
@@ -279,33 +317,6 @@
}
- /**
- * @return the operational attributes of n nbChildren
- */
- public AttributeType getNbChildren()
- {
- return nbChildren;
- }
-
-
- /**
- * @return the operational attributes of a nbSubordinates
- */
- public AttributeType getNbSubordinates()
- {
- return nbSubordinates;
- }
-
-
- /**
- * @return the operational attributes of a hasSubordinates
- */
- public AttributeType getHasSubordinates()
- {
- return hasSubordinates;
- }
-
-
/**
* @return the <code>userPassword</code> {@link AttributeType}.
*/
diff --git a/core-integ/src/test/java/org/apache/directory/server/core/operations/lookup/LookupIT.java b/core-integ/src/test/java/org/apache/directory/server/core/operations/lookup/LookupIT.java
index 00814af..50f0daf 100644
--- a/core-integ/src/test/java/org/apache/directory/server/core/operations/lookup/LookupIT.java
+++ b/core-integ/src/test/java/org/apache/directory/server/core/operations/lookup/LookupIT.java
@@ -52,8 +52,10 @@
// Entry # 1
"dn: cn=test,ou=system",
"objectClass: person",
+ "objectClass: inetorgPerson",
"cn: test",
- "sn: sn_test" })
+ "sn: sn_test",
+ })
public class LookupIT extends AbstractLdapTestUnit
{
/** The ldap connection */
@@ -104,8 +106,8 @@
Entry entry = connection.lookup( "cn=test,ou=system", "+" );
assertNotNull( entry );
- // We should have 6 attributes
- assertEquals( 8, entry.size() );
+ // We should have 9 attributes
+ assertEquals( 10, entry.size() );
// Check that all the user attributes are absent
assertNull( entry.get( "cn" ) );
@@ -129,6 +131,8 @@
assertNotNull( entry.get( "entryDn" ));
assertNotNull( entry.get( "nbChildren" ));
assertNotNull( entry.get( "nbSubordinates" ));
+ assertNotNull( entry.get( "hasSubordinates" ));
+ assertNotNull( entry.get( "structuralObjectClass" ));
assertEquals( "cn=test,ou=system", entry.get( "entryDn" ).getString() );
}
@@ -264,20 +268,21 @@
assertNotNull( entry );
- // We should have 11 attributes
- assertEquals( 11, entry.size() );
- assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates" ) );
+ // We should have 13 attributes
+ assertEquals( 13, entry.size() );
+ assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates", "hasSubordinates", "structuralObjectClass" ) );
assertEquals( 0L, Long.parseLong( entry.get( "nbChildren" ).getString() ) );
assertEquals( 0L, Long.parseLong( entry.get( "nbSubordinates" ).getString() ) );
-
+ assertEquals( "FALSE", entry.get( "hasSubordinates" ).getString() );
+
// Now lookup for the "ou=system"
entry = connection.lookup( "ou=system", "*", "+" );
assertNotNull( entry );
- // We should have 11 attributes
- assertEquals( 11, entry.size() );
- assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates" ) );
+ // We should have 12 attributes
+ assertEquals( 13, entry.size() );
+ assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates", "hasSubordinates", "structuralObjectClass" ) );
// we will have 6 children :
// - ou=configuration
@@ -289,6 +294,7 @@
// and 10 subordinates, as we have 3 children under ou=configuration and one under ou=groups
assertEquals( 6L, Long.parseLong( entry.get( "nbChildren" ).getString() ) );
assertEquals( 10L, Long.parseLong( entry.get( "nbSubordinates" ).getString() ) );
+ assertEquals( "TRUE", entry.get( "hasSubordinates" ).getString() );
// Check with only one of the two attributes
entry = connection.lookup( "ou=system", "nbChildren" );
@@ -322,4 +328,53 @@
// we will have 10 subordinates
assertEquals( 10L, Long.parseLong( entry.get( "nbSubordinates" ).getString() ) );
}
+
+
+ @Test
+ public void testLookupStructuralObjectClass() throws LdapException
+ {
+ Entry entry = connection.lookup( "cn=test,ou=system", "*", "+" );
+
+ assertNotNull( entry );
+
+ // We should have 12 attributes
+ assertEquals( 13, entry.size() );
+ assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates", "hasSubordinates", "structuralObjectClass" ) );
+ assertEquals( 0L, Long.parseLong( entry.get( "nbChildren" ).getString() ) );
+ assertEquals( 0L, Long.parseLong( entry.get( "nbSubordinates" ).getString() ) );
+ assertEquals( "FALSE", entry.get( "hasSubordinates" ).getString() );
+ assertEquals( "inetOrgPerson", entry.get( "structuralObjectClass" ).getString() );
+
+ // Now lookup for the "ou=system"
+ entry = connection.lookup( "ou=system", "*", "+" );
+
+ assertNotNull( entry );
+
+ // We should have 13 attributes
+ assertEquals( 13, entry.size() );
+ assertTrue( entry.containsAttribute( "nbChildren", "nbSubordinates", "hasSubordinates", "structuralObjectClass" ) );
+
+ // we will have 6 children :
+ // - ou=configuration
+ // - ou=consumer
+ // - ou = groups
+ // - ou=users
+ // - ou=prefNodeNames
+ // - uid=admin
+ // and 10 subordinates, as we have 3 children under ou=configuration and one under ou=groups
+ assertEquals( 6L, Long.parseLong( entry.get( "nbChildren" ).getString() ) );
+ assertEquals( 10L, Long.parseLong( entry.get( "nbSubordinates" ).getString() ) );
+ assertEquals( "TRUE", entry.get( "hasSubordinates" ).getString() );
+ assertEquals( "organizationalUnit", entry.get( "structuralObjectClass" ).getString() );
+
+ // Check with only one of the two attributes
+ entry = connection.lookup( "ou=system", "structuralObjectClass" );
+
+ assertNotNull( entry );
+
+ // We should have 1 attributes
+ assertEquals( 1, entry.size() );
+ assertTrue( entry.containsAttribute( "structuralObjectClass" ) );
+ assertEquals( "organizationalUnit", entry.get( "structuralObjectClass" ).getString() );
+ }
}
diff --git a/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchIT.java b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchIT.java
index 9599fe7..01c8cb1 100644
--- a/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchIT.java
+++ b/core-integ/src/test/java/org/apache/directory/server/core/operations/search/SearchIT.java
@@ -2148,7 +2148,7 @@
@Test
- public void testSearchSubordinates() throws Exception
+ public void testSearchHasSubordinates() throws Exception
{
SearchControls controls = new SearchControls();
controls.setSearchScope( SearchControls.OBJECT_SCOPE );
diff --git a/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java b/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
index b0cca73..cbd1fd4 100644
--- a/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
+++ b/interceptors/operational/src/main/java/org/apache/directory/server/core/operational/OperationalAttributeInterceptor.java
@@ -20,7 +20,9 @@
package org.apache.directory.server.core.operational;
+import java.util.HashMap;
import java.util.Iterator;
+import java.util.Map;
import java.util.List;
import java.util.Set;
import java.util.UUID;
@@ -40,6 +42,7 @@
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.schema.AttributeTypeOptions;
+import org.apache.directory.api.ldap.model.schema.ObjectClass;
import org.apache.directory.api.ldap.model.schema.SchemaManager;
import org.apache.directory.api.util.DateUtils;
import org.apache.directory.server.constants.ApacheSchemaConstants;
@@ -676,14 +679,18 @@
AttributeTypeOptions nbSubordinatesAto = new AttributeTypeOptions( nbSubordinatesAt );
AttributeType hasSubordinatesAt = directoryService.getAtProvider().getHasSubordinates();
AttributeTypeOptions hasSubordinatesAto = new AttributeTypeOptions( hasSubordinatesAt );
+ AttributeType structuralObjectClassAt = directoryService.getAtProvider().getStructuralObjectClass();
+ AttributeTypeOptions structuralObjectClassAto = new AttributeTypeOptions( structuralObjectClassAt );
if ( returningAttributes != null )
{
boolean nbChildrenRequested = returningAttributes.contains( nbChildrenAto ) || allAttributes;
boolean nbSubordinatesRequested = returningAttributes.contains( nbSubordinatesAto ) || allAttributes;
boolean hasSubordinatesRequested = returningAttributes.contains( hasSubordinatesAto ) || allAttributes;
+ boolean structuralObjectClassRequested = returningAttributes.contains( structuralObjectClassAto ) || allAttributes;
- if ( nbChildrenRequested || nbSubordinatesRequested )
+ if ( nbChildrenRequested || nbSubordinatesRequested || hasSubordinatesRequested
+ || structuralObjectClassRequested )
{
Partition partition = directoryService.getPartitionNexus().getPartition( entry.getDn() );
Subordinates subordinates = partition.getSubordinates( operationContext.getTransaction(), entry );
@@ -691,25 +698,77 @@
long nbChildren = subordinates.getNbChildren();
long nbSubordinates = subordinates.getNbSubordinates();
+ // Inject the nbChildren OpAttr if needed
if ( nbChildrenRequested )
{
entry.add( new DefaultAttribute( nbChildrenAt,
Long.toString( nbChildren ) ) );
}
+ // Inject the nbSubordinates OpAttr if needed
if ( nbSubordinatesRequested )
{
entry.add( new DefaultAttribute( nbSubordinatesAt,
Long.toString( nbSubordinates ) ) );
}
+ // Inject the hasSubordinates OpAttr if needed
if ( hasSubordinatesRequested )
{
- entry.add( new DefaultAttribute( hasSubordinatesAt, "TRUE" ) );
+ if ( nbSubordinates > 0 )
+ {
+ entry.add( new DefaultAttribute( hasSubordinatesAt, "TRUE" ) );
+ }
+ else
+ {
+ entry.add( new DefaultAttribute( hasSubordinatesAt, "FALSE" ) );
+ }
}
- else
+
+ // Inject the structuralObjectclass OpAttr if needed
+ if ( structuralObjectClassRequested )
{
- entry.add( new DefaultAttribute( hasSubordinatesAt, "FALSE" ) );
+ Attribute objectClasses = entry.get( SchemaConstants.OBJECT_CLASS_AT );
+ Map<String, ObjectClass> superiors = new HashMap<>();
+ ObjectClass[] objectClassArray = new ObjectClass[objectClasses.size()];
+ int nbStructural = 0;
+
+ // First get all the structural objectClasses
+ for ( Value objectClassValue : objectClasses )
+ {
+ ObjectClass objectClass =
+ schemaManager.getObjectClassRegistry().get( objectClassValue.getNormalized() );
+
+ if ( objectClass.isStructural() )
+ {
+ objectClassArray[nbStructural++] = objectClass;
+
+ // We can only have one superior objectClass for Structural ObjectClass
+ superiors.put( objectClass.getSuperiors().get( 0 ).getOid(), objectClass );
+ }
+ }
+
+ // Then find the top of them
+ if ( nbStructural == 1 )
+ {
+ entry.add( new DefaultAttribute( structuralObjectClassAt,
+ objectClassArray[0].getName() ) );
+ }
+ else
+ {
+ ObjectClass topStructural = objectClassArray[0];
+
+ for ( ObjectClass oc : objectClassArray )
+ {
+ if ( !superiors.containsKey( oc.getOid() ) )
+ {
+ // We are done : the current OC is not the superior of any other
+ // OC, this is necessarily the top level one
+ entry.add( new DefaultAttribute( structuralObjectClassAt, oc.getName() ) );
+ break;
+ }
+ }
+ }
}
}
}
diff --git a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java
index 49797db..16f6ed7 100644
--- a/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java
+++ b/server-integ/src/test/java/org/apache/directory/server/operations/search/SearchIT.java
@@ -1278,7 +1278,7 @@
// ensure that all operational attributes are returned
// and no user attributes
- assertEquals( 9, attrs.size() );
+ assertEquals( 11, attrs.size() );
assertNull( attrs.get( "cn" ) );
assertNull( attrs.get( "sn" ) );
assertNull( attrs.get( "objectClass" ) );
@@ -1292,6 +1292,8 @@
assertNotNull( attrs.get( "subschemaSubentry" ) );
assertNotNull( attrs.get( "nbChildren" ) );
assertNotNull( attrs.get( "nbSubordinates" ) );
+ assertNotNull( attrs.get( "hasSubordinates" ) );
+ assertNotNull( attrs.get( "structuralObjectClass" ) );
res.close();
ctx.close();
@@ -1438,7 +1440,7 @@
Attributes attrs = result.getAttributes();
// ensure that all user attributes are returned
- assertEquals( 15, attrs.size() );
+ assertEquals( 17, attrs.size() );
assertNotNull( attrs.get( "cn" ) );
assertNotNull( attrs.get( "sn" ) );
assertNotNull( attrs.get( "objectClass" ) );
@@ -1453,6 +1455,8 @@
assertNotNull( attrs.get( "subschemaSubentry" ) );
assertNotNull( attrs.get( "nbChildren" ) );
assertNotNull( attrs.get( "nbSubordinates" ) );
+ assertNotNull( attrs.get( "hasSubordinates" ) );
+ assertNotNull( attrs.get( "structuralObjectClass" ) );
res.close();
ctx.close();
}
diff --git a/service/src/test/java/org/apache/directory/server/UberJarMainTest.java b/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
index a793853..2dd9ed9 100644
--- a/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
+++ b/service/src/test/java/org/apache/directory/server/UberJarMainTest.java
@@ -73,7 +73,6 @@
private UberjarMain uberjarMain;
private KeyStore keyStore;
- private File keyStoreFile;
@Before
public void create()