From 019158fc70a39418454962d9ec15f54feacea231 Mon Sep 17 00:00:00 2001
From: neil_a_wilson <neil_a_wilson@localhost>
Date: Sun, 24 Jun 2007 00:55:50 +0000
Subject: [PATCH] Migrate the root DN configuration to the admin framework.

---
 opends/src/server/org/opends/server/core/RootDNConfigManager.java |  943 ++++++++++++----------------------------------------------
 1 files changed, 198 insertions(+), 745 deletions(-)

diff --git a/opends/src/server/org/opends/server/core/RootDNConfigManager.java b/opends/src/server/org/opends/server/core/RootDNConfigManager.java
index 1c11aef..3b4da18 100644
--- a/opends/src/server/org/opends/server/core/RootDNConfigManager.java
+++ b/opends/src/server/org/opends/server/core/RootDNConfigManager.java
@@ -29,73 +29,49 @@
 
 
 import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedHashSet;
-import java.util.LinkedList;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 
-import org.opends.server.api.ConfigAddListener;
-import org.opends.server.api.ConfigChangeListener;
-import org.opends.server.api.ConfigDeleteListener;
-import org.opends.server.api.ConfigHandler;
-import org.opends.server.api.ConfigurableComponent;
-import org.opends.server.config.ConfigAttribute;
-import org.opends.server.config.ConfigEntry;
+import org.opends.server.admin.server.ConfigurationAddListener;
+import org.opends.server.admin.server.ConfigurationChangeListener;
+import org.opends.server.admin.server.ConfigurationDeleteListener;
+import org.opends.server.admin.std.server.RootCfg;
+import org.opends.server.admin.std.server.RootDNCfg;
+import org.opends.server.admin.std.server.RootDNUserCfg;
+import org.opends.server.admin.server.ServerManagementContext;
 import org.opends.server.config.ConfigException;
-import org.opends.server.config.DNConfigAttribute;
-import org.opends.server.config.MultiChoiceConfigAttribute;
 import org.opends.server.types.ConfigChangeResult;
 import org.opends.server.types.DirectoryException;
 import org.opends.server.types.DN;
-import org.opends.server.types.ErrorLogCategory;
-import org.opends.server.types.ErrorLogSeverity;
 import org.opends.server.types.InitializationException;
 import org.opends.server.types.Privilege;
 import org.opends.server.types.ResultCode;
 
-import static org.opends.server.config.ConfigConstants.*;
-import org.opends.server.types.DebugLogLevel;
-import static org.opends.server.loggers.ErrorLogger.*;
-import static org.opends.server.loggers.debug.DebugLogger.*;
-import org.opends.server.loggers.debug.DebugTracer;
 import static org.opends.server.messages.ConfigMessages.*;
 import static org.opends.server.messages.MessageHandler.*;
-import static org.opends.server.util.ServerConstants.*;
-import static org.opends.server.util.StaticUtils.*;
 
 
 
 /**
- * This class defines a utility that will be used to manage the set of root DNs
- * defined in the Directory Server.  The root DN accounts will exist below
- * "cn=Root DNs,cn=config" and must have the ds-cfg-root-dn objectclass.  They
- * may optionally have a ds-cfg-bind-dn that may be used to provide an alternate
- * DN for use when binding to the server.
+ * This class defines a utility that will be used to manage the set of root
+ * users defined in the Directory Server.  It will handle both the
+ * "cn=Root DNs,cn=config" entry itself (through the root privilege change
+ * listener), and all of its children.
  */
 public class RootDNConfigManager
-       implements ConfigChangeListener, ConfigAddListener, ConfigDeleteListener,
-                  ConfigurableComponent
+       implements ConfigurationChangeListener<RootDNUserCfg>,
+                  ConfigurationAddListener<RootDNUserCfg>,
+                  ConfigurationDeleteListener<RootDNUserCfg>
+
 {
-  /**
-   * The tracer object for the debug logger.
-   */
-  private static final DebugTracer TRACER = getTracer();
+  // A mapping between the actual root DNs and their alternate bind DNs.
+  private ConcurrentHashMap<DN,HashSet<DN>> alternateBindDNs;
 
-
-
-
-  // A mapping between each root DN user entry and a list of the alternate
-  // bind DNs for that user.
-  private ConcurrentHashMap<DN,List<DN>> bindMappings;
-
-  // The DN of the entry that serves as the base for the root DN
-  // configuration entries.
-  private DN rootDNConfigBaseDN;
-
-  // The set of privileges that will be automatically inherited by root users.
-  private LinkedHashSet<Privilege> rootPrivileges;
+  // The root privilege change listener that will handle changes to the
+  // "cn=Root DNs,cn=config" entry itself.
+  private RootPrivilegeChangeListener rootPrivilegeChangeListener;
 
 
 
@@ -104,560 +80,197 @@
    */
   public RootDNConfigManager()
   {
-    bindMappings = new ConcurrentHashMap<DN,List<DN>>();
+    alternateBindDNs = new ConcurrentHashMap<DN,HashSet<DN>>();
+    rootPrivilegeChangeListener = new RootPrivilegeChangeListener();
   }
 
 
 
   /**
-   * Initializes all root DNs currently defined in the Directory Server
-   * configuration.  This should only be called at Directory Server startup.
+   * Initializes all of the root users currently defined in the Directory Server
+   * configuration, as well as the set of privileges that root users will
+   * inherit by default.
    *
-   * @throws  ConfigException  If a configuration problem causes the root DN
-   *                           initialization process to fail.
+   * @throws  ConfigException  If a configuration problem causes the identity
+   *                           mapper initialization process to fail.
    *
    * @throws  InitializationException  If a problem occurs while initializing
-   *                                   the root DNs that is not related to the
-   *                                   server configuration.
+   *                                   the identity mappers that is not related
+   *                                   to the server configuration.
    */
   public void initializeRootDNs()
          throws ConfigException, InitializationException
   {
-    // First, get the base configuration entry for the root DNs.
-    ConfigHandler configHandler = DirectoryServer.getConfigHandler();
-    ConfigEntry   baseEntry;
-    try
+    // Get the root configuration object.
+    ServerManagementContext managementContext =
+         ServerManagementContext.getInstance();
+    RootCfg rootConfiguration =
+         managementContext.getRootConfiguration();
+
+
+    // Get the root DN configuration object, use it to set the default root
+    // privileges, and register a change listener for it.
+    RootDNCfg rootDNCfg = rootConfiguration.getRootDN();
+    rootPrivilegeChangeListener.setDefaultRootPrivileges(rootDNCfg);
+    rootDNCfg.addChangeListener(rootPrivilegeChangeListener);
+
+
+    // Register as an add and delete listener for new root DN users.
+    rootDNCfg.addRootDNUserAddListener(this);
+    rootDNCfg.addRootDNUserDeleteListener(this);
+
+
+    // Get the set of root users defined below "cn=Root DNs,cn=config".  For
+    // each one, register as a change listener, and get the set of alternate
+    // bind DNs.
+    for (String name : rootDNCfg.listRootDNUsers())
     {
-      rootDNConfigBaseDN = DN.decode(DN_ROOT_DN_CONFIG_BASE);
-      baseEntry = configHandler.getConfigEntry(rootDNConfigBaseDN);
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
+      RootDNUserCfg rootUserCfg = rootDNCfg.getRootDNUser(name);
+      rootUserCfg.addChangeListener(this);
+      DirectoryServer.registerRootDN(rootUserCfg.dn());
+
+      HashSet<DN> altBindDNs = new HashSet<DN>();
+      for (DN alternateBindDN : rootUserCfg.getAlternateBindDN())
       {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      int    msgID   = MSGID_CONFIG_ROOTDN_CANNOT_GET_BASE;
-      String message = getMessage(msgID, String.valueOf(e));
-      throw new ConfigException(msgID, message, e);
-    }
-
-    if (baseEntry == null)
-    {
-      int    msgID   = MSGID_CONFIG_ROOTDN_BASE_DOES_NOT_EXIST;
-      String message = getMessage(msgID);
-      throw new ConfigException(msgID, message);
-    }
-
-
-    // Get the set of privileges that root users should have by default.
-    rootPrivileges = new LinkedHashSet<Privilege>(
-                              Privilege.getDefaultRootPrivileges());
-
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
-    MultiChoiceConfigAttribute rootPrivStub =
-         new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                        getMessage(msgID), false, true, false,
-                                        Privilege.getPrivilegeNames());
-    try
-    {
-      MultiChoiceConfigAttribute rootPrivAttr =
-           (MultiChoiceConfigAttribute)
-           baseEntry.getConfigAttribute(rootPrivStub);
-      if (rootPrivAttr != null)
-      {
-        ArrayList<Privilege> privList = new ArrayList<Privilege>();
-        for (String value : rootPrivAttr.activeValues())
+        try
         {
-          String privName = toLowerCase(value);
-          Privilege p = Privilege.privilegeForName(privName);
-          if (p == null)
-          {
-            msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
-            String message = getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                        String.valueOf(rootDNConfigBaseDN),
-                                        String.valueOf(value));
-            logError(ErrorLogCategory.CONFIGURATION,
-                     ErrorLogSeverity.SEVERE_WARNING, message, msgID);
-          }
-          else
-          {
-            privList.add(p);
-          }
+          altBindDNs.add(alternateBindDN);
+          DirectoryServer.registerAlternateRootDN(rootUserCfg.dn(),
+                                                  alternateBindDN);
         }
-
-        rootPrivileges = new LinkedHashSet<Privilege>(privList);
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
-      String message = getMessage(msgID, getExceptionMessage(e));
-      throw new InitializationException(msgID, message, e);
-    }
-
-
-    // Register with the configuration base entry as an add and delete listener.
-    // So that we will be notified of attempts to create or remove root DN
-    // entries.  Also, register with the server as a configurable component so
-    // that we can detect and apply any changes to the root
-    baseEntry.registerAddListener(this);
-    baseEntry.registerDeleteListener(this);
-    DirectoryServer.registerConfigurableComponent(this);
-
-
-    // See if the base entry has any children.  If not, then we don't need to
-    // do anything else.
-    if (! baseEntry.hasChildren())
-    {
-      return;
-    }
-
-
-    // Iterate through the child entries and process them as root DN entries.
-    for (ConfigEntry childEntry : baseEntry.getChildren().values())
-    {
-      StringBuilder unacceptableReason = new StringBuilder();
-      if (! configAddIsAcceptable(childEntry, unacceptableReason))
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_ROOTDN_ENTRY_UNACCEPTABLE,
-                 String.valueOf(childEntry.getDN()),
-                 unacceptableReason.toString());
-        continue;
-      }
-
-      try
-      {
-        ConfigChangeResult result = applyConfigurationAdd(childEntry);
-        if (result.getResultCode() != ResultCode.SUCCESS)
+        catch (DirectoryException de)
         {
-          StringBuilder buffer = new StringBuilder();
-
-          List<String> resultMessages = result.getMessages();
-          if ((resultMessages == null) || (resultMessages.isEmpty()))
-          {
-            buffer.append(getMessage(MSGID_CONFIG_UNKNOWN_UNACCEPTABLE_REASON));
-          }
-          else
-          {
-            Iterator<String> iterator = resultMessages.iterator();
-
-            buffer.append(iterator.next());
-            while (iterator.hasNext())
-            {
-              buffer.append(EOL);
-              buffer.append(iterator.next());
-            }
-          }
-
-          logError(ErrorLogCategory.CONFIGURATION,
-                   ErrorLogSeverity.SEVERE_ERROR,
-                   MSGID_CONFIG_ROOTDN_CANNOT_CREATE,
-                   String.valueOf(childEntry.getDN()), buffer.toString());
+          throw new InitializationException(de.getMessageID(),
+                                            de.getErrorMessage(), de);
         }
       }
-      catch (Exception e)
-      {
-        logError(ErrorLogCategory.CONFIGURATION, ErrorLogSeverity.SEVERE_ERROR,
-                 MSGID_CONFIG_PWGENERATOR_CANNOT_CREATE_GENERATOR,
-                 childEntry.getDN().toString(), String.valueOf(e));
-      }
+
+      alternateBindDNs.put(rootUserCfg.dn(), altBindDNs);
     }
   }
 
 
 
   /**
-   * Retrieves the set of privileges that should automatically be granted to
-   * root users when they authenticate.
+   * Retrieves the set of privileges that will be granted to root users by
+   * default.
    *
-   * @return  The set of privileges that should automatically be granted to root
-   *          users when they authenticate.
+   * @return  The set of privileges that will be granted to root users by
+   *          default.
    */
   public Set<Privilege> getRootPrivileges()
   {
-    return rootPrivileges;
+    return rootPrivilegeChangeListener.getDefaultRootPrivileges();
   }
 
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * modification is acceptable to this change listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested update.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed change is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  public boolean configChangeIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  public boolean isConfigurationAddAcceptable(RootDNUserCfg configuration,
+                                              List<String> unacceptableReasons)
   {
-    // Make sure that the entry has an appropriate objectclass for a root DN.
-    if (! configEntry.hasObjectClass(OC_ROOT_DN))
+    // The new root user must not have an alternate bind DN that is already
+    // in use.
+    boolean configAcceptable = true;
+    for (DN altBindDN : configuration.getAlternateBindDN())
     {
-      int    msgID   = MSGID_CONFIG_ROOTDN_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntry.getDN().toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // See if the entry has any alternate DNs.  If so, then make sure they are
-    // valid.
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN;
-    DNConfigAttribute alternateDNsStub =
-         new DNConfigAttribute(ATTR_ROOTDN_ALTERNATE_BIND_DN, getMessage(msgID),
-                               false, true, false);
-    try
-    {
-      DNConfigAttribute alternateDNsAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(alternateDNsStub);
-
-      if (alternateDNsAttr != null)
+      DN existingRootDN = DirectoryServer.getActualRootBindDN(altBindDN);
+      if (existingRootDN != null)
       {
-        // There were alternate DNs provided, so see if there are any duplicate
-        // values that are already registered for a different root DN.
-        for (DN alternateBindDN : alternateDNsAttr.pendingValues())
-        {
-          DN rootDN = DirectoryServer.getActualRootBindDN(alternateBindDN);
-          if ((rootDN != null) && (! rootDN.equals(configEntry.getDN())))
-          {
-            msgID = MSGID_CONFIG_ROOTDN_CONFLICTING_MAPPING;
-            String message = getMessage(msgID, String.valueOf(alternateBindDN),
-                                        String.valueOf(configEntry.getDN()),
-                                        String.valueOf(rootDN));
-            unacceptableReason.append(message);
-            return false;
-          }
-        }
+        int    msgID   = MSGID_CONFIG_ROOTDN_CONFLICTING_MAPPING;
+        String message = getMessage(msgID, String.valueOf(altBindDN),
+                                    String.valueOf(configuration.dn()),
+                                    String.valueOf(existingRootDN));
+        unacceptableReasons.add(message);
+
+        configAcceptable = false;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
 
-      msgID = MSGID_CONFIG_ROOTDN_CANNOT_PARSE_ALTERNATE_BIND_DNS;
-      String message = getMessage(msgID, String.valueOf(configEntry.getDN()),
-                                  getExceptionMessage(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the root DN entry appears to be acceptable.
-    return true;
+    return configAcceptable;
   }
 
 
 
   /**
-   * Attempts to apply a new configuration to this Directory Server component
-   * based on the provided changed entry.
-   *
-   * @param  configEntry  The configuration entry that containing the updated
-   *                      configuration for this component.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationChange(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationAdd(RootDNUserCfg configuration)
   {
-    DN                configEntryDN       = configEntry.getDN();
+    configuration.addChangeListener(this);
+
     ResultCode        resultCode          = ResultCode.SUCCESS;
     boolean           adminActionRequired = false;
     ArrayList<String> messages            = new ArrayList<String>();
 
-
-    // Get the set of alternate bind DNs for the entry, if there are any.
-    List<DN> alternateBindDNs = null;
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN;
-    DNConfigAttribute alternateDNsStub =
-         new DNConfigAttribute(ATTR_ROOTDN_ALTERNATE_BIND_DN, getMessage(msgID),
-                               false, true, false);
-    try
+    HashSet<DN> altBindDNs = new HashSet<DN>();
+    for (DN altBindDN : configuration.getAlternateBindDN())
     {
-      DNConfigAttribute alternateDNsAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(alternateDNsStub);
-      if (alternateDNsAttr != null)
+      try
       {
-        alternateBindDNs = alternateDNsAttr.activeValues();
+        DirectoryServer.registerAlternateRootDN(configuration.dn(), altBindDN);
+        altBindDNs.add(altBindDN);
+      }
+      catch (DirectoryException de)
+      {
+        // This shouldn't happen, since the set of DNs should have already been
+        // validated.
+        resultCode = DirectoryServer.getServerErrorResultCode();
+        messages.add(de.getErrorMessage());
+
+        for (DN dn : altBindDNs)
+        {
+          DirectoryServer.deregisterAlternateRootBindDN(dn);
+        }
+        break;
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_CANNOT_PARSE_ALTERNATE_BIND_DNS;
-      messages.add(getMessage(msgID, getExceptionMessage(e)));
-
-      resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-    }
-
 
     if (resultCode == ResultCode.SUCCESS)
     {
-      List<DN> existingMappings = bindMappings.get(configEntryDN);
-      if (existingMappings != null)
-      {
-        for (DN mappedDN : existingMappings)
-        {
-          if ((alternateBindDNs == null) ||
-              (! alternateBindDNs.contains(mappedDN)))
-          {
-            DirectoryServer.deregisterAlternateRootBindDN(mappedDN);
-          }
-        }
-      }
-
-      if (alternateBindDNs == null)
-      {
-        alternateBindDNs = new ArrayList<DN>(0);
-      }
-      else
-      {
-        for (DN alternateBindDN : alternateBindDNs)
-        {
-          try
-          {
-            DirectoryServer.registerAlternateRootDN(configEntryDN,
-                                                    alternateBindDN);
-          }
-          catch (DirectoryException de)
-          {
-            if (debugEnabled())
-            {
-              TRACER.debugCaught(DebugLogLevel.ERROR, de);
-            }
-
-            msgID = MSGID_CONFIG_ROOTDN_CANNOT_REGISTER_ALTERNATE_BIND_DN;
-            messages.add(getMessage(msgID, String.valueOf(alternateBindDN),
-                                    String.valueOf(configEntryDN),
-                                    de.getErrorMessage()));
-
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = ResultCode.CONSTRAINT_VIOLATION;
-            }
-          }
-        }
-      }
-
-      bindMappings.put(configEntryDN, alternateBindDNs);
+      DirectoryServer.registerRootDN(configuration.dn());
+      alternateBindDNs.put(configuration.dn(), altBindDNs);
     }
 
-
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
 
 
 
   /**
-   * Indicates whether the configuration entry that will result from a proposed
-   * add is acceptable to this add listener.
-   *
-   * @param  configEntry         The configuration entry that will result from
-   *                             the requested add.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed entry is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry contains an acceptable
-   *          configuration, or <CODE>false</CODE> if it does not.
+   * {@inheritDoc}
    */
-  public boolean configAddIsAcceptable(ConfigEntry configEntry,
-                                       StringBuilder unacceptableReason)
+  public boolean isConfigurationDeleteAcceptable(RootDNUserCfg configuration,
+                      List<String> unacceptableReasons)
   {
-    // Make sure that no entry already exists with the specified DN, and that
-    // there is no other root user with a conflicting alternate bind DN.
-    DN configEntryDN = configEntry.getDN();
-    if (bindMappings.containsKey(configEntryDN) ||
-        (DirectoryServer.getActualRootBindDN(configEntryDN) != null))
-    {
-      int    msgID   = MSGID_CONFIG_ROOTDN_EXISTS;
-      String message = getMessage(msgID, String.valueOf(configEntryDN));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // Make sure that the entry has the root DN objectclass.
-    if (! configEntry.hasObjectClass(OC_ROOT_DN))
-    {
-      int    msgID   = MSGID_CONFIG_ROOTDN_INVALID_OBJECTCLASS;
-      String message = getMessage(msgID, configEntryDN.toString());
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-
-
-    // See if the entry has any alternate DNs.  If so, then make sure they are
-    // valid.
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN;
-    DNConfigAttribute alternateDNsStub =
-         new DNConfigAttribute(ATTR_ROOTDN_ALTERNATE_BIND_DN, getMessage(msgID),
-                               false, true, false);
-    try
-    {
-      DNConfigAttribute alternateDNsAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(alternateDNsStub);
-
-      if (alternateDNsAttr != null)
-      {
-        // There were alternate DNs provided, so see if there are any duplicate
-        // values that are already registered for a different root DN.
-        for (DN alternateBindDN : alternateDNsAttr.pendingValues())
-        {
-          DN rootDN = DirectoryServer.getActualRootBindDN(alternateBindDN);
-          if ((rootDN != null) && (! rootDN.equals(configEntryDN)))
-          {
-            msgID = MSGID_CONFIG_ROOTDN_CONFLICTING_MAPPING;
-            String message = getMessage(msgID, String.valueOf(alternateBindDN),
-                                        String.valueOf(configEntryDN),
-                                        String.valueOf(rootDN));
-            unacceptableReason.append(message);
-            return false;
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_CANNOT_PARSE_ALTERNATE_BIND_DNS;
-      String message = getMessage(msgID, getExceptionMessage(e));
-      unacceptableReason.append(message);
-      return false;
-    }
-
-
-    // If we've gotten here then the root DN entry appears to be acceptable.
     return true;
   }
 
 
 
   /**
-   * Attempts to apply a new configuration based on the provided added entry.
-   *
-   * @param  configEntry  The new configuration entry that contains the
-   *                      configuration to apply.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
+   * {@inheritDoc}
    */
-  public ConfigChangeResult applyConfigurationAdd(ConfigEntry configEntry)
+  public ConfigChangeResult applyConfigurationDelete(
+                                 RootDNUserCfg configuration)
   {
-    DN                configEntryDN       = configEntry.getDN();
+    DirectoryServer.deregisterRootDN(configuration.dn());
+    configuration.removeChangeListener(this);
+
     ResultCode        resultCode          = ResultCode.SUCCESS;
     boolean           adminActionRequired = false;
     ArrayList<String> messages            = new ArrayList<String>();
 
-
-    // Get the set of alternate bind DNs for the entry, if there are any.
-    List<DN> alternateBindDNs = null;
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ALTERNATE_BIND_DN;
-    DNConfigAttribute alternateDNsStub =
-         new DNConfigAttribute(ATTR_ROOTDN_ALTERNATE_BIND_DN, getMessage(msgID),
-                               false, true, false);
-    try
+    HashSet<DN> altBindDNs = alternateBindDNs.remove(configuration.dn());
+    if (altBindDNs != null)
     {
-      DNConfigAttribute alternateDNsAttr =
-           (DNConfigAttribute) configEntry.getConfigAttribute(alternateDNsStub);
-      if (alternateDNsAttr != null)
+      for (DN dn : altBindDNs)
       {
-        alternateBindDNs = alternateDNsAttr.activeValues();
+        DirectoryServer.deregisterAlternateRootBindDN(dn);
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_CANNOT_PARSE_ALTERNATE_BIND_DNS;
-      messages.add(getMessage(msgID, getExceptionMessage(e)));
-
-      resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-    }
-
-
-    if (resultCode == ResultCode.SUCCESS)
-    {
-      List<DN> existingMappings = bindMappings.get(configEntryDN);
-      if (existingMappings != null)
-      {
-        for (DN mappedDN : existingMappings)
-        {
-          if ((alternateBindDNs == null) ||
-              (! alternateBindDNs.contains(mappedDN)))
-          {
-            DirectoryServer.deregisterAlternateRootBindDN(mappedDN);
-          }
-        }
-      }
-
-      if (alternateBindDNs == null)
-      {
-        alternateBindDNs = new ArrayList<DN>(0);
-      }
-      else
-      {
-        for (DN alternateBindDN : alternateBindDNs)
-        {
-          try
-          {
-            DirectoryServer.registerAlternateRootDN(configEntryDN,
-                                                    alternateBindDN);
-          }
-          catch (DirectoryException de)
-          {
-            if (debugEnabled())
-            {
-              TRACER.debugCaught(DebugLogLevel.ERROR, de);
-            }
-
-            msgID = MSGID_CONFIG_ROOTDN_CANNOT_REGISTER_ALTERNATE_BIND_DN;
-            messages.add(getMessage(msgID, String.valueOf(alternateBindDN),
-                                    String.valueOf(configEntryDN)));
-
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = ResultCode.CONSTRAINT_VIOLATION;
-            }
-          }
-        }
-      }
-
-      bindMappings.put(configEntryDN, alternateBindDNs);
-      DirectoryServer.registerRootDN(configEntryDN);
-      configEntry.registerChangeListener(this);
-    }
-
 
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
@@ -665,267 +278,107 @@
 
 
   /**
-   * Indicates whether it is acceptable to remove the provided configuration
-   * entry.
-   *
-   * @param  configEntry         The configuration entry that will be removed
-   *                             from the configuration.
-   * @param  unacceptableReason  A buffer to which this method can append a
-   *                             human-readable message explaining why the
-   *                             proposed delete is not acceptable.
-   *
-   * @return  <CODE>true</CODE> if the proposed entry may be removed from the
-   *          configuration, or <CODE>false</CODE> if not.
+   * {@inheritDoc}
    */
-  public boolean configDeleteIsAcceptable(ConfigEntry configEntry,
-                                          StringBuilder unacceptableReason)
+  public boolean isConfigurationChangeAcceptable(RootDNUserCfg configuration,
+                      List<String> unacceptableReasons)
   {
-    // A delete should always be acceptable, so just return true.
-    return true;
-  }
+    boolean configAcceptable = true;
 
-
-
-  /**
-   * Attempts to apply a new configuration based on the provided deleted entry.
-   *
-   * @param  configEntry  The new configuration entry that has been deleted.
-   *
-   * @return  Information about the result of processing the configuration
-   *          change.
-   */
-  public ConfigChangeResult applyConfigurationDelete(ConfigEntry configEntry)
-  {
-    DN         configEntryDN       = configEntry.getDN();
-    ResultCode resultCode          = ResultCode.SUCCESS;
-    boolean    adminActionRequired = false;
-
-
-    // See if the entry is registered as a root DN.  If so, then deregister it
-    // and any alternate bind DNs that it might have.
-    List<DN> alternateBindDNs = bindMappings.remove(configEntryDN);
-    if (alternateBindDNs != null)
+    // There must not be any new alternate bind DNs that are already in use by
+    // other root users.
+    for (DN altBindDN: configuration.getAlternateBindDN())
     {
-      for (DN alternateBindDN : alternateBindDNs)
+      DN existingRootDN = DirectoryServer.getActualRootBindDN(altBindDN);
+      if ((existingRootDN != null) &&
+          (! existingRootDN.equals(configuration.dn())))
       {
-        DirectoryServer.deregisterAlternateRootBindDN(alternateBindDN);
+        int    msgID   = MSGID_CONFIG_ROOTDN_CONFLICTING_MAPPING;
+        String message = getMessage(msgID, String.valueOf(altBindDN),
+                                    String.valueOf(configuration.dn()),
+                                    String.valueOf(existingRootDN));
+        unacceptableReasons.add(message);
+
+        configAcceptable = false;
       }
     }
 
-
-    return new ConfigChangeResult(resultCode, adminActionRequired);
+    return configAcceptable;
   }
 
 
 
   /**
-   * Retrieves the DN of the configuration entry with which this
-   * component is associated.
-   *
-   * @return  The DN of the configuration entry with which this
-   *          component is associated.
+   * {@inheritDoc}
    */
-  public DN getConfigurableComponentEntryDN()
-  {
-    return rootDNConfigBaseDN;
-  }
-
-
-
-  /**
-   * Retrieves the set of configuration attributes that are associated
-   * with this configurable component.
-   *
-   * @return  The set of configuration attributes that are associated
-   *          with this configurable component.
-   */
-  public List<ConfigAttribute> getConfigurationAttributes()
-  {
-    LinkedList<ConfigAttribute> attrList = new LinkedList<ConfigAttribute>();
-
-    LinkedList<String> currentValues = new LinkedList<String>();
-    for (Privilege p : rootPrivileges)
-    {
-      currentValues.add(p.getName());
-    }
-
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
-    attrList.add(new MultiChoiceConfigAttribute(
-                          ATTR_DEFAULT_ROOT_PRIVILEGE_NAME, getMessage(msgID),
-                          false, true, false, Privilege.getPrivilegeNames(),
-                          currentValues));
-
-    return attrList;
-  }
-
-
-
-  /**
-   * Indicates whether the provided configuration entry has an
-   * acceptable configuration for this component.  If it does not,
-   * then detailed information about the problem(s) should be added to
-   * the provided list.
-   *
-   * @param  configEntry          The configuration entry for which to
-   *                              make the determination.
-   * @param  unacceptableReasons  A list that can be used to hold
-   *                              messages about why the provided
-   *                              entry does not have an acceptable
-   *                              configuration.
-   *
-   * @return  <CODE>true</CODE> if the provided entry has an
-   *          acceptable configuration for this component, or
-   *          <CODE>false</CODE> if not.
-   */
-  public boolean hasAcceptableConfiguration(ConfigEntry configEntry,
-                                            List<String> unacceptableReasons)
-  {
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
-    MultiChoiceConfigAttribute rootPrivStub =
-         new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                        getMessage(msgID), false, true, false,
-                                        Privilege.getPrivilegeNames());
-    try
-    {
-      MultiChoiceConfigAttribute rootPrivAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(rootPrivStub);
-      if (rootPrivAttr != null)
-      {
-        for (String value : rootPrivAttr.activeValues())
-        {
-          String privName = toLowerCase(value);
-          Privilege p = Privilege.privilegeForName(privName);
-          if (p == null)
-          {
-            msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
-            String message = getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                        String.valueOf(rootDNConfigBaseDN),
-                                        String.valueOf(value));
-            unacceptableReasons.add(message);
-            return false;
-          }
-        }
-      }
-    }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
-      String message = getMessage(msgID, getExceptionMessage(e));
-      unacceptableReasons.add(message);
-      return false;
-    }
-
-
-    // If we've gotten here, then everything looks OK.
-    return true;
-  }
-
-
-
-  /**
-   * Makes a best-effort attempt to apply the configuration contained
-   * in the provided entry.  Information about the result of this
-   * processing should be added to the provided message list.
-   * Information should always be added to this list if a
-   * configuration change could not be applied.  If detailed results
-   * are requested, then information about the changes applied
-   * successfully (and optionally about parameters that were not
-   * changed) should also be included.
-   *
-   * @param  configEntry      The entry containing the new
-   *                          configuration to apply for this
-   *                          component.
-   * @param  detailedResults  Indicates whether detailed information
-   *                          about the processing should be added to
-   *                          the list.
-   *
-   * @return  Information about the result of the configuration
-   *          update.
-   */
-  public ConfigChangeResult applyNewConfiguration(ConfigEntry configEntry,
-                                                  boolean detailedResults)
+  public ConfigChangeResult applyConfigurationChange(
+                                 RootDNUserCfg configuration)
   {
     ResultCode        resultCode          = ResultCode.SUCCESS;
-    ArrayList<String> messages            = new ArrayList<String>();
     boolean           adminActionRequired = false;
+    ArrayList<String> messages            = new ArrayList<String>();
 
+    HashSet<DN> setDNs = new HashSet<DN>();
+    HashSet<DN> addDNs = new HashSet<DN>();
+    HashSet<DN> delDNs =
+         new HashSet<DN>(alternateBindDNs.get(configuration.dn()));
 
-    LinkedHashSet<Privilege> newRootPrivileges =
-         new LinkedHashSet<Privilege>(Privilege.getDefaultRootPrivileges());
-
-    int msgID = MSGID_CONFIG_ROOTDN_DESCRIPTION_ROOT_PRIVILEGE;
-    MultiChoiceConfigAttribute rootPrivStub =
-         new MultiChoiceConfigAttribute(ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                        getMessage(msgID), false, true, false,
-                                        Privilege.getPrivilegeNames());
-    try
+    for (DN altBindDN : configuration.getAlternateBindDN())
     {
-      MultiChoiceConfigAttribute rootPrivAttr =
-           (MultiChoiceConfigAttribute)
-           configEntry.getConfigAttribute(rootPrivStub);
-      if (rootPrivAttr != null)
-      {
-        ArrayList<Privilege> privList = new ArrayList<Privilege>();
-        for (String value : rootPrivAttr.activeValues())
-        {
-          String privName = toLowerCase(value);
-          Privilege p = Privilege.privilegeForName(privName);
-          if (p == null)
-          {
-            if (resultCode == ResultCode.SUCCESS)
-            {
-              resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-            }
+      setDNs.add(altBindDN);
 
-            msgID = MSGID_CONFIG_ROOTDN_UNRECOGNIZED_PRIVILEGE;
-            messages.add(getMessage(msgID, ATTR_DEFAULT_ROOT_PRIVILEGE_NAME,
-                                    String.valueOf(rootDNConfigBaseDN),
-                                    String.valueOf(value)));
-          }
-          else
-          {
-            privList.add(p);
-          }
+      if (! delDNs.remove(altBindDN))
+      {
+        addDNs.add(altBindDN);
+      }
+    }
+
+    for (DN dn : delDNs)
+    {
+      DirectoryServer.deregisterAlternateRootBindDN(dn);
+    }
+
+    HashSet<DN> addedDNs = new HashSet<DN>(addDNs.size());
+    for (DN dn : addDNs)
+    {
+      try
+      {
+        DirectoryServer.registerAlternateRootDN(configuration.dn(), dn);
+        addedDNs.add(dn);
+      }
+      catch (DirectoryException de)
+      {
+        // This shouldn't happen, since the set of DNs should have already been
+        // validated.
+        resultCode = DirectoryServer.getServerErrorResultCode();
+        messages.add(de.getErrorMessage());
+
+        for (DN addedDN : addedDNs)
+        {
+          DirectoryServer.deregisterAlternateRootBindDN(addedDN);
         }
 
-        newRootPrivileges = new LinkedHashSet<Privilege>(privList);
+        for (DN deletedDN : delDNs)
+        {
+          try
+          {
+            DirectoryServer.registerAlternateRootDN(configuration.dn(),
+                                                    deletedDN);
+          }
+          catch (Exception e)
+          {
+            // This should also never happen.
+            alternateBindDNs.get(configuration.dn()).remove(deletedDN);
+          }
+        }
       }
     }
-    catch (Exception e)
-    {
-      if (debugEnabled())
-      {
-        TRACER.debugCaught(DebugLogLevel.ERROR, e);
-      }
-
-      if (resultCode == ResultCode.SUCCESS)
-      {
-        resultCode = ResultCode.INVALID_ATTRIBUTE_SYNTAX;
-      }
-
-      msgID = MSGID_CONFIG_ROOTDN_ERROR_DETERMINING_ROOT_PRIVILEGES;
-      messages.add(getMessage(msgID, getExceptionMessage(e)));
-    }
-
 
     if (resultCode == ResultCode.SUCCESS)
     {
-      rootPrivileges = newRootPrivileges;
-
-      if (detailedResults)
-      {
-        msgID = MSGID_CONFIG_ROOTDN_UPDATED_PRIVILEGES;
-        messages.add(getMessage(msgID));
-      }
+      alternateBindDNs.put(configuration.dn(), setDNs);
     }
 
-
     return new ConfigChangeResult(resultCode, adminActionRequired, messages);
   }
 }

--
Gitblit v1.10.0