From b68d5cc1a6352dddd67adf06b18c3690c683debe Mon Sep 17 00:00:00 2001
From: Nicolas Capponi <nicolas.capponi@forgerock.com>
Date: Mon, 07 Nov 2016 15:05:30 +0000
Subject: [PATCH] OPENDJ-3417 Move responsability of backends management to BackendConfigManager

---
 opendj-server-legacy/src/main/java/org/opends/server/backends/RootDSEBackend.java |  266 ++++++++++------------------------------------------
 1 files changed, 52 insertions(+), 214 deletions(-)

diff --git a/opendj-server-legacy/src/main/java/org/opends/server/backends/RootDSEBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/backends/RootDSEBackend.java
index d66ec65..fff1f37 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/backends/RootDSEBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/backends/RootDSEBackend.java
@@ -30,6 +30,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -51,8 +52,8 @@
 import org.forgerock.opendj.ldap.schema.ObjectClass;
 import org.forgerock.opendj.server.config.server.RootDSEBackendCfg;
 import org.forgerock.util.Reject;
-import org.forgerock.util.Utils;
 import org.opends.server.api.LocalBackend;
+import org.opends.server.api.Backend;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.core.AddOperation;
 import org.opends.server.core.DeleteOperation;
@@ -126,11 +127,8 @@
   private DN rootDSEDN;
   /** The set of base DNs for this backend. */
   private Set<DN> baseDNs;
-  /**
-   * The set of subordinate base DNs and their associated backends that will be
-   * used for non-base searches.
-   */
-  private ConcurrentHashMap<DN, LocalBackend<?>> subordinateBaseDNs;
+
+  private ServerContext serverContext;
 
   /**
    * Creates a new backend with the provided information.  All backend
@@ -148,6 +146,7 @@
   public void configureBackend(RootDSEBackendCfg config, ServerContext serverContext) throws ConfigException
   {
     Reject.ifNull(config);
+    this.serverContext = serverContext;
     currentConfig = config;
     configEntryDN = config.dn();
   }
@@ -173,43 +172,6 @@
     rootDSEDN    = DN.rootDN();
     baseDNs = Collections.singleton(rootDSEDN);
 
-    // Create the set of subordinate base DNs.  If this is specified in the
-    // configuration, then use that set.  Otherwise, use the set of non-private
-    // backends defined in the server.
-    try
-    {
-      Set<DN> subDNs = currentConfig.getSubordinateBaseDN();
-      if (subDNs.isEmpty())
-      {
-        // This is fine -- we'll just use the set of user-defined suffixes.
-        subordinateBaseDNs = null;
-      }
-      else
-      {
-        subordinateBaseDNs = new ConcurrentHashMap<>();
-        for (DN baseDN : subDNs)
-        {
-          LocalBackend<?> backend = DirectoryServer.getBackend(baseDN);
-          if (backend != null)
-          {
-            subordinateBaseDNs.put(baseDN, backend);
-          }
-          else
-          {
-            logger.warn(WARN_ROOTDSE_NO_BACKEND_FOR_SUBORDINATE_BASE, baseDN);
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      logger.traceException(e);
-
-      LocalizableMessage message = WARN_ROOTDSE_SUBORDINATE_BASE_EXCEPTION.get(
-          stackTraceToSingleLineString(e));
-      throw new InitializationException(message, e);
-    }
-
     // Determine whether all root DSE attributes should be treated as user
     // attributes.
     showAllAttributes = currentConfig.isShowAllAttributes();
@@ -314,21 +276,7 @@
     {
       return -1;
     }
-
-    long count = 1;
-    for (Map.Entry<DN, LocalBackend<?>> entry : getSubordinateBaseDNs().entrySet())
-    {
-      DN subBase = entry.getKey();
-      LocalBackend<?> b = entry.getValue();
-      Entry subBaseEntry = b.getEntry(subBase);
-      if (subBaseEntry != null)
-      {
-        count++;
-        count += b.getNumberOfEntriesInBaseDN(subBase);
-      }
-    }
-
-    return count;
+    return 1;
   }
 
   @Override
@@ -339,20 +287,7 @@
     {
       return -1;
     }
-
-    long count = 0;
-
-    for (Map.Entry<DN, LocalBackend<?>> entry : getSubordinateBaseDNs().entrySet())
-    {
-      DN subBase = entry.getKey();
-      Entry subBaseEntry = entry.getValue().getEntry(subBase);
-      if (subBaseEntry != null)
-      {
-        count ++;
-      }
-    }
-
-    return count;
+    return 0;
   }
 
   @Override
@@ -363,27 +298,6 @@
     {
       return getRootDSE();
     }
-
-    // This method should never be used to get anything other than the root DSE.
-    // If we got here, then that appears to be the case, so log a message.
-    logger.warn(WARN_ROOTDSE_GET_ENTRY_NONROOT, entryDN);
-
-    // Go ahead and check the subordinate backends to see if we can find the
-    // entry there.  Note that in order to avoid potential loop conditions, this
-    // will only work if the set of subordinate bases has been explicitly
-    // specified.
-    if (subordinateBaseDNs != null)
-    {
-      for (LocalBackend<?> b : subordinateBaseDNs.values())
-      {
-        if (b.handlesEntry(entryDN))
-        {
-          return b.getEntry(entryDN);
-        }
-      }
-    }
-
-    // If we've gotten here, then we couldn't find the entry so return null.
     return null;
   }
 
@@ -410,30 +324,27 @@
     Map<AttributeType, List<Attribute>> dseUserAttrs = new HashMap<>();
     Map<AttributeType, List<Attribute>> dseOperationalAttrs = new HashMap<>();
 
-    Map<DN, LocalBackend<?>> publicNamingContexts = showSubordinatesNamingContexts ?
-        DirectoryServer.getAllPublicNamingContexts() :
-        DirectoryServer.getPublicNamingContexts();
-    Attribute publicNamingContextAttr = createAttribute(ATTR_NAMING_CONTEXTS, publicNamingContexts.keySet());
+    Set<DN> publicNamingContexts = showSubordinatesNamingContexts ?
+        getAllPublicNamingContexts() : getTopLevelPublicNamingContexts();
+    Attribute publicNamingContextAttr = createAttribute(ATTR_NAMING_CONTEXTS, publicNamingContexts);
     addAttribute(publicNamingContextAttr, dseUserAttrs, dseOperationalAttrs);
 
     // Add the "ds-private-naming-contexts" attribute.
     Attribute privateNamingContextAttr = createAttribute(
-        ATTR_PRIVATE_NAMING_CONTEXTS, DirectoryServer.getPrivateNamingContexts().keySet());
+        ATTR_PRIVATE_NAMING_CONTEXTS, serverContext.getBackendManager().getPrivateNamingContexts().keySet());
     addAttribute(privateNamingContextAttr, dseUserAttrs, dseOperationalAttrs);
 
     // Add the "supportedControl" attribute.
-    Attribute supportedControlAttr = createAttribute(ATTR_SUPPORTED_CONTROL,
-        DirectoryServer.getSupportedControls());
+    Attribute supportedControlAttr = createAttribute(ATTR_SUPPORTED_CONTROL, getAllControls());
     addAttribute(supportedControlAttr, dseUserAttrs, dseOperationalAttrs);
 
     // Add the "supportedExtension" attribute.
-    Attribute supportedExtensionAttr = createAttribute(
-        ATTR_SUPPORTED_EXTENSION, DirectoryServer.getSupportedExtensions());
+    Attribute supportedExtensionAttr = createAttribute(ATTR_SUPPORTED_EXTENSION,
+        DirectoryServer.getSupportedExtensions());
     addAttribute(supportedExtensionAttr, dseUserAttrs, dseOperationalAttrs);
 
     // Add the "supportedFeature" attribute.
-    Attribute supportedFeatureAttr = createAttribute(ATTR_SUPPORTED_FEATURE,
-        DirectoryServer.getSupportedFeatures());
+    Attribute supportedFeatureAttr = createAttribute(ATTR_SUPPORTED_FEATURE, DirectoryServer.getSupportedFeatures());
     addAttribute(supportedFeatureAttr, dseUserAttrs, dseOperationalAttrs);
 
     // Add the "supportedSASLMechanisms" attribute.
@@ -503,6 +414,35 @@
     return e;
   }
 
+  private Set<String> getAllControls()
+  {
+    // TODO: this duplicates what is done in DirectoryServer (see DirectoryServer.getSupportedControls())
+    // How should this be handled ?
+    final Set<String> controls = new HashSet<>();
+    for (Backend<?> backend : serverContext.getBackendManager().getAllBackends())
+    {
+      controls.addAll(backend.getSupportedControls());
+    }
+    return controls;
+  }
+
+  private Set<DN> getAllPublicNamingContexts()
+  {
+    Set<DN> namingContexts = new HashSet<>();
+    for (Backend<?> backend : serverContext.getBackendManager().getAllBackends())
+    {
+      namingContexts.addAll(backend.getBaseDNs());
+    }
+    return namingContexts;
+  }
+
+  private Set<DN> getTopLevelPublicNamingContexts()
+  {
+    // TODO: this implementation is insufficient because it handles only the local backends
+    // The non-local backends must be added for completeness
+    return new HashSet<DN>(serverContext.getBackendManager().getPublicNamingContexts().keySet());
+  }
+
   private void addAll(Collection<Attribute> attributes,
       Map<AttributeType, List<Attribute>> userAttrs, Map<AttributeType, List<Attribute>> operationalAttrs)
   {
@@ -567,22 +507,6 @@
     {
       return true;
     }
-
-    // If it was not the null DN, then iterate through the associated
-    // subordinate backends to make the determination.
-    for (Map.Entry<DN, LocalBackend<?>> entry : getSubordinateBaseDNs().entrySet())
-    {
-      DN baseDN = entry.getKey();
-      if (entryDN.isSubordinateOrEqualTo(baseDN))
-      {
-        LocalBackend<?> b = entry.getValue();
-        if (b.entryExists(entryDN))
-        {
-          return true;
-        }
-      }
-    }
-
     return false;
   }
 
@@ -639,72 +563,13 @@
         break;
 
       case SINGLE_LEVEL:
-        for (Map.Entry<DN, LocalBackend<?>> entry : getSubordinateBaseDNs().entrySet())
-        {
-          searchOperation.checkIfCanceled(false);
-
-          DN subBase = entry.getKey();
-          LocalBackend<?> b = entry.getValue();
-          Entry subBaseEntry = b.getEntry(subBase);
-          if (subBaseEntry != null && filter.matchesEntry(subBaseEntry))
-          {
-            searchOperation.returnEntry(subBaseEntry, null);
-          }
-        }
-        break;
-
       case WHOLE_SUBTREE:
       case SUBORDINATES:
-        try
-        {
-          for (Map.Entry<DN, LocalBackend<?>> entry : getSubordinateBaseDNs().entrySet())
-          {
-            searchOperation.checkIfCanceled(false);
-
-            DN subBase = entry.getKey();
-            LocalBackend<?> b = entry.getValue();
-
-            searchOperation.setBaseDN(subBase);
-            try
-            {
-              b.search(searchOperation);
-            }
-            catch (DirectoryException de)
-            {
-              // If it's a "no such object" exception, then the base entry for
-              // the backend doesn't exist.  This isn't an error, so ignore it.
-              // We'll propogate all other errors, though.
-              if (de.getResultCode() != ResultCode.NO_SUCH_OBJECT)
-              {
-                throw de;
-              }
-            }
-          }
-        }
-        catch (DirectoryException de)
-        {
-          logger.traceException(de);
-
-          throw de;
-        }
-        catch (Exception e)
-        {
-          logger.traceException(e);
-
-          LocalizableMessage message = ERR_ROOTDSE_UNEXPECTED_SEARCH_FAILURE.
-              get(searchOperation.getConnectionID(),
-                  searchOperation.getOperationID(),
-                  stackTraceToSingleLineString(e));
-          throw new DirectoryException(
-                         DirectoryServer.getServerErrorResultCode(), message,
-                         e);
-        }
-        finally
-        {
-          searchOperation.setBaseDN(rootDSEDN);
-        }
-        break;
-
+        throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM,
+            ERR_ROOTDSE_NOT_SUPPORTED_SCOPE.get(
+                searchOperation.getConnectionID(),
+                searchOperation.getOperationID(),
+                searchOperation.getScope()));
       default:
         LocalizableMessage message = ERR_ROOTDSE_INVALID_SEARCH_SCOPE.
             get(searchOperation.getConnectionID(),
@@ -714,21 +579,6 @@
     }
   }
 
-  /**
-   * Returns the subordinate base DNs of the root DSE.
-   *
-   * @return the subordinate base DNs of the root DSE
-   */
-  @SuppressWarnings({ "unchecked", "rawtypes" })
-  public Map<DN, LocalBackend<?>> getSubordinateBaseDNs()
-  {
-    if (subordinateBaseDNs != null)
-    {
-      return subordinateBaseDNs;
-    }
-    return DirectoryServer.getPublicNamingContexts();
-  }
-
   @Override
   public Set<String> getSupportedControls()
   {
@@ -842,7 +692,7 @@
       {
         for (DN baseDN : subDNs)
         {
-          LocalBackend<?> backend = DirectoryServer.getBackend(baseDN);
+          LocalBackend<?> backend = DirectoryServer.getLocalBackend(baseDN);
           if (backend == null)
           {
             unacceptableReasons.add(WARN_ROOTDSE_NO_BACKEND_FOR_SUBORDINATE_BASE.get(baseDN));
@@ -869,7 +719,7 @@
     final ConfigChangeResult ccr = new ConfigChangeResult();
 
     // Check to see if we should apply a new set of base DNs.
-    ConcurrentHashMap<DN, LocalBackend<?>> subBases;
+    ConcurrentHashMap<DN, Backend<?>> subBases;
     try
     {
       Set<DN> subDNs = cfg.getSubordinateBaseDN();
@@ -883,7 +733,7 @@
         subBases = new ConcurrentHashMap<>();
         for (DN baseDN : subDNs)
         {
-          LocalBackend<?> backend = DirectoryServer.getBackend(baseDN);
+          LocalBackend<?> backend = DirectoryServer.getLocalBackend(baseDN);
           if (backend == null)
           {
             // This is not fine.  We can't use a suffix that doesn't exist.
@@ -928,18 +778,6 @@
 
     if (ccr.getResultCode() == ResultCode.SUCCESS)
     {
-      subordinateBaseDNs = subBases;
-
-      if (subordinateBaseDNs == null)
-      {
-        ccr.addMessage(INFO_ROOTDSE_USING_SUFFIXES_AS_BASE_DNS.get());
-      }
-      else
-      {
-        String basesStr = "{ " + Utils.joinAsString(", ", subordinateBaseDNs.keySet()) + " }";
-        ccr.addMessage(INFO_ROOTDSE_USING_NEW_SUBORDINATE_BASE_DNS.get(basesStr));
-      }
-
       if (showAllAttributes != newShowAll)
       {
         showAllAttributes = newShowAll;

--
Gitblit v1.10.0