From 6b91643447398f13e01a4e02f8431e5263fc9bff Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Wed, 20 Feb 2008 09:22:09 +0000
Subject: [PATCH] Fix for issue 2962 (Setup should allow non-secure replication port while LDAP access is SSL-enabled)

---
 opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java         |    2 
 opends/src/ads/org/opends/admin/ads/TopologyCache.java                         |   31 ++
 opends/src/ads/org/opends/admin/ads/util/PreferredConnection.java              |  147 +++++++++++++
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java |  101 ++++++++-
 opends/src/ads/org/opends/admin/ads/util/ServerLoader.java                     |  121 ++++++++--
 opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java           |    4 
 opends/src/ads/org/opends/admin/ads/ServerDescriptor.java                      |   94 ++++++++
 opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java           |  121 +++++++++-
 opends/src/quicksetup/org/opends/quicksetup/Application.java                   |    9 
 9 files changed, 568 insertions(+), 62 deletions(-)

diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index 9ac105c..9100d85 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -84,6 +84,10 @@
      */
     LDAPS_ENABLED,
     /**
+     * The associated value is an ArrayList of Boolean.
+     */
+    STARTTLS_ENABLED,
+    /**
      * The associated value is an ArrayList of Integer.
      */
     JMX_PORT,
@@ -297,6 +301,80 @@
   }
 
   /**
+   * Returns the URL to access this server using LDAP.  Returns
+   * <CODE>null</CODE> if the server is not configured to listen on an LDAP
+   * port.
+   * @return the URL to access this server using LDAP.
+   */
+  public String getLDAPURL()
+  {
+    String ldapUrl = null;
+    String host = getHostName();
+    int port = -1;
+
+    if (!serverProperties.isEmpty())
+    {
+      ArrayList s = (ArrayList)serverProperties.get(
+          ServerProperty.LDAP_ENABLED);
+      ArrayList p = (ArrayList)serverProperties.get(
+          ServerProperty.LDAP_PORT);
+      if (s != null)
+      {
+        for (int i=0; i<s.size(); i++)
+        {
+          if (Boolean.TRUE.equals(s.get(i)))
+          {
+            port = (Integer)p.get(i);
+            break;
+          }
+        }
+      }
+    }
+    if (port != -1)
+    {
+      ldapUrl = ConnectionUtils.getLDAPUrl(host, port, false);
+    }
+    return ldapUrl;
+  }
+
+  /**
+   * Returns the URL to access this server using LDAPS.  Returns
+   * <CODE>null</CODE> if the server is not configured to listen on an LDAPS
+   * port.
+   * @return the URL to access this server using LDAP.
+   */
+  public String getLDAPsURL()
+  {
+    String ldapsUrl = null;
+    String host = getHostName();
+    int port = -1;
+
+    if (!serverProperties.isEmpty())
+    {
+      ArrayList s = (ArrayList)serverProperties.get(
+          ServerProperty.LDAPS_ENABLED);
+      ArrayList p = (ArrayList)serverProperties.get(
+          ServerProperty.LDAPS_PORT);
+      if (s != null)
+      {
+        for (int i=0; i<s.size(); i++)
+        {
+          if (Boolean.TRUE.equals(s.get(i)))
+          {
+            port = (Integer)p.get(i);
+            break;
+          }
+        }
+      }
+    }
+    if (port != -1)
+    {
+      ldapsUrl = ConnectionUtils.getLDAPUrl(host, port, true);
+    }
+    return ldapsUrl;
+  }
+
+  /**
    * Returns a String of type host-name:port-number for the server.  If
    * the provided securePreferred is set to true the port that will be used
    * (if LDAPS is enabled) will be the LDAPS port.
@@ -517,6 +595,16 @@
         adsProperties.put(adsProps[i][1], String.valueOf(port));
       }
     }
+
+    ArrayList array = (ArrayList)serverProperties.get(
+        ServerProperty.STARTTLS_ENABLED);
+    boolean startTLSEnabled = false;
+    if ((array != null) && !array.isEmpty())
+    {
+      startTLSEnabled = Boolean.TRUE.equals(array.get(array.size() -1));
+    }
+    adsProperties.put(ADSContext.ServerProperty.STARTTLS_ENABLED,
+        startTLSEnabled ? "true" : "false");
     adsProperties.put(ADSContext.ServerProperty.ID, getHostPort(true));
     adsProperties.put(ADSContext.ServerProperty.INSTANCE_PUBLIC_KEY_CERTIFICATE,
                       getInstancePublicKeyCertificate());
@@ -576,6 +664,7 @@
             "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)";
@@ -587,11 +676,13 @@
     ArrayList<Integer> ldapsPorts = new ArrayList<Integer>();
     ArrayList<Boolean> ldapEnabled = new ArrayList<Boolean>();
     ArrayList<Boolean> ldapsEnabled = new ArrayList<Boolean>();
+    ArrayList<Boolean> startTLSEnabled = new ArrayList<Boolean>();
 
     desc.serverProperties.put(ServerProperty.LDAP_PORT, ldapPorts);
     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);
 
     while(listeners.hasMore())
     {
@@ -613,6 +704,9 @@
       {
         ldapPorts.add(new Integer(port));
         ldapEnabled.add(enabled);
+        enabled = "true".equalsIgnoreCase(
+            getFirstValue(sr, "ds-cfg-allow-start-tls"));
+        startTLSEnabled.add(enabled);
       }
     }
   }
diff --git a/opends/src/ads/org/opends/admin/ads/TopologyCache.java b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
index 8a9ef30..c3cf586 100644
--- a/opends/src/ads/org/opends/admin/ads/TopologyCache.java
+++ b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
@@ -31,6 +31,7 @@
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
 import java.util.logging.Level;
@@ -41,6 +42,7 @@
 import org.opends.admin.ads.ADSContext.ServerProperty;
 import org.opends.admin.ads.util.ApplicationTrustManager;
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.admin.ads.util.ServerLoader;
 
 /**
@@ -57,6 +59,8 @@
   private String pwd;
   private Set<ServerDescriptor> servers = new HashSet<ServerDescriptor>();
   private Set<SuffixDescriptor> suffixes = new HashSet<SuffixDescriptor>();
+  private LinkedHashSet<PreferredConnection> preferredConnections =
+    new LinkedHashSet<PreferredConnection>();
 
   private final boolean isMultiThreaded = true;
   private final static int MULTITHREAD_TIMEOUT = 90 * 1000;
@@ -173,6 +177,30 @@
   }
 
   /**
+   * Sets the list of LDAP URLs and connection type that are preferred to be
+   * used to connect to the servers.  When we have a server to which we can
+   * connect using a URL on the list we will try to use it.
+   * @param cnx the list of preferred connections.
+   */
+  public void setPreferredConnections(LinkedHashSet<PreferredConnection> cnx)
+  {
+    preferredConnections.clear();
+    preferredConnections.addAll(cnx);
+  }
+
+  /**
+   * Returns the list of LDAP URLs and connection type that are preferred to be
+   * used to connect to the servers.  If a URL is on this list, when we have a
+   * server to which we can connect using that URL and the associated connection
+   * type we will try to use it.
+   * @return the list of preferred connections.
+   */
+  public LinkedHashSet<PreferredConnection> getPreferredConnections()
+  {
+    return new LinkedHashSet<PreferredConnection>(preferredConnections);
+  }
+
+  /**
    * Returns a Set containing all the servers that are registered in the ADS.
    * @return a Set containing all the servers that are registered in the ADS.
    */
@@ -240,7 +268,8 @@
       Map<ServerProperty,Object> serverProperties)
   {
     return new ServerLoader(serverProperties, dn, pwd,
-        trustManager == null ? null : trustManager.createCopy());
+        trustManager == null ? null : trustManager.createCopy(),
+            getPreferredConnections());
   }
 
   /**
diff --git a/opends/src/ads/org/opends/admin/ads/util/PreferredConnection.java b/opends/src/ads/org/opends/admin/ads/util/PreferredConnection.java
new file mode 100644
index 0000000..5b8b5ed
--- /dev/null
+++ b/opends/src/ads/org/opends/admin/ads/util/PreferredConnection.java
@@ -0,0 +1,147 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE
+ * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at
+ * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
+ * add the following below this CDDL HEADER, with the fields enclosed
+ * by brackets "[]" replaced with your own identifying information:
+ *      Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ *
+ *      Copyright 2008 Sun Microsystems, Inc.
+ */
+
+package org.opends.admin.ads.util;
+
+import javax.naming.ldap.InitialLdapContext;
+
+/**
+ * A simple class that is used to be able to specify which URL and connection
+ * type to use when we connect to a server.
+ */
+public class PreferredConnection
+{
+  private String ldapUrl;
+  private Type type;
+  /**
+   * The type of the connection.
+   */
+  public enum Type
+  {
+    /**
+     * LDAP connection.
+     */
+    LDAP,
+    /**
+     * LDAPS connection.
+     */
+    LDAPS,
+    /**
+     * Start TLS connection.
+     */
+    START_TLS
+  }
+
+  /**
+   * The constructor of the PreferredConnection.
+   * @param ldapUrl the LDAP URL to connect to the server.
+   * @param type the type of connection to be used to connect (required to
+   * differentiate StartTLS and regular LDAP).
+   */
+  public PreferredConnection(String ldapUrl, Type type)
+  {
+    this.ldapUrl = ldapUrl;
+    this.type = type;
+  }
+
+  /**
+   * Returns the LDAP URL to be used.
+   * @return the LDAP URL to be used.
+   */
+  public String getLDAPURL()
+  {
+    return ldapUrl;
+  }
+
+  /**
+   * Returns the type of the connection.
+   * @return the type of the connection.
+   */
+  public Type getType()
+  {
+    return type;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int hashCode()
+  {
+    return (type+ldapUrl.toLowerCase()).hashCode();
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public boolean equals(Object o)
+  {
+    boolean equals = false;
+    if (this != o)
+    {
+      if ((o != null) &&
+      (o instanceof PreferredConnection))
+      {
+        PreferredConnection p = (PreferredConnection)o;
+        equals = type == p.getType() &&
+        ldapUrl.equalsIgnoreCase(p.getLDAPURL());
+      }
+    }
+    else
+    {
+      equals = true;
+    }
+    return equals;
+  }
+
+
+  /**
+   * Commodity method that returns a PreferredConnection object with the
+   * information on a given InitialLdapContext.
+   * @param ctx the connection we retrieve the inforamtion from.
+   * @return a preferred connection object.
+   */
+  public static PreferredConnection getPreferredConnection(
+      InitialLdapContext ctx)
+  {
+    String ldapUrl = ConnectionUtils.getLdapUrl(ctx);
+    PreferredConnection.Type type;
+    if (ConnectionUtils.isStartTLS(ctx))
+    {
+      type = PreferredConnection.Type.START_TLS;
+    }
+    else if (ConnectionUtils.isSSL(ctx))
+    {
+      type = PreferredConnection.Type.LDAPS;
+    }
+    else
+    {
+      type = PreferredConnection.Type.LDAP;
+    }
+    PreferredConnection cnx = new PreferredConnection(ldapUrl, type);
+    return cnx;
+  }
+}
diff --git a/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java b/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java
index 40fd304..f8eda0b 100644
--- a/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java
+++ b/opends/src/ads/org/opends/admin/ads/util/ServerLoader.java
@@ -27,6 +27,7 @@
 
 package org.opends.admin.ads.util;
 
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -60,6 +61,7 @@
   private ApplicationTrustManager trustManager;
   private String dn;
   private String pwd;
+  private LinkedHashSet<PreferredConnection> preferredLDAPURLs;
 
   private static final Logger LOG =
     Logger.getLogger(ServerLoader.class.getName());
@@ -72,14 +74,20 @@
    * @param pwd the password that we must use to bind to the server.
    * @param trustManager the ApplicationTrustManager to be used when we try
    * to connect to the server.
+   * @param preferredLDAPURLs the list of preferred LDAP URLs that we want
+   * to use to connect to the server.  They will be used only if they correspond
+   * to the URLs that we found in the the server properties.
    */
   public ServerLoader(Map<ServerProperty,Object> serverProperties,
-      String dn, String pwd, ApplicationTrustManager trustManager)
+      String dn, String pwd, ApplicationTrustManager trustManager,
+      LinkedHashSet<PreferredConnection> preferredLDAPURLs)
   {
     this.serverProperties = serverProperties;
     this.dn = dn;
     this.pwd = pwd;
     this.trustManager = trustManager;
+    this.preferredLDAPURLs =
+      new LinkedHashSet<PreferredConnection>(preferredLDAPURLs);
   }
 
   /**
@@ -115,14 +123,14 @@
     if (!isOver)
     {
       isInterrupted = true;
-      String ldapUrl = getLdapsUrl(serverProperties);
+      String ldapUrl = getLastLdapUrl();
       if (ldapUrl == null)
       {
-        ldapUrl = getStartTlsLdapUrl(serverProperties);
-      }
-      if (ldapUrl == null)
-      {
-        ldapUrl = getLdapUrl(serverProperties);
+        LinkedHashSet<PreferredConnection> urls = getLDAPURLsByPreference();
+        if (!urls.isEmpty())
+        {
+          ldapUrl = urls.iterator().next().getLDAPURL();
+        }
       }
       lastException = new TopologyCacheException(
           TopologyCacheException.Type.TIMEOUT,
@@ -246,30 +254,35 @@
       String host = (String)serverProperties.get(ServerProperty.HOST_NAME);
       trustManager.setHost(host);
     }
-    lastLdapUrl = getLdapsUrl(serverProperties);
 
-    if (lastLdapUrl == null)
+    /* Try to connect to the server in a certain order of preference.  If an
+     * URL fails, we will try with the others.
+     */
+    LinkedHashSet<PreferredConnection> conns = getLDAPURLsByPreference();
+
+    for (PreferredConnection connection : conns)
     {
-      lastLdapUrl = getStartTlsLdapUrl(serverProperties);
-      if (lastLdapUrl == null)
+      if (ctx == null)
       {
-        lastLdapUrl = getLdapUrl(serverProperties);
-        ctx = ConnectionUtils.createLdapContext(lastLdapUrl, dn, pwd,
-            ConnectionUtils.getDefaultLDAPTimeout(), null);
-      }
-      else
-      {
-        ctx = ConnectionUtils.createStartTLSContext(lastLdapUrl, dn, pwd,
-            ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager,
-            null, null);
+        lastLdapUrl = connection.getLDAPURL();
+        switch (connection.getType())
+        {
+        case LDAPS:
+          ctx = ConnectionUtils.createLdapsContext(lastLdapUrl, dn, pwd,
+              ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager,
+              null);
+          break;
+        case START_TLS:
+          ctx = ConnectionUtils.createStartTLSContext(lastLdapUrl, dn, pwd,
+              ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager,
+              null, null);
+          break;
+        default:
+          ctx = ConnectionUtils.createLdapContext(lastLdapUrl, dn, pwd,
+              ConnectionUtils.getDefaultLDAPTimeout(), null);
+        }
       }
     }
-    else
-    {
-      ctx = ConnectionUtils.createLdapsContext(lastLdapUrl, dn, pwd,
-          ConnectionUtils.getDefaultLDAPTimeout(), null, trustManager, null);
-    }
-
     return ctx;
   }
 
@@ -384,4 +397,60 @@
     }
     return isAdministratorDn;
   }
+
+  /**
+   * Returns the list of LDAP URLs that can be used to connect to the server.
+   * They are ordered so that the first URL is the preferred URL to be used.
+   * @return the list of LDAP URLs that can be used to connect to the server.
+   * They are ordered so that the first URL is the preferred URL to be used.
+   */
+  private LinkedHashSet<PreferredConnection> getLDAPURLsByPreference()
+  {
+    LinkedHashSet<PreferredConnection> ldapUrls =
+      new LinkedHashSet<PreferredConnection>();
+
+    String ldapsUrl = getLdapsUrl(serverProperties);
+    String startTLSUrl = getStartTlsLdapUrl(serverProperties);
+    String ldapUrl = getLdapUrl(serverProperties);
+
+    /**
+     * Check the preferred connections passed in the constructor.
+     */
+    for (PreferredConnection connection : preferredLDAPURLs)
+    {
+      String url = connection.getLDAPURL();
+      if (url.equalsIgnoreCase(ldapsUrl) &&
+          connection.getType() == PreferredConnection.Type.LDAPS)
+      {
+        ldapUrls.add(connection);
+      }
+      else if (url.equalsIgnoreCase(startTLSUrl) &&
+          connection.getType() == PreferredConnection.Type.START_TLS)
+      {
+        ldapUrls.add(connection);
+      }
+      else if (url.equalsIgnoreCase(ldapUrl) &&
+          connection.getType() == PreferredConnection.Type.LDAP)
+      {
+        ldapUrls.add(connection);
+      }
+    }
+
+    if (ldapsUrl != null)
+    {
+      ldapUrls.add(
+          new PreferredConnection(ldapsUrl, PreferredConnection.Type.LDAPS));
+    }
+    if (startTLSUrl != null)
+    {
+      ldapUrls.add(new PreferredConnection(startTLSUrl,
+              PreferredConnection.Type.START_TLS));
+    }
+    if (ldapUrl != null)
+    {
+      ldapUrls.add(new PreferredConnection(ldapUrl,
+          PreferredConnection.Type.LDAP));
+    }
+    return ldapUrls;
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
index fe04f20..b18102b 100644
--- a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
@@ -76,6 +76,7 @@
 import org.opends.admin.ads.ADSContext.AdministratorProperty;
 import org.opends.admin.ads.util.ApplicationTrustManager;
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.admin.ads.util.ServerLoader;
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
@@ -372,7 +373,9 @@
           subcommandLaunched = false;
         }
 
-        if (subcommandLaunched)
+        // Display the log file only if the operation is successful (when there
+        // is a critical error this is already displayed).
+        if (subcommandLaunched && (returnValue == SUCCESSFUL_NOP))
         {
           File logFile = QuickSetupLog.getLogFile();
           if (logFile != null)
@@ -2332,6 +2335,7 @@
           // LDAPConnectionConsoleInteraction object might have changed.
           TopologyCache cache = new TopologyCache(adsContext,
               getTrustManager());
+          cache.setPreferredConnections(getPreferredConnections(ctx[0]));
           cache.reloadTopology();
 
           reloadTopology = false;
@@ -2409,6 +2413,8 @@
                         adminPwd, getTrustManager());
                     adsContext = new ADSContext(ctx[0]);
                     cache = new TopologyCache(adsContext, getTrustManager());
+                    cache.setPreferredConnections(
+                        getPreferredConnections(ctx[0]));
                     connected = true;
                   }
                   catch (Throwable t)
@@ -4104,9 +4110,14 @@
       LinkedHashSet<Message> messages = new LinkedHashSet<Message>();
       try
       {
+        LinkedHashSet<PreferredConnection> cnx =
+          new LinkedHashSet<PreferredConnection>();
+        cnx.addAll(getPreferredConnections(ctx1));
+        cnx.addAll(getPreferredConnections(ctx2));
         if (adsCtx1.hasAdminData())
         {
           TopologyCache cache = new TopologyCache(adsCtx1, getTrustManager());
+          cache.setPreferredConnections(cnx);
           cache.reloadTopology();
           messages.addAll(getErrorMessages(cache));
         }
@@ -4114,6 +4125,7 @@
         if (adsCtx2.hasAdminData())
         {
           TopologyCache cache = new TopologyCache(adsCtx2, getTrustManager());
+          cache.setPreferredConnections(cnx);
           cache.reloadTopology();
           messages.addAll(getErrorMessages(cache));
         }
@@ -4316,9 +4328,14 @@
     TopologyCache cache2 = null;
     try
     {
+      LinkedHashSet<PreferredConnection> cnx =
+        new LinkedHashSet<PreferredConnection>();
+      cnx.addAll(getPreferredConnections(ctx1));
+      cnx.addAll(getPreferredConnections(ctx2));
       if (adsCtx1.hasAdminData())
       {
         cache1 = new TopologyCache(adsCtx1, getTrustManager());
+        cache1.setPreferredConnections(cnx);
         cache1.reloadTopology();
         usedReplicationServerIds.addAll(getReplicationServerIds(cache1));
       }
@@ -4326,6 +4343,7 @@
       if (adsCtx2.hasAdminData())
       {
         cache2 = new TopologyCache(adsCtx2, getTrustManager());
+        cache2.setPreferredConnections(cnx);
         cache2.reloadTopology();
         usedReplicationServerIds.addAll(getReplicationServerIds(cache2));
       }
@@ -4582,6 +4600,7 @@
       if (adsCtx.hasAdminData() && tryToUpdateRemote)
       {
         cache = new TopologyCache(adsCtx, getTrustManager());
+        cache.setPreferredConnections(getPreferredConnections(ctx));
         cache.reloadTopology();
       }
     }
@@ -4732,7 +4751,7 @@
       for (ServerDescriptor s : serversToUpdate)
       {
         removeReferencesInServer(s, replicationServerHostPort, bindDn, pwd,
-            suffixesToDisable, disableAllBaseDns);
+            suffixesToDisable, disableAllBaseDns, getPreferredConnections(ctx));
       }
 
       if (disableAllBaseDns)
@@ -4785,6 +4804,7 @@
     try
     {
       cache = new TopologyCache(adsCtx, getTrustManager());
+      cache.setPreferredConnections(getPreferredConnections(ctx));
       cache.reloadTopology();
     }
     catch (TopologyCacheException tce)
@@ -4904,7 +4924,8 @@
       for (Set<ReplicaDescriptor> replicas : orderedReplicaLists)
       {
         printlnProgress();
-        displayStatus(replicas, uData.isScriptFriendly());
+        displayStatus(replicas, uData.isScriptFriendly(),
+            getPreferredConnections(ctx));
       }
       if (oneReplicated && !uData.isScriptFriendly())
       {
@@ -4920,10 +4941,11 @@
    * that all the replicas have the same baseDN and that if they are replicated
    * all the replicas are replicated with each other.
    * @param replicas the list of replicas that we are trying to display.
+   * @param cnx the preferred connections used to connect to the server.
    * @param scriptFriendly wheter to display it on script-friendly mode or not.
    */
   private void displayStatus(Set<ReplicaDescriptor> replicas,
-      boolean scriptFriendly)
+      boolean scriptFriendly, LinkedHashSet<PreferredConnection> cnx)
   {
 
     boolean isReplicated = false;
@@ -4936,13 +4958,13 @@
       {
         isReplicated = true;
       }
-      hostPorts.add(replica.getServer().getHostPort(true));
+      hostPorts.add(getHostPort(replica.getServer(), cnx));
     }
     for (String hostPort : hostPorts)
     {
       for (ReplicaDescriptor replica : replicas)
       {
-        if (replica.getServer().getHostPort(true).equals(hostPort))
+        if (getHostPort(replica.getServer(), cnx).equals(hostPort))
         {
           orderedReplicas.add(replica);
         }
@@ -5008,7 +5030,7 @@
         switch (j)
         {
         case SERVERPORT:
-          v = Message.raw(replica.getServer().getHostPort(true));
+          v = Message.raw(getHostPort(replica.getServer(), cnx));
           break;
         case NUMBER_ENTRIES:
           int nEntries = replica.getEntries();
@@ -5596,7 +5618,7 @@
               cache.getAdsContext().getDirContext());
 
           ServerLoader loader = new ServerLoader(s.getAdsProperties(),
-              dn, pwd, getTrustManager());
+              dn, pwd, getTrustManager(), cache.getPreferredConnections());
           InitialLdapContext ctx = null;
           try
           {
@@ -5610,13 +5632,15 @@
           }
           catch (NamingException ne)
           {
-            String hostPort = server.getHostPort(true);
+            String hostPort = getHostPort(server,
+                cache.getPreferredConnections());
             Message msg = getMessageForException(ne, hostPort);
             throw new ReplicationCliException(msg, ERROR_CONNECTING, ne);
           }
           catch (OpenDsException ode)
           {
-            String hostPort = server.getHostPort(true);
+            String hostPort = getHostPort(server,
+                cache.getPreferredConnections());
             Message msg = getMessageForEnableException(ode, hostPort, baseDN);
             throw new ReplicationCliException(msg,
                 ERROR_ENABLING_REPLICATION_ON_BASEDN, ode);
@@ -6315,16 +6339,19 @@
    * to the provided replication server.
    * @param removeFromReplicationServers if references must be removed from
    * the replication servers.
+   * @param preferredURLs the preferred LDAP URLs to be used to connect to the
+   * server.
    * @throws ReplicationCliException if there is an error updating the
    * configuration.
    */
   private void removeReferencesInServer(ServerDescriptor server,
       String replicationServer, String bindDn, String pwd,
-      Collection<String> baseDNs, boolean updateReplicationServers)
+      Collection<String> baseDNs, boolean updateReplicationServers,
+      LinkedHashSet<PreferredConnection> cnx)
   throws ReplicationCliException
   {
     ServerLoader loader = new ServerLoader(server.getAdsProperties(), bindDn,
-        pwd, getTrustManager());
+        pwd, getTrustManager(), cnx);
     InitialLdapContext ctx = null;
     String lastBaseDN = null;
     String hostPort = null;
@@ -6435,7 +6462,7 @@
     }
     catch (NamingException ne)
     {
-      hostPort = server.getHostPort(true);
+      hostPort = getHostPort(server, cnx);
       Message msg = getMessageForException(ne, hostPort);
       throw new ReplicationCliException(msg, ERROR_CONNECTING, ne);
     }
@@ -7203,4 +7230,52 @@
     }
     return returnValue;
   }
+
+  /**
+   * Commodity method that generates a list of preferred connection (of just
+   * one) with the information on a given InitialLdapContext.
+   * @param ctx the connection we retrieve the inforamtion from.
+   * @return a list containing the preferred connection object.
+   */
+  private LinkedHashSet<PreferredConnection> getPreferredConnections(
+      InitialLdapContext ctx)
+  {
+    PreferredConnection cnx = PreferredConnection.getPreferredConnection(ctx);
+    LinkedHashSet<PreferredConnection> returnValue =
+      new LinkedHashSet<PreferredConnection>();
+    returnValue.add(cnx);
+    return returnValue;
+  }
+
+  /**
+   * Returns the host port representation of the server to be used in progress,
+   * status and error messages.  It takes into account the fact the host and
+   * port provided by the user.
+   * @param server the ServerDescriptor.
+   * @param cnx the preferred connections list.
+   * @return the host port string representation of the provided server.
+   */
+  protected String getHostPort(ServerDescriptor server,
+      Collection<PreferredConnection> cnx)
+  {
+    String hostPort = null;
+
+    for (PreferredConnection connection : cnx)
+    {
+      String url = connection.getLDAPURL();
+      if (url.equals(server.getLDAPURL()))
+      {
+        hostPort = server.getHostPort(false);
+      }
+      else if (url.equals(server.getLDAPsURL()))
+      {
+        hostPort = server.getHostPort(true);
+      }
+    }
+    if (hostPort == null)
+    {
+      hostPort = server.getHostPort(true);
+    }
+    return hostPort;
+  }
 }
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java b/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
index c19a7a9..31cec31 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
+++ b/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
@@ -41,6 +41,7 @@
 import org.opends.admin.ads.TopologyCacheException;
 import org.opends.admin.ads.util.ApplicationTrustManager;
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.guitools.uninstaller.ui.ConfirmUninstallPanel;
 import org.opends.guitools.uninstaller.ui.LoginDialog;
 import org.opends.quicksetup.ui.*;
@@ -1867,7 +1868,8 @@
         String dn = ADSContext.getAdministratorDN(
             getUninstallUserData().getAdminUID());
         String pwd = getUninstallUserData().getAdminPwd();
-        ctx = getRemoteConnection(server, dn, pwd, getTrustManager());
+        ctx = getRemoteConnection(server, dn, pwd, getTrustManager(),
+            new LinkedHashSet<PreferredConnection>());
 
         // Update replication servers and domains.  If the domain
         // is an ADS, then remove it from there.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opends/src/quicksetup/org/opends/quicksetup/Application.java
index a7b53b9..97e4923 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -34,6 +34,7 @@
 import org.opends.admin.ads.ServerDescriptor;
 import org.opends.admin.ads.TopologyCacheException;
 import org.opends.admin.ads.util.ApplicationTrustManager;
+import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.admin.ads.util.ServerLoader;
 import org.opends.quicksetup.event.ProgressNotifier;
 import org.opends.quicksetup.event.ProgressUpdateListener;
@@ -50,6 +51,7 @@
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.IOException;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -743,17 +745,20 @@
    * connection.
    * @param dn the dn to be used to authenticate.
    * @param pwd the pwd to be used to authenticate.
+   * @param cnx the ordered list of preferred connections to connect to the
+   * server.
    * @return the InitialLdapContext to the remote server.
    * @throws ApplicationException if something goes wrong.
    */
   protected InitialLdapContext getRemoteConnection(ServerDescriptor server,
-      String dn, String pwd, ApplicationTrustManager trustManager)
+      String dn, String pwd, ApplicationTrustManager trustManager,
+      LinkedHashSet<PreferredConnection> cnx)
   throws ApplicationException
   {
     Map<ADSContext.ServerProperty, Object> adsProperties =
       server.getAdsProperties();
     ServerLoader loader = new ServerLoader(adsProperties, dn, pwd,
-        trustManager);
+        trustManager, cnx);
 
     InitialLdapContext ctx = null;
     try
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 617628f..5365efc 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -61,6 +61,7 @@
 import org.opends.admin.ads.TopologyCacheException;
 import org.opends.admin.ads.util.ApplicationTrustManager;
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.admin.ads.util.PreferredConnection;
 import org.opends.quicksetup.ui.*;
 import org.opends.quicksetup.util.Utils;
 
@@ -1451,13 +1452,14 @@
     {
       notifyListeners(getFormattedWithPoints(
           INFO_PROGRESS_UNCONFIGURING_REPLICATION_REMOTE.get(
-                  server.getHostPort(true))));
+                  getHostPort(server))));
       try
       {
-        ctx = getRemoteConnection(server, getTrustManager());
+        ctx = getRemoteConnection(server, getTrustManager(),
+            getPreferredConnections());
         helper.unconfigureReplication(ctx,
             hmConfiguredRemoteReplication.get(server),
-            server.getHostPort(true));
+            ConnectionUtils.getHostPort(ctx));
       }
       catch (ApplicationException ae)
       {
@@ -1647,7 +1649,7 @@
       {
         notifyListeners(getFormattedWithPoints(
             INFO_PROGRESS_CONFIGURING_REPLICATION_REMOTE.get(
-                    server.getHostPort(true))));
+                    getHostPort(server))));
         Integer v = (Integer)server.getServerProperties().get(
             ServerDescriptor.ServerProperty.REPLICATION_SERVER_PORT);
         int replicationPort;
@@ -1671,7 +1673,7 @@
             replicationPort = Constants.DEFAULT_REPLICATION_PORT;
             enableSecureReplication = false;
             LOG.log(Level.WARNING, "Could not find replication port for: "+
-                server.getHostPort(true));
+                getHostPort(server));
           }
         }
         HashSet<String> dns = new HashSet<String>();
@@ -1711,11 +1713,12 @@
         }
 
 
-        ctx = getRemoteConnection(server, getTrustManager());
+        ctx = getRemoteConnection(server, getTrustManager(),
+            getPreferredConnections());
         ConfiguredReplication repl =
           helper.configureReplication(ctx, remoteReplicationServers,
               replicationPort, enableSecureReplication,
-              server.getHostPort(true), knownReplicationServerIds,
+              ConnectionUtils.getHostPort(ctx), knownReplicationServerIds,
               knownServerIds);
         long remoteTimeMeasureTime = System.currentTimeMillis();
         long remoteTime = Utils.getServerClock(ctx);
@@ -2033,7 +2036,8 @@
       InitialLdapContext rCtx = null;
       try
       {
-        rCtx = getRemoteConnection(server, getTrustManager());
+        rCtx = getRemoteConnection(server, getTrustManager(),
+            getPreferredConnections());
         ServerDescriptor s = ServerDescriptor.createStandalone(rCtx);
         for (ReplicaDescriptor replica : s.getReplicas())
         {
@@ -2054,12 +2058,12 @@
         if (Utils.isCertificateException(ne))
         {
           msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(
-              server.getHostPort(true), ne.toString(true));
+              getHostPort(server), ne.toString(true));
         }
         else
         {
            msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(
-               server.getHostPort(true), ne.toString(true));
+               getHostPort(server), ne.toString(true));
         }
         throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg,
             ne);
@@ -2077,7 +2081,7 @@
 
       ReplicaDescriptor replica = suffix.getReplicas().iterator().next();
       ServerDescriptor server = replica.getServer();
-      String hostPort = server.getHostPort(true);
+      String hostPort = getHostPort(server);
 
       boolean isADS = areDnsEqual(dn, ADSContext.getAdministrationSuffixDN());
       boolean isSchema = areDnsEqual(dn, Constants.SCHEMA_DN);
@@ -2114,7 +2118,8 @@
           InitialLdapContext rCtx = null;
           try
           {
-            rCtx = getRemoteConnection(server, getTrustManager());
+            rCtx = getRemoteConnection(server, getTrustManager(),
+                getPreferredConnections());
             ServerDescriptor s = ServerDescriptor.createStandalone(rCtx);
             for (ReplicaDescriptor r : s.getReplicas())
             {
@@ -2130,12 +2135,12 @@
             if (Utils.isCertificateException(ne))
             {
               msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(
-                  server.getHostPort(true), ne.toString(true));
+                  getHostPort(server), ne.toString(true));
             }
             else
             {
                msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(
-                   server.getHostPort(true), ne.toString(true));
+                   getHostPort(server), ne.toString(true));
             }
             throw new ApplicationException(ReturnCode.CONFIGURATION_ERROR, msg,
                 ne);
@@ -2504,6 +2509,40 @@
       DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY;
   }
 
+  /**
+   * Returns the list of preferred URLs to connect to remote servers.  In fact
+   * it returns only the URL to the remote server specified by the user in
+   * the replication options panel.  The method returns a list for convenience
+   * with other interfaces.
+   * NOTE: this method assumes that the UserData object has already been updated
+   * with the host and port of the remote server.
+   * @return the list of preferred URLs to connect to remote servers.
+   */
+  private LinkedHashSet<PreferredConnection> getPreferredConnections()
+  {
+    LinkedHashSet<PreferredConnection> cnx =
+      new LinkedHashSet<PreferredConnection>();
+    DataReplicationOptions repl = getUserData().getReplicationOptions();
+    if (repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY)
+    {
+      AuthenticationData auth = repl.getAuthenticationData();
+      if (auth != null)
+      {
+        PreferredConnection.Type type;
+        if (auth.useSecureConnection())
+        {
+          type = PreferredConnection.Type.LDAPS;
+        }
+        else
+        {
+          type = PreferredConnection.Type.LDAP;
+        }
+        cnx.add(new PreferredConnection(getLdapUrl(auth), type));
+      }
+    }
+    return cnx;
+  }
+
   private String getLdapUrl(AuthenticationData auth)
   {
     String ldapUrl;
@@ -3525,7 +3564,7 @@
             (replicationPort > MAX_PORT_VALUE))
         {
           errorMsgs.add(INFO_INVALID_REMOTE_REPLICATION_PORT_VALUE_RANGE.get(
-                  server.getHostPort(true),
+                  getHostPort(server),
                   String.valueOf(MIN_PORT_VALUE),
                   String.valueOf(MAX_PORT_VALUE)));
         }
@@ -3544,7 +3583,7 @@
           {
             errorMsgs.add(
                   INFO_REMOTE_REPLICATION_PORT_ALREADY_CHOSEN_FOR_OTHER_PROTOCOL
-                          .get(server.getHostPort(true)));
+                          .get(getHostPort(server)));
           }
         }
         AuthenticationData authData = new AuthenticationData();
@@ -3763,6 +3802,13 @@
       type = SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY;
     }
     lastLoadedCache = new TopologyCache(adsContext, trustManager);
+    LinkedHashSet<PreferredConnection> cnx =
+      new LinkedHashSet<PreferredConnection>();
+    cnx.add(PreferredConnection.getPreferredConnection(
+        adsContext.getDirContext()));
+    // We cannot use getPreferredConnections since the user data has not been
+    // updated yet.
+    lastLoadedCache.setPreferredConnections(cnx);
     lastLoadedCache.reloadTopology();
     Set<SuffixDescriptor> suffixes = lastLoadedCache.getSuffixes();
 
@@ -4015,11 +4061,15 @@
    * @param server the object describing the server.
    * @param trustManager the trust manager to be used to establish the
    * connection.
+   * @param preferredURLs the list of preferred LDAP URLs to be used to connect
+   * to the server.
    * @return the InitialLdapContext to the remote server.
    * @throws ApplicationException if something goes wrong.
    */
   private InitialLdapContext getRemoteConnection(ServerDescriptor server,
-      ApplicationTrustManager trustManager) throws ApplicationException
+      ApplicationTrustManager trustManager,
+      LinkedHashSet<PreferredConnection> cnx)
+  throws ApplicationException
   {
     Map<ADSContext.ServerProperty, Object> adsProperties;
     AuthenticationData auth =
@@ -4052,7 +4102,7 @@
       server.setAdsProperties(adsProperties);
     }
     return  getRemoteConnection(server, auth.getDn(), auth.getPwd(),
-        trustManager);
+        trustManager, cnx);
   }
 
   /**
@@ -4315,6 +4365,7 @@
             LOG.log(Level.INFO, "Initialization completed successfully.");
             notifyListeners(getFormattedProgress(
                 INFO_SUFFIX_INITIALIZED_SUCCESSFULLY.get()));
+            notifyListeners(getLineBreak());
           }
         }
       }
@@ -4326,6 +4377,7 @@
         {
           notifyListeners(getFormattedProgress(
             INFO_SUFFIX_INITIALIZED_SUCCESSFULLY.get()));
+          notifyListeners(getLineBreak());
         }
       }
       catch (NamingException ne)
@@ -4574,6 +4626,39 @@
           Utils.getThrowableMsg(INFO_BUG_MSG.get(), t), t);
     }
   }
+
+
+  /**
+   * Returns the host port representation of the server to be used in progress
+   * and error messages.  It takes into account the fact the host and port
+   * provided by the user in the replication options panel.
+   * NOTE: the code assumes that the user data with the contents of the
+   * replication options has already been updated.
+   * @param server the ServerDescriptor.
+   * @return the host port string representation of the provided server.
+   */
+  protected String getHostPort(ServerDescriptor server)
+  {
+    String hostPort = null;
+
+    for (PreferredConnection connection : getPreferredConnections())
+    {
+      String url = connection.getLDAPURL();
+      if (url.equals(server.getLDAPURL()))
+      {
+        hostPort = server.getHostPort(false);
+      }
+      else if (url.equals(server.getLDAPsURL()))
+      {
+        hostPort = server.getHostPort(true);
+      }
+    }
+    if (hostPort == null)
+    {
+      hostPort = server.getHostPort(true);
+    }
+    return hostPort;
+  }
 }
 
 /**
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java b/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
index d4cc645..ef8a021 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/ServerController.java
@@ -403,7 +403,7 @@
           boolean connected = false;
           Configuration config = installation.getCurrentConfiguration();
           int port = config.getPort();
-          String ldapUrl = "ldap://localhost:" + port;
+          String ldapUrl = "ldap://0.0.0.0:" + port;
 
           // See if the application has prompted for credentials.  If
           // not we'll just try to connect anonymously.

--
Gitblit v1.10.0