From 10f0e9c1ad2e1296678c3706152a84437da35a78 Mon Sep 17 00:00:00 2001
From: Jean-Noël Rouvignac <jean-noel.rouvignac@forgerock.com>
Date: Wed, 06 Apr 2016 16:25:31 +0000
Subject: [PATCH] Fix uninstall tool + add upgrade task for removing configuration backend

---
 /dev/null                                                                                             |   52 ----
 opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java                        |   21 -
 opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java                       |    4 
 opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java                   |  342 +++++++++-----------------
 opendj-server-legacy/src/main/java/org/opends/server/core/ConfigurationBackend.java                   |   89 ++++++
 opendj-server-legacy/src/messages/org/opends/messages/tool.properties                                 |    2 
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java         |  143 ----------
 opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciListenerManager.java |  120 ++------
 8 files changed, 254 insertions(+), 519 deletions(-)

diff --git a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ConfigFileHandlerBackendConfiguration.xml b/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ConfigFileHandlerBackendConfiguration.xml
deleted file mode 100644
index 59bd2ed..0000000
--- a/opendj-maven-plugin/src/main/resources/config/xml/org/forgerock/opendj/server/config/ConfigFileHandlerBackendConfiguration.xml
+++ /dev/null
@@ -1,52 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-  The contents of this file are subject to the terms of the Common Development and
-  Distribution License (the License). You may not use this file except in compliance with the
-  License.
-
-  You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the
-  specific language governing permission and limitations under the License.
-
-  When distributing Covered Software, include this CDDL Header Notice in each file and include
-  the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL
-  Header, with the fields enclosed by brackets [] replaced by your own identifying
-  information: "Portions Copyright [year] [name of copyright owner]".
-
-  Copyright 2007-2008 Sun Microsystems, Inc.
-  Portions Copyright 2016 ForgeRock AS.
-!-->
-<adm:managed-object name="config-file-handler-backend"
-  plural-name="config-file-handler-backends"
-  package="org.forgerock.opendj.server.config" extends="backend"
-  advanced="true" xmlns:adm="http://opendj.forgerock.org/admin"
-  xmlns:ldap="http://opendj.forgerock.org/admin-ldap">
-  <adm:synopsis>
-    The
-    <adm:user-friendly-name />
-    allows clients to access the server configuration over protocol, and 
-    allow both read and write operations. Note: Modify DN operations are not
-    supported for entries in the server configuration.
-  </adm:synopsis>
-  <adm:profile name="ldap">
-    <ldap:object-class>
-      <ldap:name>ds-cfg-config-file-handler-backend</ldap:name>
-      <ldap:superior>ds-cfg-backend</ldap:superior>
-    </ldap:object-class>
-  </adm:profile>
-  <adm:property-override name="java-class" advanced="true">
-    <adm:default-behavior>
-      <adm:defined>
-        <adm:value>
-          org.opends.server.core.ConfigurationBackend
-        </adm:value>
-      </adm:defined>
-    </adm:default-behavior>
-  </adm:property-override>
-  <adm:property-override name="writability-mode" advanced="true">
-    <adm:default-behavior>
-      <adm:defined>
-        <adm:value>enabled</adm:value>
-      </adm:defined>
-    </adm:default-behavior>
-  </adm:property-override>
-</adm:managed-object>
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
index 953d0ac..ef801b0 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciHandler.java
@@ -22,7 +22,6 @@
 import java.util.SortedSet;
 import java.util.TreeSet;
 
-import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.LocalizedIllegalArgumentException;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigException;
@@ -33,23 +32,17 @@
 import org.forgerock.opendj.ldap.ModificationType;
 import org.forgerock.opendj.ldap.RDN;
 import org.forgerock.opendj.ldap.ResultCode;
-import org.forgerock.opendj.ldap.SearchScope;
 import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.forgerock.opendj.server.config.server.DseeCompatAccessControlHandlerCfg;
 import org.opends.server.api.AccessControlHandler;
-import org.opends.server.api.Backend;
 import org.opends.server.api.ClientConnection;
 import org.opends.server.backends.pluggable.SuffixContainer;
 import org.opends.server.controls.GetEffectiveRightsRequestControl;
 import org.opends.server.core.BindOperation;
-import org.opends.server.core.ConfigurationBackend;
 import org.opends.server.core.DirectoryServer;
 import org.opends.server.core.ExtendedOperation;
 import org.opends.server.core.ModifyDNOperation;
 import org.opends.server.core.SearchOperation;
-import org.opends.server.protocols.internal.InternalClientConnection;
-import org.opends.server.protocols.internal.InternalSearchOperation;
-import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.protocols.ldap.LDAPControl;
 import org.opends.server.types.Attribute;
 import org.opends.server.types.AttributeBuilder;
@@ -68,22 +61,17 @@
 import org.opends.server.workflowelement.localbackend.LocalBackendCompareOperation;
 import org.opends.server.workflowelement.localbackend.LocalBackendDeleteOperation;
 import org.opends.server.workflowelement.localbackend.LocalBackendModifyOperation;
-import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
 
 import static org.opends.messages.AccessControlMessages.*;
 import static org.opends.server.authorization.dseecompat.Aci.*;
 import static org.opends.server.authorization.dseecompat.EnumEvalReason.*;
 import static org.opends.server.config.ConfigConstants.*;
 import static org.opends.server.core.DirectoryServer.*;
-import static org.opends.server.protocols.internal.InternalClientConnection.*;
-import static org.opends.server.protocols.internal.Requests.*;
 import static org.opends.server.schema.SchemaConstants.*;
 import static org.opends.server.util.ServerConstants.*;
 import static org.opends.server.util.StaticUtils.*;
 
-/**
- * The AciHandler class performs the main processing for the dseecompat package.
- */
+/** The AciHandler class performs the main processing for the dseecompat package. */
 public final class AciHandler extends
     AccessControlHandler<DseeCompatAccessControlHandlerCfg>
 {
@@ -129,8 +117,6 @@
     initStatics();
   }
 
-
-
   /**
    * We initialize these for each new AciHandler so that we can clear out the
    * stale references that can occur during an in-core restart.
@@ -168,7 +154,6 @@
     // the intializeAccessControlHandler method.
   }
 
-  /** {@inheritDoc} */
   @Override
   public void filterEntry(Operation operation,
       SearchResultEntry unfilteredEntry, SearchResultEntry filteredEntry)
@@ -194,7 +179,6 @@
     }
   }
 
-  /** {@inheritDoc} */
   @Override
   public void finalizeAccessControlHandler()
   {
@@ -203,7 +187,6 @@
     DirectoryServer.deregisterSupportedControl(OID_GET_EFFECTIVE_RIGHTS);
   }
 
-  /** {@inheritDoc} */
   @Override
   public void initializeAccessControlHandler(
       DseeCompatAccessControlHandlerCfg configuration)
@@ -214,11 +197,9 @@
     aciList = new AciList(configurationDN);
     aciListenerMgr = new AciListenerManager(aciList, configurationDN);
     processGlobalAcis(configuration);
-    processConfigAcis();
     DirectoryServer.registerSupportedControl(OID_GET_EFFECTIVE_RIGHTS);
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(DN entryDN, Operation op, Control control)
       throws DirectoryException
@@ -257,7 +238,6 @@
     return true;
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(ExtendedOperation operation)
   {
@@ -272,7 +252,6 @@
     return accessAllowed(container);
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(LocalBackendAddOperation operation)
       throws DirectoryException
@@ -284,7 +263,6 @@
         && verifySyntax(operation.getEntryToAdd(), operation, container.getClientDN());
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(BindOperation bindOperation)
   {
@@ -292,8 +270,6 @@
     return true;
   }
 
-
-
   /**
    * Check access on compare operations. Note that the attribute type is
    * unavailable at this time, so this method partially parses the raw
@@ -328,8 +304,6 @@
     return isAllowed(container, operation);
   }
 
-
-
   /**
    * Check access on delete operations.
    *
@@ -345,8 +319,6 @@
     return isAllowed(container, operation);
   }
 
-
-
   /**
    * Checks access on a modifyDN operation.
    *
@@ -394,7 +366,6 @@
     return rdnChangesAllowed;
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(LocalBackendModifyOperation operation)
       throws DirectoryException
@@ -403,7 +374,6 @@
     return aciCheckMods(container, operation, skipAccessCheck(operation));
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(SearchOperation searchOperation)
   {
@@ -411,7 +381,6 @@
     return true;
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean isAllowed(Operation operation, Entry entry,
       SearchFilter filter) throws DirectoryException
@@ -426,7 +395,6 @@
     return testFilter(container, filter);
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean mayProxy(Entry proxyUser, Entry proxiedUser, Operation op)
   {
@@ -443,7 +411,6 @@
     return accessAllowedEntry(container);
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean maySend(DN dn, Operation operation, SearchResultReference reference)
   {
@@ -465,7 +432,6 @@
     return accessAllowed(container);
   }
 
-  /** {@inheritDoc} */
   @Override
   public boolean maySend(Operation operation, SearchResultEntry entry)
   {
@@ -513,8 +479,6 @@
     return true;
   }
 
-
-
   /**
    * Check access using the specified container. This container will
    * have all of the information to gather applicable ACIs and perform
@@ -579,8 +543,6 @@
     return ret;
   }
 
-
-
   /*
    * TODO Evaluate performance of this method. TODO Evaluate security
    * concerns of this method. Logic from this method taken almost
@@ -642,8 +604,6 @@
     return false;
   }
 
-
-
   /**
    * Performs an access check against all of the attributes of an entry. The
    * attributes that fail access are removed from the entry. This method
@@ -676,8 +636,6 @@
     }
   }
 
-
-
   /**
    * Checks to see if a LDAP modification is allowed access.
    *
@@ -708,8 +666,7 @@
 
       if (modAttrType.equals(aciType)
           /*
-           * Check that the operation has modify privileges if it contains
-           * an "aci" attribute type.
+           * Check that the operation has modify privileges if it contains an "aci" attribute type.
            */
           && !operation.getClientConnection().hasPrivilege(
               Privilege.MODIFY_ACL, operation))
@@ -725,8 +682,8 @@
               || modType == ModificationType.REPLACE
               || modType == ModificationType.INCREMENT)
           /*
-           * Check if we have rights to delete all values of an attribute
-           * type in the resource entry.
+           * Check if we have rights to delete all values of an attribute type in the resource
+           * entry.
            */
           && resourceEntry.hasAttribute(modAttrType))
       {
@@ -816,8 +773,6 @@
     return true;
   }
 
-
-
   /**
    * Perform all needed RDN checks for the modifyDN operation. The old RDN is
    * not equal to the new RDN. The access checks are:
@@ -860,8 +815,6 @@
     return ret;
   }
 
-
-
   /**
    * Check access on the new superior entry if it exists. If superiordn is null,
    * the entry does not exist or the DN cannot be locked then false is returned.
@@ -891,8 +844,6 @@
     }
   }
 
-
-
   /**
    * Check access on each attribute-value pair component of the
    * specified RDN. There may be more than one attribute-value pair if
@@ -922,8 +873,6 @@
     return true;
   }
 
-
-
   /**
    * Creates the allow and deny ACI lists based on the provided target
    * match context. These lists are stored in the evaluation context.
@@ -960,8 +909,6 @@
     targetMatchCtx.setDenyList(denys);
   }
 
-
-
   /**
    * Gathers all of the attribute types in an entry along with the
    * "objectclass" attribute type in a List. The "objectclass" attribute
@@ -988,8 +935,6 @@
     return typeList;
   }
 
-
-
   /**
    * Check access using the accessAllowed method. The LDAP add, compare,
    * modify and delete operations use this function. The other supported
@@ -1021,70 +966,6 @@
     return SYNTAX_DN_OID.equals(attribute.getSyntax().getOID());
   }
 
-
-
-  /**
-   * Process all ACIs under the "cn=config" naming context and adds them
-   * to the ACI list cache. It also logs messages about the number of
-   * ACIs added to the cache. This method is called once at startup. It
-   * will put the server in lockdown mode if needed.
-   *
-   * @throws InitializationException
-   *           If there is an error searching for the ACIs in the naming
-   *           context.
-   */
-  private void processConfigAcis() throws InitializationException
-  {
-    LinkedList<LocalizableMessage> failedACIMsgs = new LinkedList<>();
-    InternalClientConnection conn = getRootConnection();
-
-    Backend<?> configBackend = DirectoryServer.getBackend(ConfigurationBackend.CONFIG_BACKEND_ID);
-    for (DN baseDN : configBackend.getBaseDNs())
-    {
-      try
-      {
-        if (! configBackend.entryExists(baseDN))
-        {
-          continue;
-        }
-      }
-      catch (Exception e)
-      {
-        logger.traceException(e);
-
-        // FIXME -- Is there anything that we need to do here?
-        continue;
-      }
-
-      try {
-        SearchRequest request = newSearchRequest(baseDN, SearchScope.WHOLE_SUBTREE, "aci=*").addAttribute("aci");
-        InternalSearchOperation internalSearch =
-            new InternalSearchOperation(conn, nextOperationID(), nextMessageID(), request);
-        LocalBackendSearchOperation localSearch = new LocalBackendSearchOperation(internalSearch);
-
-        configBackend.search(localSearch);
-
-        if (!internalSearch.getSearchEntries().isEmpty())
-        {
-          int validAcis =
-              aciList.addAci(internalSearch.getSearchEntries(), failedACIMsgs);
-          if (!failedACIMsgs.isEmpty())
-          {
-            aciListenerMgr.logMsgsSetLockDownMode(failedACIMsgs);
-          }
-          logger.debug(INFO_ACI_ADD_LIST_ACIS, validAcis, baseDN);
-        }
-      }
-      catch (Exception e)
-      {
-        LocalizableMessage message = INFO_ACI_HANDLER_FAIL_PROCESS_ACI.get();
-        throw new InitializationException(message, e);
-      }
-    }
-  }
-
-
-
   /**
    * Process all global ACI attribute types found in the configuration
    * entry and adds them to that ACI list cache. It also logs messages
@@ -1105,7 +986,7 @@
   {
     try
     {
-      final SortedSet<Aci> globalAcis = new TreeSet<Aci>();
+      final SortedSet<Aci> globalAcis = new TreeSet<>();
       for (String value : configuration.getGlobalACI())
       {
         globalAcis.add(Aci.decode(ByteString.valueOfUtf8(value), DN.rootDN()));
@@ -1124,8 +1005,6 @@
     }
   }
 
-
-
   /**
    * Check to see if the specified entry has the specified privilege.
    *
@@ -1139,8 +1018,6 @@
     return ClientConnection.hasPrivilege(e, Privilege.BYPASS_ACL);
   }
 
-
-
   /**
    * Check to see if the client entry has BYPASS_ACL privileges for this
    * operation.
@@ -1156,8 +1033,6 @@
         Privilege.BYPASS_ACL, operation);
   }
 
-
-
   /**
    * Performs the test of the deny and allow access lists using the
    * provided evaluation context. The deny list is checked first.
@@ -1185,12 +1060,12 @@
       final EnumEvalResult res = Aci.evaluate(evalCtx, denyAci);
       // Failure could be returned if a system limit is hit or
       // search fails
-      if (res.equals(EnumEvalResult.FAIL))
+      if (EnumEvalResult.FAIL.equals(res))
       {
         evalCtx.setEvaluationResult(EVALUATED_DENY_ACI, denyAci);
         return false;
       }
-      else if (res.equals(EnumEvalResult.TRUE))
+      else if (EnumEvalResult.TRUE.equals(res))
       {
         if (testAndSetTargAttrOperationMatches(evalCtx, denyAci, true))
         {
@@ -1204,7 +1079,7 @@
     for (Aci allowAci : evalCtx.getAllowList())
     {
       final EnumEvalResult res = Aci.evaluate(evalCtx, allowAci);
-      if (res.equals(EnumEvalResult.TRUE))
+      if (EnumEvalResult.TRUE.equals(res))
       {
         if (testAndSetTargAttrOperationMatches(evalCtx, allowAci, false))
         {
@@ -1281,8 +1156,6 @@
     return true;
   }
 
-
-
   /**
    * Evaluate an entry to be added to see if it has any "aci" attribute
    * type. If it does, examines each "aci" attribute type value for
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciListenerManager.java b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciListenerManager.java
index 2577e75..4507d11 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciListenerManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/authorization/dseecompat/AciListenerManager.java
@@ -16,13 +16,18 @@
  */
 package org.opends.server.authorization.dseecompat;
 
-import java.util.*;
+import java.util.EnumSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.SearchScope;
+import org.forgerock.opendj.ldap.schema.AttributeType;
 import org.opends.server.api.AlertGenerator;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackendInitializationListener;
@@ -31,13 +36,22 @@
 import org.opends.server.api.plugin.PluginResult.PostOperation;
 import org.opends.server.api.plugin.PluginType;
 import org.opends.server.core.DirectoryServer;
-import org.opends.server.protocols.internal.InternalClientConnection;
 import org.opends.server.protocols.internal.InternalSearchOperation;
 import org.opends.server.protocols.internal.SearchRequest;
 import org.opends.server.protocols.ldap.LDAPControl;
-import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.opends.server.types.*;
-import org.opends.server.types.operation.*;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.IndexType;
+import org.opends.server.types.Modification;
+import org.opends.server.types.SearchFilter;
+import org.opends.server.types.operation.PostOperationAddOperation;
+import org.opends.server.types.operation.PostOperationDeleteOperation;
+import org.opends.server.types.operation.PostOperationModifyDNOperation;
+import org.opends.server.types.operation.PostOperationModifyOperation;
+import org.opends.server.types.operation.PostSynchronizationAddOperation;
+import org.opends.server.types.operation.PostSynchronizationDeleteOperation;
+import org.opends.server.types.operation.PostSynchronizationModifyDNOperation;
+import org.opends.server.types.operation.PostSynchronizationModifyOperation;
 import org.opends.server.workflowelement.localbackend.LocalBackendSearchOperation;
 
 import static org.opends.messages.AccessControlMessages.*;
@@ -55,18 +69,11 @@
 {
   private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass();
 
-  /**
-   * The fully-qualified name of this class.
-   */
+  /** The fully-qualified name of this class. */
   private static final String CLASS_NAME =
       "org.opends.server.authorization.dseecompat.AciListenerManager";
 
-
-
-  /**
-   * Internal plugin used for updating the cache before a response is
-   * sent to the client.
-   */
+  /** Internal plugin used for updating the cache before a response is sent to the client. */
   private final class AciChangeListenerPlugin extends
       InternalDirectoryServerPlugin
   {
@@ -83,9 +90,6 @@
           PluginType.POST_OPERATION_MODIFY_DN), true);
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public void doPostSynchronization(
         PostSynchronizationAddOperation addOperation)
@@ -97,9 +101,6 @@
       }
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public void doPostSynchronization(
         PostSynchronizationDeleteOperation deleteOperation)
@@ -111,9 +112,6 @@
       }
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public void doPostSynchronization(
         PostSynchronizationModifyDNOperation modifyDNOperation)
@@ -125,9 +123,6 @@
       }
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public void doPostSynchronization(
         PostSynchronizationModifyOperation modifyOperation)
@@ -140,9 +135,6 @@
       }
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public PostOperation doPostOperation(
         PostOperationAddOperation addOperation)
@@ -158,9 +150,6 @@
       return PluginResult.PostOperation.continueOperationProcessing();
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public PostOperation doPostOperation(
         PostOperationDeleteOperation deleteOperation)
@@ -176,9 +165,6 @@
       return PluginResult.PostOperation.continueOperationProcessing();
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public PostOperation doPostOperation(
         PostOperationModifyDNOperation modifyDNOperation)
@@ -195,9 +181,6 @@
       return PluginResult.PostOperation.continueOperationProcessing();
     }
 
-
-
-    /** {@inheritDoc} */
     @Override
     public PostOperation doPostOperation(
         PostOperationModifyOperation modifyOperation)
@@ -214,8 +197,6 @@
       return PluginResult.PostOperation.continueOperationProcessing();
     }
 
-
-
     private void doPostAdd(Entry addedEntry)
     {
       // This entry might have both global and aci attribute types.
@@ -231,8 +212,6 @@
       }
     }
 
-
-
     private void doPostDelete(Entry deletedEntry)
     {
       // This entry might have both global and aci attribute types.
@@ -243,15 +222,11 @@
       aciList.removeAci(deletedEntry, hasAci, hasGlobalAci);
     }
 
-
-
     private void doPostModifyDN(DN fromDN, DN toDN)
     {
       aciList.renameAci(fromDN, toDN);
     }
 
-
-
     private void doPostModify(List<Modification> mods, Entry oldEntry,
         Entry newEntry)
     {
@@ -284,11 +259,8 @@
             hasGlobalAci);
       }
     }
-
   }
 
-
-
   /** The configuration DN. */
   private DN configurationDN;
 
@@ -300,15 +272,6 @@
 
   /** Search filter used in context search for "aci" attribute types. */
   private static SearchFilter aciFilter;
-
-  /**
-   * Internal plugin used for updating the cache before a response is
-   * sent to the client.
-   */
-  private final AciChangeListenerPlugin plugin;
-
-  /** The aci attribute type is operational so we need to specify it to be returned. */
-  private static LinkedHashSet<String> attrs = new LinkedHashSet<>();
   static
   {
     // Set up the filter used to search private and public contexts.
@@ -320,10 +283,10 @@
     {
       // TODO should never happen, error message?
     }
-    attrs.add("aci");
   }
 
-
+  /** Internal plugin used for updating the cache before a response is sent to the client. */
+  private final AciChangeListenerPlugin plugin;
 
   /**
    * Save the list created by the AciHandler routine. Registers as an
@@ -358,8 +321,6 @@
     DirectoryServer.registerAlertGenerator(this);
   }
 
-
-
   /**
    * Deregister from the change notification listener, the backend
    * initialization listener and the alert generator.
@@ -371,8 +332,6 @@
     DirectoryServer.deregisterAlertGenerator(this);
   }
 
-
-
   /**
    * {@inheritDoc} In this case, the server will search the backend to
    * find all aci attribute type values that it may contain and add them
@@ -393,9 +352,7 @@
 
     LinkedList<LocalizableMessage> failedACIMsgs = new LinkedList<>();
 
-    InternalClientConnection conn = getRootConnection();
-    // Add manageDsaIT control so any ACIs in referral entries will be
-    // picked up.
+    // Add manageDsaIT control so any ACIs in referral entries will be picked up.
     LDAPControl c1 = new LDAPControl(OID_MANAGE_DSAIT_CONTROL, true);
     // Add group membership control to let a backend look for it and
     // decide if it would abort searches.
@@ -418,18 +375,17 @@
       SearchRequest request = newSearchRequest(baseDN, SearchScope.WHOLE_SUBTREE, aciFilter)
           .addControl(c1)
           .addControl(c2)
-          .addAttribute(attrs);
+          .addAttribute("aci");
       InternalSearchOperation internalSearch =
-          new InternalSearchOperation(conn, nextOperationID(), nextMessageID(), request);
-      LocalBackendSearchOperation localInternalSearch =
-          new LocalBackendSearchOperation(internalSearch);
+          new InternalSearchOperation(getRootConnection(), nextOperationID(), nextMessageID(), request);
+      LocalBackendSearchOperation localInternalSearch = new LocalBackendSearchOperation(internalSearch);
       try
       {
         backend.search(localInternalSearch);
       }
       catch (Exception e)
       {
-        logger.traceException(e);
+        logger.trace(INFO_ACI_HANDLER_FAIL_PROCESS_ACI, e);
         continue;
       }
       if (!internalSearch.getSearchEntries().isEmpty())
@@ -444,12 +400,11 @@
     }
   }
 
-
-
   /**
-   * {@inheritDoc} In this case, the server will remove all aci
-   * attribute type values associated with entries in the provided
-   * backend.
+   * {@inheritDoc}
+   * <p>
+   * In this case, the server will remove all aci attribute type values associated with entries in
+   * the provided backend.
    */
   @Override
   public void performBackendPostFinalizationProcessing(Backend<?> backend)
@@ -467,7 +422,6 @@
     // nothing to do.
   }
 
-
   /**
    * Retrieves the fully-qualified name of the Java class for this alert
    * generator implementation.
@@ -481,8 +435,6 @@
     return CLASS_NAME;
   }
 
-
-
   /**
    * Retrieves the DN of the configuration entry used to configure the
    * handler.
@@ -496,8 +448,6 @@
     return this.configurationDN;
   }
 
-
-
   /**
    * Retrieves information about the set of alerts that this generator
    * may produce. The map returned should be between the notification
@@ -536,11 +486,8 @@
     }
   }
 
-
-
   /**
-   * Send an WARN_ACI_ENTER_LOCKDOWN_MODE alert notification and put the
-   * server in lockdown mode.
+   * Send an WARN_ACI_ENTER_LOCKDOWN_MODE alert notification and put the server in lockdown mode.
    */
   private void setLockDownMode()
   {
@@ -554,7 +501,6 @@
           ALERT_TYPE_ACCESS_CONTROL_PARSE_FAILED, lockDownMsg);
       // Enter lockdown mode.
       DirectoryServer.setLockdownMode(true);
-
     }
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java b/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
index 9cf4385..966778d 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/BackendConfigManager.java
@@ -27,26 +27,25 @@
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Set;
-
 import java.util.concurrent.ConcurrentHashMap;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.config.server.ConfigChangeResult;
 import org.forgerock.opendj.config.server.ConfigException;
-import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.config.server.ConfigurationAddListener;
 import org.forgerock.opendj.config.server.ConfigurationChangeListener;
 import org.forgerock.opendj.config.server.ConfigurationDeleteListener;
+import org.forgerock.opendj.ldap.DN;
+import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.server.config.meta.BackendCfgDefn;
 import org.forgerock.opendj.server.config.server.BackendCfg;
 import org.forgerock.opendj.server.config.server.RootCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.BackendInitializationListener;
 import org.opends.server.config.ConfigConstants;
-import org.forgerock.opendj.ldap.DN;
-import org.opends.server.types.Entry;
 import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.WritabilityMode;
 
@@ -83,18 +82,20 @@
    * Initializes the configuration associated with the Directory Server
    * backends. This should only be called at Directory Server startup.
    *
+   * @param backendIDsToStart
+   *           The list of backendID to start. Everything will be started if empty.
    * @throws ConfigException
    *           If a critical configuration problem prevents the backend
    *           initialization from succeeding.
    * @throws InitializationException
    *           If a problem occurs while initializing the backends that is not
    *           related to the server configuration.
-   * @param backendIDsToStart
-   *           The list of backendID to start. Everything will be started if empty.
    */
   public void initializeBackendConfig(Collection<String> backendIDsToStart)
          throws ConfigException, InitializationException
   {
+    initializeConfigurationBackend();
+
     // Register add and delete listeners.
     RootCfg root = serverContext.getRootConfig();
     root.addBackendAddListener(this);
@@ -115,7 +116,6 @@
       LocalizableMessage message =
           ERR_CONFIG_BACKEND_CANNOT_GET_CONFIG_BASE.get(getExceptionMessage(e));
       throw new ConfigException(message, e);
-
     }
 
 
@@ -124,8 +124,7 @@
     // configuration, even if there are no backends defined below it.
     if (backendRoot == null)
     {
-      LocalizableMessage message = ERR_CONFIG_BACKEND_BASE_DOES_NOT_EXIST.get();
-      throw new ConfigException(message);
+      throw new ConfigException(ERR_CONFIG_BACKEND_BASE_DOES_NOT_EXIST.get());
     }
 
 
@@ -134,109 +133,77 @@
     {
       // Get the handler's configuration.
       // This will decode and validate its properties.
-      BackendCfg backendCfg = root.getBackend(name);
-
+      final BackendCfg backendCfg = root.getBackend(name);
+      final DN backendDN = backendCfg.dn();
       final String backendID = backendCfg.getBackendId();
       if (!backendIDsToStart.isEmpty() && !backendIDsToStart.contains(backendID))
       {
         continue;
       }
-      DN backendDN = backendCfg.dn();
 
       // Register as a change listener for this backend so that we can be
       // notified when it is disabled or enabled.
       backendCfg.addChangeListener(this);
 
-      // Ignore this handler if it is disabled.
-      if (backendCfg.isEnabled())
+      if (!backendCfg.isEnabled())
       {
-        // If there is already a backend registered with the specified ID,
-        // then log an error and skip it.
-        if (DirectoryServer.hasBackend(backendID))
-        {
-          logger.warn(WARN_CONFIG_BACKEND_DUPLICATE_BACKEND_ID, backendID, backendDN);
-          continue;
-        }
-
-        // See if the entry contains an attribute that specifies the class name
-        // for the backend implementation.  If it does, then load it and make
-        // sure that it's a valid backend implementation.  There is no such
-        // attribute, the specified class cannot be loaded, or it does not
-        // contain a valid backend implementation, then log an error and skip it.
-        String className = backendCfg.getJavaClass();
-
-        Backend<? extends BackendCfg> backend;
-        try
-        {
-          backend = loadBackendClass(className).newInstance();
-        }
-        catch (Exception e)
-        {
-          logger.traceException(e);
-          logger.error(ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE, className, backendDN, stackTraceToSingleLineString(e));
-          continue;
-        }
-
-        // If this backend is the configuration backend, then we don't want to do
-        // any more with it because the configuration will have already been started.
-        if (backend instanceof ConfigurationBackend)
-        {
-          continue;
-        }
-
-        // Set the backend ID and writability mode for this backend.
-        backend.setBackendID(backendID);
-        backend.setWritabilityMode(toWritabilityMode(backendCfg.getWritabilityMode()));
-
-
-        ConfigChangeResult ccr = new ConfigChangeResult();
-        if (!acquireSharedLock(backend, backendID, ccr)
-            || !initializeBackend(backend, backendCfg, ccr))
-        {
-          logger.error(ccr.getMessages().get(0));
-          continue;
-        }
-
-        onBackendPreInitialization(backend);
-
-        try
-        {
-          DirectoryServer.registerBackend(backend);
-        }
-        catch (Exception e)
-        {
-          logger.traceException(e);
-
-          logger.warn(WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND, backendID, getExceptionMessage(e));
-          // FIXME -- Do we need to send an admin alert?
-        }
-
-        onBackendPostInitialization(backend);
-
-        // Put this backend in the hash so that we will be able to find it if it is altered
-        registeredBackends.put(backendDN, backend);
-      }
-      else
-      {
-        // The backend is explicitly disabled.  Log a mild warning and continue.
         logger.debug(INFO_CONFIG_BACKEND_DISABLED, backendDN);
+        continue;
       }
+      else if (DirectoryServer.hasBackend(backendID))
+      {
+        logger.warn(WARN_CONFIG_BACKEND_DUPLICATE_BACKEND_ID, backendID, backendDN);
+        continue;
+      }
+
+      // See if the entry contains an attribute that specifies the class name
+      // for the backend implementation.  If it does, then load it and make
+      // sure that it's a valid backend implementation.  There is no such
+      // attribute, the specified class cannot be loaded, or it does not
+      // contain a valid backend implementation, then log an error and skip it.
+      String className = backendCfg.getJavaClass();
+
+      Backend<? extends BackendCfg> backend;
+      try
+      {
+        backend = loadBackendClass(className).newInstance();
+      }
+      catch (Exception e)
+      {
+        logger.traceException(e);
+        logger.error(ERR_CONFIG_BACKEND_CANNOT_INSTANTIATE, className, backendDN, stackTraceToSingleLineString(e));
+        continue;
+      }
+
+      initializeBackend(backend, backendCfg);
     }
   }
 
-  private void onBackendPreInitialization(Backend<? extends BackendCfg> backend)
+  private void initializeConfigurationBackend() throws InitializationException
   {
-    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    final ConfigurationBackend configBackend =
+        new ConfigurationBackend(serverContext, DirectoryServer.getConfigurationHandler());
+    initializeBackend(configBackend, configBackend.getBackendCfg());
+  }
+
+  private void initializeBackend(Backend<? extends BackendCfg> backend, BackendCfg backendCfg)
+  {
+    ConfigChangeResult ccr = new ConfigChangeResult();
+    initializeBackend(backend, backendCfg, ccr);
+    for (LocalizableMessage msg : ccr.getMessages())
     {
-      listener.performBackendPreInitializationProcessing(backend);
+      logger.error(msg);
     }
   }
 
-  private void onBackendPostInitialization(Backend<? extends BackendCfg> backend)
+  private void initializeBackend(Backend<? extends BackendCfg> backend, BackendCfg backendCfg, ConfigChangeResult ccr)
   {
-    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    backend.setBackendID(backendCfg.getBackendId());
+    backend.setWritabilityMode(toWritabilityMode(backendCfg.getWritabilityMode()));
+
+    if (acquireSharedLock(backend, backendCfg.getBackendId(), ccr) && configureAndOpenBackend(backend, backendCfg, ccr))
     {
-      listener.performBackendPostInitializationProcessing(backend);
+      registerBackend(backend, backendCfg, ccr);
     }
   }
 
@@ -422,40 +389,11 @@
         {
           // It isn't disabled, so we will do so now and deregister it from the
           // Directory Server.
-          registeredBackends.remove(backendDN);
-
-          for (BackendInitializationListener listener : getBackendInitializationListeners())
-          {
-            listener.performBackendPreFinalizationProcessing(backend);
-          }
-
-          DirectoryServer.deregisterBackend(backend);
-
-          for (BackendInitializationListener listener : getBackendInitializationListeners())
-          {
-            listener.performBackendPostFinalizationProcessing(backend);
-          }
+          deregisterBackend(backendDN, backend);
 
           backend.finalizeBackend();
 
-          // Remove the shared lock for this backend.
-          try
-          {
-            String lockFile = LockFileManager.getBackendLockFileName(backend);
-            StringBuilder failureReason = new StringBuilder();
-            if (! LockFileManager.releaseLock(lockFile, failureReason))
-            {
-              logger.warn(WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK, backend.getBackendID(), failureReason);
-              // FIXME -- Do we need to send an admin alert?
-            }
-          }
-          catch (Exception e2)
-          {
-            logger.traceException(e2);
-            logger.warn(WARN_CONFIG_BACKEND_CANNOT_RELEASE_SHARED_LOCK, backend
-                .getBackendID(), stackTraceToSingleLineString(e2));
-            // FIXME -- Do we need to send an admin alert?
-          }
+          releaseSharedLock(backend, backend.getBackendID());
 
           return ccr;
         } // else already disabled, no need to do anything.
@@ -471,10 +409,6 @@
       return ccr;
     }
 
-
-    String backendID = cfg.getBackendId();
-    WritabilityMode writabilityMode = toWritabilityMode(cfg.getWritabilityMode());
-
     // See if the entry contains an attribute that specifies the class name
     // for the backend implementation.  If it does, then load it and make sure
     // that it's a valid backend implementation.  There is no such attribute,
@@ -482,13 +416,10 @@
     // backend implementation, then log an error and skip it.
     String className = cfg.getJavaClass();
 
-
-    // See if this backend is currently active and if so if the name of the
-    // class is the same.
+    // See if this backend is currently active and if so if the name of the class is the same.
     if (backend != null && !className.equals(backend.getClass().getName()))
     {
-      // It is not the same.  Try to load it and see if it is a valid backend
-      // implementation.
+      // It is not the same. Try to load it and see if it is a valid backend implementation.
       try
       {
         Class<?> backendClass = DirectoryServer.loadClass(className);
@@ -537,50 +468,51 @@
         return ccr;
       }
 
-
-      // Set the backend ID and writability mode for this backend.
-      backend.setBackendID(backendID);
-      backend.setWritabilityMode(writabilityMode);
-
-      if (!acquireSharedLock(backend, backendID, ccr)
-          || !initializeBackend(backend, cfg, ccr))
-      {
-        return ccr;
-      }
-
-      onBackendPreInitialization(backend);
-
-      // Register the backend with the server.
-      try
-      {
-        DirectoryServer.registerBackend(backend);
-      }
-      catch (Exception e)
-      {
-        logger.traceException(e);
-
-        LocalizableMessage message = WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(
-                backendID, getExceptionMessage(e));
-        logger.warn(message);
-
-        // FIXME -- Do we need to send an admin alert?
-        ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-        ccr.addMessage(message);
-        return ccr;
-      }
-
-      onBackendPostInitialization(backend);
-
-      registeredBackends.put(backendDN, backend);
+      initializeBackend(backend, cfg, ccr);
+      return ccr;
     }
     else if (ccr.getResultCode() == ResultCode.SUCCESS && backend != null)
     {
-      backend.setWritabilityMode(writabilityMode);
+      backend.setWritabilityMode(toWritabilityMode(cfg.getWritabilityMode()));
     }
 
     return ccr;
   }
 
+  private boolean registerBackend(Backend<? extends BackendCfg> backend, BackendCfg backendCfg, ConfigChangeResult ccr)
+  {
+    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    {
+      listener.performBackendPreInitializationProcessing(backend);
+    }
+
+    try
+    {
+      DirectoryServer.registerBackend(backend);
+    }
+    catch (Exception e)
+    {
+      logger.traceException(e);
+
+      LocalizableMessage message =
+          WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(backendCfg.getBackendId(), getExceptionMessage(e));
+      logger.error(message);
+
+      // FIXME -- Do we need to send an admin alert?
+      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
+      ccr.addMessage(message);
+      return false;
+    }
+
+    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    {
+      listener.performBackendPostInitializationProcessing(backend);
+    }
+
+    registeredBackends.put(backendCfg.dn(), backend);
+    return true;
+  }
+
   @Override
   public boolean isConfigurationAddAcceptable(
        BackendCfg configEntry,
@@ -709,51 +641,15 @@
       return ccr;
     }
 
-
-    // Set the backend ID and writability mode for this backend.
-    backend.setBackendID(backendID);
-    backend.setWritabilityMode(toWritabilityMode(cfg.getWritabilityMode()));
-
-
-    if (!acquireSharedLock(backend, backendID, ccr)
-        || !initializeBackend(backend, cfg, ccr))
-    {
-      return ccr;
-    }
-
-    onBackendPreInitialization(backend);
-
-    // At this point, the backend should be online.  Add it as one of the
-    // registered backends for this backend config manager.
-    try
-    {
-      DirectoryServer.registerBackend(backend);
-    }
-    catch (Exception e)
-    {
-      logger.traceException(e);
-
-      LocalizableMessage message = WARN_CONFIG_BACKEND_CANNOT_REGISTER_BACKEND.get(
-              backendID, getExceptionMessage(e));
-      logger.error(message);
-
-      // FIXME -- Do we need to send an admin alert?
-      ccr.setResultCode(DirectoryServer.getServerErrorResultCode());
-      ccr.addMessage(message);
-      return ccr;
-    }
-
-    onBackendPostInitialization(backend);
-
-    registeredBackends.put(backendDN, backend);
+    initializeBackend(backend, cfg, ccr);
     return ccr;
   }
 
-  private boolean initializeBackend(Backend<? extends BackendCfg> backend, BackendCfg cfg, ConfigChangeResult ccr)
+  private boolean configureAndOpenBackend(Backend<?> backend, BackendCfg cfg, ConfigChangeResult ccr)
   {
     try
     {
-      initializeBackend(backend, cfg);
+      configureAndOpenBackend(backend, cfg);
       return true;
     }
     catch (Exception e)
@@ -769,6 +665,13 @@
     }
   }
 
+  @SuppressWarnings({ "unchecked", "rawtypes" })
+  private void configureAndOpenBackend(Backend backend, BackendCfg cfg) throws ConfigException, InitializationException
+  {
+    backend.configureBackend(cfg, serverContext);
+    backend.openBackend();
+  }
+
   @SuppressWarnings("unchecked")
   private Class<Backend<BackendCfg>> loadBackendClass(String className) throws Exception
   {
@@ -844,18 +747,7 @@
       return ccr;
     }
 
-    for (BackendInitializationListener listener : getBackendInitializationListeners())
-    {
-      listener.performBackendPreFinalizationProcessing(backend);
-    }
-
-    registeredBackends.remove(backendDN);
-    DirectoryServer.deregisterBackend(backend);
-
-    for (BackendInitializationListener listener : getBackendInitializationListeners())
-    {
-      listener.performBackendPostFinalizationProcessing(backend);
-    }
+    deregisterBackend(backendDN, backend);
 
     try
     {
@@ -873,11 +765,19 @@
     return ccr;
   }
 
-  @SuppressWarnings({ "unchecked", "rawtypes" })
-  private void initializeBackend(Backend backend, BackendCfg cfg)
-       throws ConfigException, InitializationException
+  private void deregisterBackend(DN backendDN, Backend<?> backend)
   {
-    backend.configureBackend(cfg, serverContext);
-    backend.openBackend();
+    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    {
+      listener.performBackendPreFinalizationProcessing(backend);
+    }
+
+    registeredBackends.remove(backendDN);
+    DirectoryServer.deregisterBackend(backend);
+
+    for (BackendInitializationListener listener : getBackendInitializationListeners())
+    {
+      listener.performBackendPostFinalizationProcessing(backend);
+    }
   }
 }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/ConfigurationBackend.java b/opendj-server-legacy/src/main/java/org/opends/server/core/ConfigurationBackend.java
index 3c81e75..942e3e2 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/ConfigurationBackend.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/ConfigurationBackend.java
@@ -23,23 +23,28 @@
 import java.io.File;
 import java.nio.file.Path;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashSet;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
+import java.util.SortedSet;
 
 import org.forgerock.i18n.LocalizableMessage;
 import org.forgerock.i18n.slf4j.LocalizedLogger;
 import org.forgerock.opendj.adapter.server3x.Converters;
 import org.forgerock.opendj.config.server.ConfigException;
+import org.forgerock.opendj.config.server.ConfigurationChangeListener;
 import org.forgerock.opendj.ldap.ConditionResult;
 import org.forgerock.opendj.ldap.DN;
 import org.forgerock.opendj.ldap.ResultCode;
 import org.forgerock.opendj.ldap.schema.AttributeType;
-import org.forgerock.opendj.server.config.server.ConfigFileHandlerBackendCfg;
+import org.forgerock.opendj.server.config.meta.BackendCfgDefn.WritabilityMode;
+import org.forgerock.opendj.server.config.server.BackendCfg;
 import org.opends.server.api.Backend;
 import org.opends.server.api.Backupable;
 import org.opends.server.api.ClientConnection;
+import org.opends.server.core.ConfigurationBackend.ConfigurationBackendCfg;
 import org.opends.server.types.BackupConfig;
 import org.opends.server.types.BackupDirectory;
 import org.opends.server.types.DirectoryException;
@@ -53,12 +58,80 @@
 import org.opends.server.types.Privilege;
 import org.opends.server.types.RestoreConfig;
 import org.opends.server.util.BackupManager;
+import org.opends.server.util.CollectionUtils;
 import org.opends.server.util.StaticUtils;
 
 /** Back-end responsible for management of configuration entries. */
-public class ConfigurationBackend extends Backend<ConfigFileHandlerBackendCfg> implements Backupable
+public class ConfigurationBackend extends Backend<ConfigurationBackendCfg> implements Backupable
 {
   /**
+   * Dummy {@link BackendCfg} implementation for the {@link ConfigurationBackend}. No config is
+   * needed for this specific backend, but this class is required to behave like other backends
+   * during initialization.
+   */
+  public final class ConfigurationBackendCfg implements BackendCfg
+  {
+    private ConfigurationBackendCfg()
+    {
+      // let nobody instantiate it
+    }
+
+    @Override
+    public DN dn()
+    {
+      return getBaseDNs()[0];
+    }
+
+    @Override
+    public Class<? extends BackendCfg> configurationClass()
+    {
+      return this.getClass();
+    }
+
+    @Override
+    public String getBackendId()
+    {
+      return CONFIG_BACKEND_ID;
+    }
+
+    @Override
+    public SortedSet<DN> getBaseDN()
+    {
+      return Collections.unmodifiableSortedSet(CollectionUtils.newTreeSet(getBaseDNs()));
+    }
+
+    @Override
+    public boolean isEnabled()
+    {
+      return true;
+    }
+
+    @Override
+    public String getJavaClass()
+    {
+      return ConfigurationBackend.class.getName();
+    }
+
+    @Override
+    public WritabilityMode getWritabilityMode()
+    {
+      return WritabilityMode.ENABLED;
+    }
+
+    @Override
+    public void addChangeListener(ConfigurationChangeListener<BackendCfg> listener)
+    {
+      // no-op
+    }
+
+    @Override
+    public void removeChangeListener(ConfigurationChangeListener<BackendCfg> listener)
+    {
+      // no-op
+    }
+  }
+
+  /**
    * The backend ID for the configuration backend.
    * <p>
    * Try to avoid potential conflict with user backend identifiers.
@@ -114,6 +187,16 @@
     setBackendID(CONFIG_BACKEND_ID);
   }
 
+  /**
+   * Returns a new {@link ConfigurationBackendCfg} for this {@link ConfigurationBackend}.
+   *
+   * @return a new {@link ConfigurationBackendCfg} for this {@link ConfigurationBackend}
+   */
+  public ConfigurationBackendCfg getBackendCfg()
+  {
+    return new ConfigurationBackendCfg();
+  }
+
   @Override
   public void closeBackend()
   {
@@ -128,7 +211,7 @@
   }
 
   @Override
-  public void configureBackend(ConfigFileHandlerBackendCfg cfg,  ServerContext serverContext) throws ConfigException
+  public void configureBackend(ConfigurationBackendCfg cfg, ServerContext serverContext) throws ConfigException
   {
     // No action is required.
   }
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
index cfc40a3..dfbc121 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/core/DirectoryServer.java
@@ -1358,17 +1358,6 @@
     configFile = environmentConfig.getConfigFile();
     configurationHandler = ConfigurationHandler.bootstrapConfiguration(serverContext);
     serverManagementContext = new ServerManagementContext(configurationHandler);
-
-    final ConfigurationBackend configBackend = new ConfigurationBackend(serverContext, configurationHandler);
-    configBackend.openBackend();
-    try
-    {
-      registerBackend(configBackend);
-    }
-    catch (DirectoryException e)
-    {
-      throw new InitializationException(LocalizableMessage.raw("Unable to register configuration backend", e));
-    }
   }
 
   /**
@@ -1527,18 +1516,8 @@
       initializeRootDNConfigManager();
 
       initializeAuthenticatedUsers();
-      // initialize both subentry manager and group manager for this backend.
       initializeSubentryManager();
       initializeGroupManager();
-
-      // Initialize both subentry manager and group manager
-      // for the configuration backend.
-      // TODO : why do we initialize these now ? Can't we do them after backend initialization ?
-
-      Backend<?> configBackend = getConfigurationBackend();
-      subentryManager.performBackendPreInitializationProcessing(configBackend);
-      groupManager.performBackendPreInitializationProcessing(configBackend);
-
       AccessControlConfigManager.getInstance().initializeAccessControl(serverContext);
 
       initializeBackends(Collections.<String> emptyList());
diff --git a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
index 5196ee1..9a9f377 100644
--- a/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
+++ b/opendj-server-legacy/src/main/java/org/opends/server/tools/upgrade/Upgrade.java
@@ -635,6 +635,10 @@
         rebuildIndexesNamed(INFO_UPGRADE_REBUILD_INDEXES_DISTINGUISHED_NAME.get(),
             "distinguishedName", "member", "owner", "roleOccupant", "seeAlso"));
 
+    register("4.0.0",
+        deleteConfigEntry(INFO_UPGRADE_TASK_CONFIGURATION_BACKEND_NOT_CONFIGURABLE.get(),
+            "dn: ds-cfg-backend-id=config,cn=Backends,cn=config"));
+
     /**
      * All upgrades will refresh the server configuration schema and generate a new upgrade folder.
      */
diff --git a/opendj-server-legacy/src/messages/org/opends/messages/tool.properties b/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
index 5be737e..e5af19e 100644
--- a/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
+++ b/opendj-server-legacy/src/messages/org/opends/messages/tool.properties
@@ -2539,6 +2539,8 @@
 ERR_LDIFIMPORT_LDIF_FILE_DOESNT_EXIST_10055=Unable to access the LDIF file %s to import. Please check that the file is \
   local to the server and the path correct.
 INFO_UPGRADE_TASK_BCRYPT_SCHEME_SUMMARY_10056=Adding Bcrypt password storage scheme configuration
+INFO_UPGRADE_TASK_CONFIGURATION_BACKEND_NOT_CONFIGURABLE_10057=Removing config entry \
+ for the non-configurable configuration backend
 
 # Strings for generated reference documentation.
 REF_SHORT_DESC_BACKUP_15000=back up OpenDJ directory data

--
Gitblit v1.10.0