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()