mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

Jean-Noël Rouvignac
05.25.2016 79456ab528b185983884c14443e0fe64425874da
Partial OPENDJ-2625 Convert all code that uses JNDI to use the SDK instead

Started to convert dsreplication over using the SDK connections
7 files modified
921 ■■■■ changed files
opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java 26 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/ServerDescriptor.java 663 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/SuffixDescriptor.java 21 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionUtils.java 81 ●●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java 49 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/quicksetup/util/Utils.java 67 ●●●● patch | view | raw | blame | history
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java 14 ●●●● patch | view | raw | blame | history
opendj-cli/src/main/java/com/forgerock/opendj/cli/Utils.java
@@ -46,6 +46,8 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.LocalizableMessageDescriptor;
import org.forgerock.opendj.ldap.AuthorizationException;
import org.forgerock.opendj.ldap.ConnectionException;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.RDN;
@@ -465,6 +467,30 @@
    }
    /**
     * Returns a message object for the given IOException.
     *
     * @param e
     *            The IOException.
     * @param hostPort
     *            The hostPort representation of the server we were contacting when the IOException occurred.
     * @return A message object for the given IOException.
     */
    public static LocalizableMessage getMessageForException(IOException e, String hostPort) {
        String arg = e.getLocalizedMessage();
        if (Utils.isCertificateException(e)) {
            return INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(hostPort, arg);
        } else if (e instanceof org.forgerock.opendj.ldap.AuthenticationException) {
            return INFO_CANNOT_CONNECT_TO_REMOTE_AUTHENTICATION.get(hostPort, arg);
        } else if (e instanceof AuthorizationException) {
            return INFO_CANNOT_CONNECT_TO_REMOTE_PERMISSIONS.get(hostPort, arg);
        } else if (e instanceof ConnectionException) {
            return ERR_CANNOT_CONNECT_TO_REMOTE_COMMUNICATION.get(hostPort, arg);
        } else {
            return INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(hostPort, arg);
        }
    }
    /**
     * Returns a localized message for a given properties key an throwable.
     *
     * @param message
opendj-server-legacy/src/main/java/org/opends/admin/ads/ServerDescriptor.java
@@ -16,9 +16,12 @@
 */
package org.opends.admin.ads;
import static org.forgerock.opendj.ldap.SearchScope.*;
import static org.forgerock.opendj.ldap.requests.Requests.*;
import static org.opends.admin.ads.util.ConnectionUtils.*;
import static org.opends.quicksetup.util.Utils.*;
import static org.opends.server.util.CollectionUtils.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
@@ -27,21 +30,19 @@
import java.util.Map;
import java.util.Set;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.Attributes;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.Attribute;
import org.forgerock.opendj.ldap.Connection;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.LdapException;
import org.forgerock.opendj.ldap.ResultCode;
import org.forgerock.opendj.ldap.requests.AddRequest;
import org.forgerock.opendj.ldap.requests.SearchRequest;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.forgerock.opendj.ldif.ConnectionEntryReader;
import org.opends.admin.ads.util.ConnectionWrapper;
import org.opends.quicksetup.Constants;
import org.opends.server.config.ConfigConstants;
@@ -179,8 +180,7 @@
   */
  public boolean isReplicationEnabled()
  {
    return Boolean.TRUE.equals(
        serverProperties.get(ServerProperty.IS_REPLICATION_ENABLED));
    return Boolean.TRUE.equals(serverProperties.get(ServerProperty.IS_REPLICATION_ENABLED));
  }
  /**
@@ -193,11 +193,7 @@
   */
  public String getReplicationServerHostPort()
  {
    if (isReplicationServer())
    {
      return getReplicationServer(getHostName(), getReplicationServerPort());
    }
    return null;
    return isReplicationServer() ? getReplicationServer(getHostName(), getReplicationServerPort()) : null;
  }
  /**
@@ -208,11 +204,7 @@
   */
  public int getReplicationServerId()
  {
    if (isReplicationServer())
    {
      return (Integer) serverProperties.get(ServerProperty.REPLICATION_SERVER_ID);
    }
    return -1;
    return isReplicationServer() ? (Integer) serverProperties.get(ServerProperty.REPLICATION_SERVER_ID) : -1;
  }
  /**
@@ -223,12 +215,7 @@
   */
  public int getReplicationServerPort()
  {
    if (isReplicationServer())
    {
      return (Integer) serverProperties.get(
          ServerProperty.REPLICATION_SERVER_PORT);
    }
    return -1;
    return isReplicationServer() ? (Integer) serverProperties.get(ServerProperty.REPLICATION_SERVER_PORT) : -1;
  }
  /**
@@ -413,20 +400,15 @@
  private ADSContext.ServerProperty getPortProperty(ADSContext.ServerProperty prop)
  {
    if (prop == ADSContext.ServerProperty.ADMIN_ENABLED)
    switch (prop)
    {
    case ADMIN_ENABLED:
      return ADSContext.ServerProperty.ADMIN_PORT;
    }
    else if (prop == ADSContext.ServerProperty.LDAPS_ENABLED)
    {
    case LDAPS_ENABLED:
      return ADSContext.ServerProperty.LDAPS_PORT;
    }
    else if (prop == ADSContext.ServerProperty.LDAP_ENABLED)
    {
    case LDAP_ENABLED:
      return ADSContext.ServerProperty.LDAP_PORT;
    }
    else
    {
    default:
      throw new IllegalStateException("Unexpected prop: "+prop);
    }
  }
@@ -639,10 +621,9 @@
   * @param filter the topology cache filter describing the information that
   * must be retrieved.
   * @return a ServerDescriptor object that corresponds to the read configuration.
   * @throws NamingException if a problem occurred reading the server configuration.
   * @throws IOException if a problem occurred reading the server configuration.
   */
  public static ServerDescriptor createStandalone(ConnectionWrapper conn, TopologyCacheFilter filter)
  throws NamingException
  public static ServerDescriptor createStandalone(ConnectionWrapper conn, TopologyCacheFilter filter) throws IOException
  {
    ServerDescriptor desc = new ServerDescriptor();
@@ -660,26 +641,18 @@
  }
  private static void updateLdapConfiguration(ServerDescriptor desc, ConnectionWrapper conn)
      throws NamingException
      throws IOException
  {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
    String filter = "(objectclass=ds-cfg-ldap-connection-handler)";
    SearchRequest request = newSearchRequest("cn=config", WHOLE_SUBTREE, filter,
            "ds-cfg-enabled",
            "ds-cfg-listen-address",
            "ds-cfg-listen-port",
            "ds-cfg-use-ssl",
            "ds-cfg-allow-start-tls",
            "objectclass"
        });
    String filter = "(objectclass=ds-cfg-ldap-connection-handler)";
    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> listeners =
      conn.getLdapContext().search(jndiName, filter, ctls);
    try
        "objectclass");
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      ArrayList<Integer> ldapPorts = new ArrayList<>();
      ArrayList<Integer> ldapsPorts = new ArrayList<>();
@@ -691,22 +664,15 @@
      desc.serverProperties.put(ServerProperty.LDAPS_PORT, ldapsPorts);
      desc.serverProperties.put(ServerProperty.LDAP_ENABLED, ldapEnabled);
      desc.serverProperties.put(ServerProperty.LDAPS_ENABLED, ldapsEnabled);
      desc.serverProperties.put(ServerProperty.STARTTLS_ENABLED,
          startTLSEnabled);
      desc.serverProperties.put(ServerProperty.STARTTLS_ENABLED, startTLSEnabled);
      while(listeners.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = listeners.next();
        SearchResultEntry sr = entryReader.readEntry();
        String port = getFirstValue(sr, "ds-cfg-listen-port");
        boolean isSecure = "true".equalsIgnoreCase(
            getFirstValue(sr, "ds-cfg-use-ssl"));
        boolean enabled = "true".equalsIgnoreCase(
            getFirstValue(sr, "ds-cfg-enabled"));
        final Integer portNumber = Integer.valueOf(port);
        if (isSecure)
        Integer portNumber = asInteger(sr, "ds-cfg-listen-port");
        boolean enabled = asBoolean(sr, "ds-cfg-enabled");
        if (asBoolean(sr, "ds-cfg-use-ssl"))
        {
          ldapsPorts.add(portNumber);
          ldapsEnabled.add(enabled);
@@ -715,44 +681,20 @@
        {
          ldapPorts.add(portNumber);
          ldapEnabled.add(enabled);
          enabled = "true".equalsIgnoreCase(
              getFirstValue(sr, "ds-cfg-allow-start-tls"));
          startTLSEnabled.add(enabled);
          startTLSEnabled.add(asBoolean(sr, "ds-cfg-allow-start-tls"));
        }
      }
    }
    finally
    {
      listeners.close();
    }
  }
  private static void updateAdminConnectorConfiguration(ServerDescriptor desc, ConnectionWrapper conn)
      throws NamingException
      throws IOException
  {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            "ds-cfg-listen-port",
            "objectclass"
        });
    String filter = "(objectclass=ds-cfg-administration-connector)";
    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> listeners =
      conn.getLdapContext().search(jndiName, filter, ctls);
    try
    {
      Integer adminConnectorPort = null;
      // we should have a single administration connector
      while (listeners.hasMore()) {
        SearchResult sr = listeners.next();
        String port = getFirstValue(sr, "ds-cfg-listen-port");
        adminConnectorPort = Integer.valueOf(port);
      }
    SearchRequest request = newSearchRequest(
        "cn=config", WHOLE_SUBTREE, "(objectclass=ds-cfg-administration-connector)",
        "ds-cfg-listen-port", "objectclass");
    SearchResultEntry sr = conn.getConnection().searchSingleEntry(request);
    Integer adminConnectorPort = asInteger(sr, "ds-cfg-listen-port");
      // Even if we have a single port, use an array to be consistent with
      // other protocols.
@@ -766,30 +708,9 @@
      desc.serverProperties.put(ServerProperty.ADMIN_PORT, adminPorts);
      desc.serverProperties.put(ServerProperty.ADMIN_ENABLED, adminEnabled);
    }
    finally
  private static void updateJmxConfiguration(ServerDescriptor desc, ConnectionWrapper conn) throws IOException
    {
      listeners.close();
    }
  }
  private static void updateJmxConfiguration(ServerDescriptor desc, ConnectionWrapper conn) throws NamingException
  {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            "ds-cfg-enabled",
            "ds-cfg-listen-address",
            "ds-cfg-listen-port",
            "ds-cfg-use-ssl",
            "objectclass"
        });
    String filter = "(objectclass=ds-cfg-jmx-connection-handler)";
    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> listeners =
      conn.getLdapContext().search(jndiName, filter, ctls);
    ArrayList<Integer> jmxPorts = new ArrayList<>();
    ArrayList<Integer> jmxsPorts = new ArrayList<>();
    ArrayList<Boolean> jmxEnabled = new ArrayList<>();
@@ -800,21 +721,22 @@
    desc.serverProperties.put(ServerProperty.JMX_ENABLED, jmxEnabled);
    desc.serverProperties.put(ServerProperty.JMXS_ENABLED, jmxsEnabled);
    try
    String filter = "(objectclass=ds-cfg-jmx-connection-handler)";
    SearchRequest request = newSearchRequest("cn=config", WHOLE_SUBTREE, filter,
        "ds-cfg-enabled",
        "ds-cfg-listen-address",
        "ds-cfg-listen-port",
        "ds-cfg-use-ssl",
        "objectclass");
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      while(listeners.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = listeners.next();
        SearchResultEntry sr = entryReader.readEntry();
        String port = getFirstValue(sr, "ds-cfg-listen-port");
        boolean isSecure = "true".equalsIgnoreCase(
            getFirstValue(sr, "ds-cfg-use-ssl"));
        boolean enabled = "true".equalsIgnoreCase(
            getFirstValue(sr, "ds-cfg-enabled"));
        Integer portNumber = Integer.valueOf(port);
        if (isSecure)
        Integer portNumber = asInteger(sr, "ds-cfg-listen-port");
        boolean enabled = asBoolean(sr, "ds-cfg-enabled");
        if (asBoolean(sr, "ds-cfg-use-ssl"))
        {
          jmxsPorts.add(portNumber);
          jmxsEnabled.add(enabled);
@@ -826,45 +748,30 @@
        }
      }
    }
    finally
    {
      listeners.close();
    }
  }
  private static void updateReplicas(ServerDescriptor desc,
      ConnectionWrapper conn, TopologyCacheFilter cacheFilter)
  throws NamingException
  private static void updateReplicas(ServerDescriptor desc, ConnectionWrapper conn, TopologyCacheFilter cacheFilter)
      throws IOException
  {
    if (!cacheFilter.searchBaseDNInformation())
    {
      return;
    }
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
    SearchRequest request = newSearchRequest("cn=config", WHOLE_SUBTREE, "(objectclass=ds-cfg-backend)",
            "ds-cfg-base-dn",
            "ds-cfg-backend-id",
            ConfigConstants.ATTR_OBJECTCLASS
        });
    String filter = "(objectclass=ds-cfg-backend)";
    LdapName jndiName = new LdapName("cn=config");
    NamingEnumeration<SearchResult> databases =
      conn.getLdapContext().search(jndiName, filter, ctls);
    try
        ConfigConstants.ATTR_OBJECTCLASS);
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      while(databases.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = databases.next();
        SearchResultEntry sr = entryReader.readEntry();
        String id = getFirstValue(sr, "ds-cfg-backend-id");
        String id = firstValueAsString(sr, "ds-cfg-backend-id");
        if (!isConfigBackend(id) || isSchemaBackend(id))
        {
          Set<String> baseDns = getValues(sr, "ds-cfg-base-dn");
          Set<DN> baseDns = asSetOfDN(sr, "ds-cfg-base-dn");
          Set<String> entries;
          if (cacheFilter.searchMonitoringInformation())
@@ -877,29 +784,29 @@
          }
          Set<ReplicaDescriptor> replicas = desc.getReplicas();
          for (String baseDn : baseDns)
          for (DN baseDn : baseDns)
          {
            if (isAddReplica(cacheFilter, baseDn))
            {
              SuffixDescriptor suffix = new SuffixDescriptor();
              suffix.setDN(baseDn);
              ReplicaDescriptor replica = new ReplicaDescriptor();
              replica.setServer(desc);
              replica.setObjectClasses(getValues(sr, ConfigConstants.ATTR_OBJECTCLASS));
              replica.setObjectClasses(asSetOfString(sr, ConfigConstants.ATTR_OBJECTCLASS));
              replica.setBackendName(id);
              replicas.add(replica);
              HashSet<ReplicaDescriptor> r = new HashSet<>();
              r.add(replica);
              suffix.setReplicas(r);
              SuffixDescriptor suffix = new SuffixDescriptor();
              suffix.setDN(baseDn);
              suffix.setReplicas(newHashSet(replica));
              replica.setSuffix(suffix);
              int nEntries = -1;
              for (String s : entries)
              {
                int index = s.indexOf(" ");
                if (index != -1)
                {
                  String dn = s.substring(index + 1);
                  if (areDnsEqual(baseDn, dn))
                  DN dn = DN.valueOf(s.substring(index + 1));
                  if (baseDn.equals(dn))
                  {
                    try
                    {
@@ -920,13 +827,9 @@
        }
      }
    }
    finally
    {
      databases.close();
    }
  }
  private static boolean isAddReplica(TopologyCacheFilter cacheFilter, String baseDn)
  private static boolean isAddReplica(TopologyCacheFilter cacheFilter, DN baseDn)
  {
    if (cacheFilter.searchAllBaseDNs())
    {
@@ -935,7 +838,7 @@
    for (String dn : cacheFilter.getBaseDNsToSearch())
    {
      if (areDnsEqual(dn, baseDn))
      if (DN.valueOf(dn).equals(baseDn))
      {
        return true;
      }
@@ -943,97 +846,47 @@
    return false;
  }
  private static void updateReplication(ServerDescriptor desc,
      ConnectionWrapper conn, TopologyCacheFilter cacheFilter)
  throws NamingException
  private static void updateReplication(ServerDescriptor desc, ConnectionWrapper conn, TopologyCacheFilter cacheFilter)
      throws IOException
  {
    boolean replicationEnabled = false;
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            "ds-cfg-enabled"
        });
    String filter = "(objectclass=ds-cfg-synchronization-provider)";
    LdapName jndiName = new LdapName(
      "cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config");
    NamingEnumeration<SearchResult> syncProviders = null;
    try
    {
      syncProviders = conn.getLdapContext().search(jndiName, filter, ctls);
      while(syncProviders.hasMore())
      {
        SearchResult sr = syncProviders.next();
        if ("true".equalsIgnoreCase(getFirstValue(sr,
          "ds-cfg-enabled")))
        {
          replicationEnabled = true;
        }
      }
    }
    catch (NameNotFoundException nse)
    {
      /* ignore */
    }
    finally
    {
      if (syncProviders != null)
      {
        syncProviders.close();
      }
    }
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_ENABLED,
        Boolean.valueOf(replicationEnabled));
    SearchRequest request = newSearchRequest(
        "cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config",
        WHOLE_SUBTREE,
        "(objectclass=ds-cfg-synchronization-provider)",
        "ds-cfg-enabled");
    SearchResultEntry sre = conn.getConnection().searchSingleEntry(request);
    Boolean replicationEnabled = asBoolean(sre, "ds-cfg-enabled");
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_ENABLED, replicationEnabled);
    Set<String> allReplicationServers = new LinkedHashSet<>();
    if (cacheFilter.searchBaseDNInformation())
    {
      ctls = new SearchControls();
      ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
      ctls.setReturningAttributes(
          new String[] {
      request = newSearchRequest(
          "cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config",
          WHOLE_SUBTREE,
          "(objectclass=ds-cfg-replication-domain)",
              "ds-cfg-base-dn",
              "ds-cfg-replication-server",
              "ds-cfg-server-id"
          });
      filter = "(objectclass=ds-cfg-replication-domain)";
      jndiName = new LdapName(
      "cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config");
      syncProviders = null;
      try
      );
      try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
      {
        syncProviders = conn.getLdapContext().search(jndiName, filter, ctls);
        while(syncProviders.hasMore())
        while (entryReader.hasNext())
        {
          SearchResult sr = syncProviders.next();
          SearchResultEntry sr = entryReader.readEntry();
          int id = Integer.parseInt(
              getFirstValue(sr, "ds-cfg-server-id"));
          Set<String> replicationServers = getValues(sr,
          "ds-cfg-replication-server");
          Set<String> dns = getValues(sr, "ds-cfg-base-dn");
          for (String dn : dns)
          int id = asInteger(sr, "ds-cfg-server-id");
          Set<String> replicationServers = asSetOfString(sr, "ds-cfg-replication-server");
          Set<DN> dns = asSetOfDN(sr, "ds-cfg-base-dn");
          for (DN dn : dns)
          {
            for (ReplicaDescriptor replica : desc.getReplicas())
            {
              if (areDnsEqual(replica.getSuffix().getDN(), dn))
              if (replica.getSuffix().getDnAsDn().equals(dn))
              {
                replica.setReplicationId(id);
                // Keep the values of the replication servers in lower case
                // to make use of Sets as String simpler.
                LinkedHashSet<String> repServers = new LinkedHashSet<>();
                for (String s: replicationServers)
                {
                  repServers.add(s.toLowerCase());
                }
                LinkedHashSet<String> repServers = toLowercase(replicationServers);
                replica.setReplicationServers(repServers);
                allReplicationServers.addAll(repServers);
              }
@@ -1041,191 +894,139 @@
          }
        }
      }
      catch (NameNotFoundException nse)
      {
        /* ignore */
      }
      finally
      {
        if (syncProviders != null)
        {
          syncProviders.close();
        }
      }
    }
    ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.SUBTREE_SCOPE);
    ctls.setReturningAttributes(
    new String[] {
      "ds-cfg-replication-port", "ds-cfg-replication-server",
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER, Boolean.FALSE);
    request = newSearchRequest(
        "cn=Multimaster Synchronization,cn=Synchronization Providers,cn=config",
        WHOLE_SUBTREE,
        "(objectclass=ds-cfg-replication-server)",
        "ds-cfg-replication-port",
        "ds-cfg-replication-server",
      "ds-cfg-replication-server-id"
    });
    filter = "(objectclass=ds-cfg-replication-server)";
    jndiName = new LdapName("cn=Multimaster "+
        "Synchronization,cn=Synchronization Providers,cn=config");
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER,
        Boolean.FALSE);
    NamingEnumeration<SearchResult> entries = null;
    try
    );
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      entries = conn.getLdapContext().search(jndiName, filter, ctls);
      while (entries.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = entries.next();
        SearchResultEntry sr = entryReader.readEntry();
        desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER,
            Boolean.TRUE);
        String v = getFirstValue(sr, "ds-cfg-replication-port");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_PORT,
            Integer.parseInt(v));
        v = getFirstValue(sr, "ds-cfg-replication-server-id");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_ID,
            Integer.parseInt(v));
        Set<String> values = getValues(sr, "ds-cfg-replication-server");
        // Keep the values of the replication servers in lower case
        // to make use of Sets as String simpler.
        desc.serverProperties.put(ServerProperty.IS_REPLICATION_SERVER, Boolean.TRUE);
        Integer port = asInteger(sr, "ds-cfg-replication-port");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_PORT, port);
        Integer serverId = asInteger(sr, "ds-cfg-replication-server-id");
        desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_ID, serverId);
        LinkedHashSet<String> repServers = toLowercase(asSetOfString(sr, "ds-cfg-replication-server"));
        allReplicationServers.addAll(repServers);
        desc.serverProperties.put(ServerProperty.EXTERNAL_REPLICATION_SERVERS, allReplicationServers);
      }
    }
    Boolean replicationSecure = isReplicationSecure(conn, replicationEnabled);
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_SECURE, replicationSecure);
  }
  /**
   * Keep the values of the replication servers in lower case to make use of Sets as String simpler.
   */
  private static LinkedHashSet<String> toLowercase(Set<String> values)
  {
        LinkedHashSet<String> repServers = new LinkedHashSet<>();
        for (String s: values)
        {
          repServers.add(s.toLowerCase());
        }
        allReplicationServers.addAll(repServers);
        desc.serverProperties.put(ServerProperty.EXTERNAL_REPLICATION_SERVERS,
            allReplicationServers);
      }
    }
    catch (NameNotFoundException nse)
    {
      /* ignore */
    }
    finally
    {
      if (entries != null)
      {
        entries.close();
      }
    return repServers;
    }
    boolean replicationSecure = false;
  private static boolean isReplicationSecure(ConnectionWrapper conn, boolean replicationEnabled) throws IOException
  {
    if (replicationEnabled)
    {
      ctls = new SearchControls();
      ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
      ctls.setReturningAttributes(
      new String[] {"ds-cfg-ssl-encryption"});
      filter = "(objectclass=ds-cfg-crypto-manager)";
      jndiName = new LdapName("cn=Crypto Manager,cn=config");
      entries = conn.getLdapContext().search(jndiName, filter, ctls);
      try
      SearchRequest request = newSearchRequest(
          "cn=Crypto Manager,cn=config", BASE_OBJECT, "(objectclass=ds-cfg-crypto-manager)",
          "ds-cfg-ssl-encryption");
      try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
      {
        while (entries.hasMore())
        while (entryReader.hasNext())
        {
          SearchResult sr = entries.next();
          String v = getFirstValue(sr, "ds-cfg-ssl-encryption");
          replicationSecure = "true".equalsIgnoreCase(v);
          SearchResultEntry sr = entryReader.readEntry();
          return asBoolean(sr, "ds-cfg-ssl-encryption");
        }
      }
      finally
      {
        entries.close();
      }
    }
    desc.serverProperties.put(ServerProperty.IS_REPLICATION_SECURE,
        Boolean.valueOf(replicationSecure));
    return false;
  }
  /**
   Updates the instance key public-key certificate value of this context from
   the local truststore of the instance bound by this context. Any current
   value of the certificate is overwritten. The intent of this method is to
   retrieve the instance-key public-key certificate when this context is bound
   to an instance, and cache it for later use in registering the instance into
   ADS.
   @param desc The map to update with the instance key-pair public-key
   certificate.
   @param conn The connection to the server.
   @throws NamingException if unable to retrieve certificate from bound
   instance.
   * Updates the instance key public-key certificate value of this context from the local truststore
   * of the instance bound by this context. Any current value of the certificate is overwritten. The
   * intent of this method is to retrieve the instance-key public-key certificate when this context
   * is bound to an instance, and cache it for later use in registering the instance into ADS.
   *
   * @param desc
   *          The map to update with the instance key-pair public-key certificate.
   * @param connWrapper
   *          The connection to the server.
   * @throws LdapException
   *           if unable to retrieve certificate from bound instance.
   */
  private static void updatePublicKeyCertificate(ServerDescriptor desc, ConnectionWrapper conn) throws NamingException
  private static void updatePublicKeyCertificate(ServerDescriptor desc, ConnectionWrapper connWrapper)
      throws LdapException
  {
    /* TODO: this DN is declared in some core constants file. Create a constants
       file for the installer and import it into the core. */
    final String dnStr = "ds-cfg-key-id=ads-certificate,cn=ads-truststore";
    final LdapName dn = new LdapName(dnStr);
    String dn = "ds-cfg-key-id=ads-certificate,cn=ads-truststore";
    Connection conn = connWrapper.getConnection();
    for (int i = 0; i < 2 ; ++i) {
      /* If the entry does not exist in the instance's truststore backend, add
         it (which induces the CryptoManager to create the public-key
         certificate attribute), then repeat the search. */
      try {
        final SearchControls searchControls = new SearchControls();
        searchControls.setSearchScope(SearchControls.OBJECT_SCOPE);
        final String attrIDs[] = { "ds-cfg-public-key-certificate;binary" };
        searchControls.setReturningAttributes(attrIDs);
        final SearchResult certEntry = conn.getLdapContext().search(dn,
                   "(objectclass=ds-cfg-instance-key)", searchControls).next();
        final Attribute certAttr = certEntry.getAttributes().get(attrIDs[0]);
        SearchRequest request = newSearchRequest(
            dn,
            BASE_OBJECT,
            "(objectclass=ds-cfg-instance-key)",
            "ds-cfg-public-key-certificate;binary");
        SearchResultEntry certEntry = conn.searchSingleEntry(request);
        final Attribute certAttr = certEntry.getAttribute("ds-cfg-public-key-certificate;binary");
        if (null != certAttr) {
          /* attribute ds-cfg-public-key-certificate is a MUST in the schema */
          desc.serverProperties.put(
                  ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE,
                  certAttr.get());
                  certAttr.firstValue().toByteArray());
        }
        break;
      }
      catch (NameNotFoundException x) {
        if (0 == i) {
      catch (LdapException e)
      {
        if (0 != i || e.getResult().getResultCode() != ResultCode.NO_SUCH_OBJECT)
        {
          throw e;
        }
          // Poke CryptoManager to initialize truststore. Note the special attribute in the request.
          final Attributes attrs = new BasicAttributes();
          final Attribute oc = new BasicAttribute("objectclass");
          oc.add("top");
          oc.add("ds-cfg-self-signed-cert-request");
          attrs.put(oc);
          conn.getLdapContext().createSubcontext(dn, attrs).close();
        }
        else {
          throw x;
        }
        AddRequest request = newAddRequest(dn)
            .addAttribute("objectclass", "top", "ds-cfg-self-signed-cert-request");
        conn.add(request);
      }
    }
  }
  private static void updateMiscellaneous(ServerDescriptor desc, ConnectionWrapper conn) throws NamingException
  private static void updateMiscellaneous(ServerDescriptor desc, ConnectionWrapper conn) throws IOException
  {
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            "ds-sync-generation-id"
        });
    String filter = "(|(objectclass=*)(objectclass=ldapsubentry))";
    LdapName jndiName = new LdapName("cn=schema");
    NamingEnumeration<SearchResult> listeners =
      conn.getLdapContext().search(jndiName, filter, ctls);
    try
    SearchRequest request = newSearchRequest("cn=schema", BASE_OBJECT, filter, "ds-sync-generation-id");
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      while(listeners.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = listeners.next();
        SearchResultEntry sr = entryReader.readEntry();
        desc.serverProperties.put(ServerProperty.SCHEMA_GENERATION_ID,
            getFirstValue(sr, "ds-sync-generation-id"));
            firstValueAsString(sr, "ds-sync-generation-id"));
      }
    }
    finally
    {
      listeners.close();
    }
  }
  /**
@@ -1235,82 +1036,70 @@
   certificates. This trust is necessary at least to initialize replication,
   which uses the trusted certificate entries in the ads-truststore for server
   authentication.
   @param conn The connection to the server.
   @param connWrapper The connection to the server.
   @param keyEntryMap The set of valid (i.e., not tagged as compromised)
   instance key-pair public-key certificate entries in ADS represented as a map
   from keyID to public-key certificate (binary).
   @throws NamingException in case an error occurs while updating the instance's
   @throws LdapException in case an error occurs while updating the instance's
   ads-truststore via LDAP.
   */
  public static void seedAdsTrustStore(
          ConnectionWrapper conn,
          Map<String, byte[]> keyEntryMap)
          throws NamingException
  public static void seedAdsTrustStore(ConnectionWrapper connWrapper, Map<String, byte[]> keyEntryMap)
      throws LdapException
  {
    Connection conn = connWrapper.getConnection();
    /* TODO: this DN is declared in some core constants file. Create a
       constants file for the installer and import it into the core. */
    final Attribute oc = new BasicAttribute("objectclass");
    oc.add("top");
    oc.add("ds-cfg-instance-key");
    for (Map.Entry<String, byte[]> keyEntry : keyEntryMap.entrySet()){
      final BasicAttributes keyAttrs = new BasicAttributes();
      keyAttrs.put(oc);
      final Attribute rdnAttr = new BasicAttribute(
              ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName(),
              keyEntry.getKey());
      keyAttrs.put(rdnAttr);
      keyAttrs.put(new BasicAttribute(
              ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.
                      getAttributeName() + ";binary", keyEntry.getValue()));
      final LdapName keyDn = new LdapName(rdnAttr.getID() + "=" + Rdn.escapeValue(rdnAttr.get()) + "," + TRUSTSTORE_DN);
      try {
        conn.getLdapContext().createSubcontext(keyDn, keyAttrs).close();
      String instanceKeyId = ADSContext.ServerProperty.INSTANCE_KEY_ID.getAttributeName();
      String instancePublicKeyCertificate =
          ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE.getAttributeName() + ";binary";
      String dn = instanceKeyId + "=" + Rdn.escapeValue(keyEntry.getKey()) + "," + TRUSTSTORE_DN;
      AddRequest request = newAddRequest(dn)
          .addAttribute("objectclass", "top", "ds-cfg-instance-key")
          .addAttribute(instanceKeyId, keyEntry.getKey())
          .addAttribute(instancePublicKeyCertificate, keyEntry.getValue());
      try
      {
        conn.add(request);
      }
      catch(NameAlreadyBoundException x){
        conn.getLdapContext().destroySubcontext(keyDn);
        conn.getLdapContext().createSubcontext(keyDn, keyAttrs).close();
      catch (LdapException e)
      {
        if (e.getResult().getResultCode() != ResultCode.ENTRY_ALREADY_EXISTS)
        {
          throw e;
        }
        conn.delete(dn);
        conn.add(request);
      }
    }
  }
  /**
   * Returns the values of the ds-base-dn-entry count attributes for the given
   * backend monitor entry using the provided connection.
   * @param conn the connection to use to update the configuration.
   * @param backendID the id of the backend.
   * Returns the values of the ds-base-dn-entry count attributes for the given backend monitor entry
   * using the provided connection.
   *
   * @param conn
   *          the connection to use to update the configuration.
   * @param backendID
   *          the id of the backend.
   * @return the values of the ds-base-dn-entry count attribute.
   * @throws NamingException if there was an error.
   * @throws IOException
   *           if there was an error.
   */
  private static Set<String> getBaseDNEntryCount(ConnectionWrapper conn,
      String backendID) throws NamingException
  private static Set<String> getBaseDNEntryCount(ConnectionWrapper conn, String backendID) throws IOException
  {
    LinkedHashSet<String> v = new LinkedHashSet<>();
    SearchControls ctls = new SearchControls();
    ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
    ctls.setReturningAttributes(
        new String[] {
            "ds-base-dn-entry-count"
        });
    String filter = "(ds-backend-id="+backendID+")";
    LdapName jndiName = new LdapName("cn=monitor");
    NamingEnumeration<SearchResult> listeners =
      conn.getLdapContext().search(jndiName, filter, ctls);
    try
    LinkedHashSet<String> results = new LinkedHashSet<>();
    SearchRequest request =
        newSearchRequest("cn=monitor", SINGLE_LEVEL, "(ds-backend-id=" + backendID + ")", "ds-base-dn-entry-count");
    try (ConnectionEntryReader entryReader = conn.getConnection().search(request))
    {
      while(listeners.hasMore())
      while (entryReader.hasNext())
      {
        SearchResult sr = listeners.next();
        v.addAll(getValues(sr, "ds-base-dn-entry-count"));
        SearchResultEntry sr = entryReader.readEntry();
        results.addAll(asSetOfString(sr, "ds-base-dn-entry-count"));
      }
    }
    finally
    {
      listeners.close();
    }
    return v;
    return results;
  }
  /**
opendj-server-legacy/src/main/java/org/opends/admin/ads/SuffixDescriptor.java
@@ -12,13 +12,15 @@
 * information: "Portions Copyright [year] [name of copyright owner]".
 *
 * Copyright 2008 Sun Microsystems, Inc.
 * Portions Copyright 2015 ForgeRock AS.
 * Portions Copyright 2015-2016 ForgeRock AS.
 */
package org.opends.admin.ads;
import java.util.HashSet;
import java.util.Set;
import org.forgerock.opendj.ldap.DN;
/**
 * The object of this class represent a topology of replicas across servers that
 * have the same suffix DN. If there is more than one replica on the suffix, the
@@ -26,7 +28,7 @@
 */
public class SuffixDescriptor
{
  private String suffixDN;
  private DN suffixDN;
  private final Set<ReplicaDescriptor> replicas = new HashSet<>();
  /**
@@ -34,7 +36,17 @@
   *
   * @return the DN associated with this suffix descriptor.
   */
  public String getDN()
  public String getDN() // FIXME change return type to DN
  {
    return suffixDN.toString();
  }
  /**
   * Returns the DN associated with this suffix descriptor.
   *
   * @return the DN associated with this suffix descriptor.
   */
  public DN getDnAsDn()
  {
    return suffixDN;
  }
@@ -45,7 +57,7 @@
   * @param suffixDN
   *          the DN associated with this suffix descriptor.
   */
  public void setDN(String suffixDN)
  public void setDN(DN suffixDN)
  {
    this.suffixDN = suffixDN;
  }
@@ -109,7 +121,6 @@
    {
      buf.append("-").append(replica.getServer().getId());
    }
    return buf.toString();
  }
}
opendj-server-legacy/src/main/java/org/opends/admin/ads/util/ConnectionUtils.java
@@ -39,6 +39,8 @@
import org.forgerock.i18n.LocalizableMessage;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.ldap.DN;
import org.forgerock.opendj.ldap.responses.SearchResultEntry;
import org.opends.server.replication.plugin.EntryHistorical;
import org.opends.server.schema.SchemaConstants;
import org.opends.server.types.HostPort;
@@ -604,4 +606,83 @@
    }
    return values;
  }
  /**
   * Returns the first attribute value in this attribute decoded as a UTF-8 string.
   *
   * @param sr
   *          the search result entry
   * @param attrDesc
   *          the attribute description
   * @return The first attribute value in this attribute decoded as a UTF-8 string.
   */
  public static String firstValueAsString(SearchResultEntry sr, String attrDesc)
  {
    org.forgerock.opendj.ldap.Attribute attr = sr.getAttribute(attrDesc);
    return (attr != null && !attr.isEmpty()) ? attr.firstValueAsString() : null;
  }
  /**
   * Returns the first value decoded as an Integer, or {@code null} if the attribute does not
   * contain any values.
   *
   * @param sr
   *          the search result entry
   * @param attrDesc
   *          the attribute description
   * @return The first value decoded as an Integer.
   */
  public static Integer asInteger(SearchResultEntry sr, String attrDesc)
  {
    org.forgerock.opendj.ldap.Attribute attr = sr.getAttribute(attrDesc);
    return attr != null ? attr.parse().asInteger() : null;
  }
  /**
   * Returns the first value decoded as a Boolean, or {@code null} if the attribute does not contain
   * any values.
   *
   * @param sr
   *          the search result entry
   * @param attrDesc
   *          the attribute description
   * @return The first value decoded as an Boolean.
   */
  public static Boolean asBoolean(SearchResultEntry sr, String attrDesc)
  {
    org.forgerock.opendj.ldap.Attribute attr = sr.getAttribute(attrDesc);
    return attr != null ? attr.parse().asBoolean() : null;
  }
  /**
   * Returns the values decoded as a set of Strings.
   *
   * @param sr
   *          the search result entry
   * @param attrDesc
   *          the attribute description
   * @return The values decoded as a set of Strings. Never {@code null} and never contains
   *         {@code null} values.
   */
  public static Set<String> asSetOfString(SearchResultEntry sr, String attrDesc)
  {
    org.forgerock.opendj.ldap.Attribute attr = sr.getAttribute(attrDesc);
    return attr != null ? attr.parse().asSetOfString() : null;
  }
  /**
   * Returns the values decoded as a set of DNs.
   *
   * @param sr
   *          the search result entry
   * @param attrDesc
   *          the attribute description
   * @return The values decoded as a set of DNs. Never {@code null} and never contains {@code null}
   *         values.
   */
  public static Set<DN> asSetOfDN(SearchResultEntry sr, String attrDesc)
  {
    org.forgerock.opendj.ldap.Attribute attr = sr.getAttribute(attrDesc);
    return attr != null ? attr.parse().asSetOfDN() : null;
  }
}
opendj-server-legacy/src/main/java/org/opends/quicksetup/installer/Installer.java
@@ -1947,10 +1947,10 @@
            backendTypes.get(backendName).getBackend());
      }
    }
    catch (NamingException ne)
    catch (NamingException e)
    {
      LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), ne);
      throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, failedMsg, ne);
      LocalizableMessage failedMsg = getThrowableMsg(INFO_ERROR_CONNECTING_TO_LOCAL.get(), e);
      throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, failedMsg, e);
    }
  }
@@ -2487,18 +2487,10 @@
          }
        }
      }
      catch (NamingException ne)
      catch (IOException e)
      {
        LocalizableMessage msg;
        if (isCertificateException(ne))
        {
          msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(getHostPort(server), ne.toString(true));
        }
        else
        {
          msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(getHostPort(server), ne.toString(true));
        }
        throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, ne);
        LocalizableMessage msg = Utils.getMessageForException(e);
        throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, e);
      }
    }
@@ -2551,18 +2543,10 @@
              }
            }
          }
          catch (NamingException ne)
          catch (IOException e)
          {
            LocalizableMessage msg;
            if (isCertificateException(ne))
            {
              msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(getHostPort(server), ne.toString(true));
            }
            else
            {
              msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(getHostPort(server), ne.toString(true));
            }
            throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, ne);
            LocalizableMessage msg = Utils.getMessageForException(e);
            throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, e);
          }
        }
        if (replicationId == -1)
@@ -2741,6 +2725,19 @@
        }
      }
    }
    catch (IOException e)
    {
      LocalizableMessage msg;
      if (isRemoteServer)
      {
        msg = getMessageForException(e, auth.getHostPort().toString());
      }
      else
      {
        msg = Utils.getMessageForException(e);
      }
      throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg, e);
    }
    catch (NamingException ne)
    {
      LocalizableMessage msg;
@@ -3955,7 +3952,7 @@
   * Update the UserInstallData object with the contents of the server to which
   * we are connected with the provided connection.
   */
  private void updateUserDataWithSuffixesInServer(ConnectionWrapper conn) throws NamingException
  private void updateUserDataWithSuffixesInServer(ConnectionWrapper conn) throws IOException
  {
    SuffixesToReplicateOptions suf = getUserData().getSuffixesToReplicateOptions();
    SuffixesToReplicateOptions.Type type;
opendj-server-legacy/src/main/java/org/opends/quicksetup/util/Utils.java
@@ -64,6 +64,8 @@
import org.forgerock.i18n.LocalizableMessageBuilder;
import org.forgerock.i18n.slf4j.LocalizedLogger;
import org.forgerock.opendj.config.ManagedObjectDefinition;
import org.forgerock.opendj.ldap.AuthorizationException;
import org.forgerock.opendj.ldap.ConnectionException;
import org.forgerock.opendj.server.config.client.BackendCfgClient;
import org.forgerock.opendj.server.config.server.BackendCfg;
import org.opends.admin.ads.ADSContext;
@@ -679,8 +681,41 @@
  }
  /**
   * Returns the path of the installation of the directory server. Note that
   * this method assumes that this code is being run locally.
   * Returns a message object for the given IOException. The code assume that we are trying to
   * connect to the local server.
   *
   * @param e
   *          the IOException.
   * @return a message object for the given IOException.
   */
  public static LocalizableMessage getMessageForException(IOException e)
  {
    final String detailedException = e.getLocalizedMessage();
    if (isCertificateException(e))
    {
      return INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE.get(detailedException);
    }
    else if (e instanceof org.forgerock.opendj.ldap.AuthenticationException)
    {
      return ERR_CANNOT_CONNECT_TO_LOCAL_AUTHENTICATION.get(detailedException);
    }
    else if (e instanceof AuthorizationException)
    {
      return ERR_CANNOT_CONNECT_TO_LOCAL_PERMISSIONS.get(detailedException);
    }
    else if (e instanceof ConnectionException)
    {
      return ERR_CANNOT_CONNECT_TO_LOCAL_COMMUNICATION.get(detailedException);
    }
    else
    {
      return ERR_CANNOT_CONNECT_TO_LOCAL_GENERIC.get(detailedException);
    }
  }
  /**
   * Returns the path of the installation of the directory server. Note that this method assumes
   * that this code is being run locally.
   *
   * @return the path of the installation of the directory server.
   */
@@ -1761,7 +1796,7 @@
      Set<SuffixDescriptor> suffixes = suf.getSuffixes();
      for (SuffixDescriptor suffix : suffixes)
      {
        baseDNs.add(suffix.getDN());
        baseDNs.add(suffix.getDN().toString());
      }
    }
    return baseDNs;
@@ -1774,15 +1809,15 @@
    Set<SuffixDescriptor> suffixes = userData.getSuffixesToReplicateOptions().getSuffixes();
    AuthenticationData authData = userData.getReplicationOptions().getAuthenticationData();
    String ldapURL = ConnectionUtils.getLDAPUrl(authData.getHostPort(), authData.useSecureConnection());
    suffixLoop:
    for (SuffixDescriptor suffix : suffixes)
    {
      boolean found = false;
      for (ReplicaDescriptor replica : suffix.getReplicas())
      {
        if (ldapURL.equalsIgnoreCase(replica.getServer().getAdminConnectorURL()))
        {
          // This is the server we're configuring
          found = true;
          Set<String> baseDNs = hm.get(replica.getServer());
          if (baseDNs == null)
          {
@@ -1790,31 +1825,25 @@
            hm.put(replica.getServer(), baseDNs);
          }
          baseDNs.add(suffix.getDN());
          break;
          continue suffixLoop;
        }
      }
      if (!found)
      {
        for (ReplicaDescriptor replica : suffix.getReplicas())
        {
          if (hm.keySet().contains(replica.getServer()))
        Set<String> baseDNs = hm.get(replica.getServer());
        if (baseDNs != null)
          {
            hm.get(replica.getServer()).add(suffix.getDN());
            found = true;
            break;
          baseDNs.add(suffix.getDN());
          continue suffixLoop;
          }
        }
      }
      if (!found)
      {
        // We haven't found the server yet, just take the first one
        ReplicaDescriptor replica = suffix.getReplicas().iterator().next();
        if (replica != null)
        {
          Set<String> baseDNs = new LinkedHashSet<>();
          hm.put(replica.getServer(), baseDNs);
          baseDNs.add(suffix.getDN());
        }
        hm.put(replica.getServer(), newLinkedHashSet(suffix.getDN()));
      }
    }
    return hm;
opendj-server-legacy/src/main/java/org/opends/server/tools/dsreplication/ReplicationCliMain.java
@@ -1470,10 +1470,10 @@
      {
        return;
      }
      catch (NamingException ne)
      catch (NamingException e)
      {
        throw new ReplicationCliException(getThrowableMsg(ERR_READING_SERVER_TASK_PROGRESS.get(), ne),
            ERROR_CONNECTING, ne);
        throw new ReplicationCliException(getThrowableMsg(ERR_READING_SERVER_TASK_PROGRESS.get(), e),
            ERROR_CONNECTING, e);
      }
    }
  }
@@ -1700,7 +1700,7 @@
      for (BaseDNDescriptor baseDN : backend.getBaseDns())
      {
        SuffixDescriptor suffix = new SuffixDescriptor();
        suffix.setDN(baseDN.getDn().toString());
        suffix.setDN(baseDN.getDn());
        ReplicaDescriptor replica = new ReplicaDescriptor();
@@ -5478,10 +5478,10 @@
    {
      return ServerDescriptor.createStandalone(conn, filter);
    }
    catch (NamingException ne)
    catch (IOException e)
    {
      throw new ReplicationCliException(
          getMessageForException(ne, conn.getHostPort().toString()), ERROR_READING_CONFIGURATION, ne);
          getMessageForException(e, conn.getHostPort().toString()), ERROR_READING_CONFIGURATION, e);
    }
  }
@@ -6969,7 +6969,7 @@
        }
      }
    }
    catch (NamingException ne)
    catch (IOException ne)
    {
      LocalizableMessage msg = getMessageForException(ne, connSource.getHostPort().toString());
      throw new ReplicationCliException(msg, ERROR_READING_CONFIGURATION, ne);