/** {@inheritDoc} */
  public ConfigChangeResult applyConfigurationChange(RootDNUserCfg configuration) {
    ResultCode resultCode = ResultCode.SUCCESS;
    boolean adminActionRequired = false;
    ArrayList<Message> messages = new ArrayList<Message>();

    HashSet<DN> setDNs = new HashSet<DN>();
    HashSet<DN> addDNs = new HashSet<DN>();
    HashSet<DN> delDNs = new HashSet<DN>(alternateBindDNs.get(configuration.dn()));

    for (DN altBindDN : configuration.getAlternateBindDN()) {
      setDNs.add(altBindDN);

      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.getMessageObject());

        for (DN addedDN : addedDNs) {
          DirectoryServer.deregisterAlternateRootBindDN(addedDN);
        }

        for (DN deletedDN : delDNs) {
          try {
            DirectoryServer.registerAlternateRootDN(configuration.dn(), deletedDN);
          } catch (Exception e) {
            // This should also never happen.
            alternateBindDNs.get(configuration.dn()).remove(deletedDN);
          }
        }
      }
    }

    if (resultCode == ResultCode.SUCCESS) {
      alternateBindDNs.put(configuration.dn(), setDNs);
    }

    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
  /** {@inheritDoc} */
  public ConfigChangeResult applyConfigurationAdd(RootDNUserCfg configuration) {
    configuration.addChangeListener(this);

    ResultCode resultCode = ResultCode.SUCCESS;
    boolean adminActionRequired = false;
    ArrayList<Message> messages = new ArrayList<Message>();

    HashSet<DN> altBindDNs = new HashSet<DN>();
    for (DN altBindDN : configuration.getAlternateBindDN()) {
      try {
        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.getMessageObject());

        for (DN dn : altBindDNs) {
          DirectoryServer.deregisterAlternateRootBindDN(dn);
        }
        break;
      }
    }

    if (resultCode == ResultCode.SUCCESS) {
      DirectoryServer.registerRootDN(configuration.dn());
      alternateBindDNs.put(configuration.dn(), altBindDNs);
    }

    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }
  /** {@inheritDoc} */
  public ConfigChangeResult applyConfigurationDelete(RootDNUserCfg configuration) {
    DirectoryServer.deregisterRootDN(configuration.dn());
    configuration.removeChangeListener(this);

    ResultCode resultCode = ResultCode.SUCCESS;
    boolean adminActionRequired = false;
    ArrayList<Message> messages = new ArrayList<Message>();

    HashSet<DN> altBindDNs = alternateBindDNs.remove(configuration.dn());
    if (altBindDNs != null) {
      for (DN dn : altBindDNs) {
        DirectoryServer.deregisterAlternateRootBindDN(dn);
      }
    }

    return new ConfigChangeResult(resultCode, adminActionRequired, messages);
  }