From eb93a7bf09123d5fe7a8509e4a1421101163b670 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Fri, 08 Jun 2007 14:43:45 +0000
Subject: [PATCH] The following commit adds all the code necessary to be able to configure replication using the setup.

---
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java                |  442 ++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                      | 2157 +++++++++++++++++++----
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FieldName.java                             |   18 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetupLog.java                            |    3 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/DataReplicationOptions.java         |   13 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java       |  110 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java         |   14 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java                             |    8 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                               |  422 ++-
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SuffixesToReplicatePanel.java    |   66 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java                      |   13 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserData.java                                 |   91 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java       |   71 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Step.java                                     |    5 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/InstallReviewPanel.java          |  131 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java                            |  108 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties                |  183 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java                              |   18 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataCertificateException.java             |  134 +
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/images/wait.gif                               |    0 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataConfirmationException.java            |    2 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java                           |   12 
 opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java                         |   12 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SecurityOptions.java                          |   33 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java     |  105 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java          |    4 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java            |   20 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java                            |   26 
 opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties              |    1 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/DataReplicationPanel.java        |   76 
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RemoteReplicationPortsPanel.java |  310 +++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CertificateDialog.java                     |  655 +++++++
 opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java                        |   44 
 33 files changed, 4,476 insertions(+), 831 deletions(-)

diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java
index eda03c8..4fa82af 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -27,6 +27,7 @@
 
 package org.opends.quicksetup;
 
+import org.opends.admin.ads.util.ApplicationTrustManager;
 import org.opends.quicksetup.event.ProgressNotifier;
 import org.opends.quicksetup.event.ProgressUpdateListener;
 import org.opends.quicksetup.event.ProgressUpdateEvent;
@@ -64,6 +65,8 @@
 
   private ServerController serverController;
 
+  private ApplicationTrustManager trustManager;
+
   /** Formats progress messages. */
   protected ProgressMessageFormatter formatter;
 
@@ -526,6 +529,21 @@
   abstract public boolean isFinished();
 
   /**
+   * Returns the trust manager that can be used to establish secure connections.
+   * @return the trust manager that can be used to establish secure connections.
+   */
+  protected ApplicationTrustManager getTrustManager()
+  {
+    if (trustManager == null)
+    {
+      trustManager = new ApplicationTrustManager();
+    }
+    return trustManager;
+  }
+
+
+
+  /**
    * Indicates whether or not this application is capable of cancelling
    * the operation performed in the run method.  A cancellable operation
    * should leave its environment in the same state as it was prior to
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetupLog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetupLog.java
index 43e6ed2..36619dc 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetupLog.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/QuickSetupLog.java
@@ -58,6 +58,9 @@
       logger.setUseParentHandlers(false); // disable logging to console
       logger.addHandler(fileHandler);
       logger.log(Level.INFO, getInitialLogRecord());
+      logger = Logger.getLogger("org.opends.admin.ads");
+      logger.setUseParentHandlers(false); // disable logging to console
+      logger.addHandler(fileHandler);
     }
   }
 
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SecurityOptions.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SecurityOptions.java
index 178a5a1..58cfab1 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SecurityOptions.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/SecurityOptions.java
@@ -65,8 +65,6 @@
   }
 
   private CertificateType certificateType;
-
-  private String selfSignedCertificateName;
   private String keyStorePath;
   private String keyStorePassword;
   private String aliasToUse;
@@ -93,19 +91,17 @@
   /**
    * Creates a new instance of a SecurityOptions using a self-signed
    * certificate.
-   * @param name the name of the certificate (the CN value).
    * @param enableSSL whether SSL is enabled or not.
    * @param enableStartTLS whether Start TLS is enabled or not.
    * @param sslPort the value of the LDAPS port.
    * @return a new instance of a SecurityOptions using a self-signed
    * certificate.
    */
-  public static SecurityOptions createSelfSignedCertificateOptions(String name,
+  public static SecurityOptions createSelfSignedCertificateOptions(
       boolean enableSSL, boolean enableStartTLS, int sslPort)
   {
     SecurityOptions ops = new SecurityOptions();
     ops.setCertificateType(CertificateType.SELF_SIGNED_CERTIFICATE);
-    ops.setSelfSignedCertificateName(name);
     updateCertificateOptions(ops, enableSSL, enableStartTLS, sslPort, null);
     return ops;
   }
@@ -270,24 +266,6 @@
   }
 
   /**
-   * Returns the self-signed certificate name.
-   * @return the self-signed certificate name.
-   */
-  public String getSelfSignedCertificateName()
-  {
-    return selfSignedCertificateName;
-  }
-
-  /**
-   * Sets the self-signed certificate name.
-   * @param selfSignedCertificateName the new self-signed certificate name.
-   */
-  private void setSelfSignedCertificateName(String selfSignedCertificateName)
-  {
-    this.selfSignedCertificateName = selfSignedCertificateName;
-  }
-
-  /**
    * Updates the provided certificate options object with some parameters.
    * @param ops the SecurityOptions object to be updated.
    * @param enableSSL whether to enable SSL or not.
@@ -328,15 +306,6 @@
   }
 
   /**
-   * Sets the Self-Signed certificate name (the CN).
-   * @param selfSignedCertificateName the new Self-Signed certificate name.
-   */
-  void setCertificateUserName(String selfSignedCertificateName)
-  {
-    this.selfSignedCertificateName = selfSignedCertificateName;
-  }
-
-  /**
    * Returns the alias of the certificate in the keystore to be used.
    * @return the alias of the certificate in the keystore to be used.
    */
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Step.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Step.java
index bf532dc..be3d2ec 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Step.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Step.java
@@ -63,6 +63,11 @@
    */
   SUFFIXES_OPTIONS("suffixes-step"),
   /**
+   * Panel when the user specifies the replication ports of the remote servers
+   * that have not defined it.
+   */
+  REMOTE_REPLICATION_PORTS("remote-replication-ports-step"),
+  /**
    * Data Options panel (suffix dn, LDIF path, etc.).
    */
   NEW_SUFFIX_OPTIONS("data-options-step"),
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserData.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserData.java
index 38051d7..7aa2a7b 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserData.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserData.java
@@ -27,8 +27,11 @@
 
 package org.opends.quicksetup;
 
+import java.util.HashMap;
 import java.util.HashSet;
+import java.util.Map;
 
+import org.opends.admin.ads.ServerDescriptor;
 import org.opends.admin.ads.SuffixDescriptor;
 import org.opends.quicksetup.installer.AuthenticationData;
 import org.opends.quicksetup.installer.DataReplicationOptions;
@@ -47,6 +50,8 @@
 {
   private String serverLocation;
 
+  private String hostName;
+
   private int serverPort;
 
   private String directoryManagerDn;
@@ -72,6 +77,8 @@
 
   private SuffixesToReplicateOptions suffixesToReplicateOptions;
 
+  private Map<ServerDescriptor, Integer> remoteWithNoReplicationPort;
+
   private boolean silent;
 
   private boolean noninteractive;
@@ -93,6 +100,8 @@
       setServerPort(defaultPort);
     }
 
+    setHostName(getDefaultHostName());
+
     setDirectoryManagerDn(Constants.DIRECTORY_MANAGER_DN);
 
     setNewSuffixOptions(defaultNewSuffixOptions);
@@ -100,7 +109,8 @@
     data.setDn(Constants.DIRECTORY_MANAGER_DN);
     data.setPort(389);
     DataReplicationOptions repl = new DataReplicationOptions(
-        DataReplicationOptions.Type.STANDALONE, data);
+        DataReplicationOptions.Type.STANDALONE, data,
+        getDefaultReplicationPort());
     setReplicationOptions(repl);
     setGlobalAdministratorUID("admin");
 
@@ -112,8 +122,9 @@
     setSuffixesToReplicateOptions(suffixes);
     SecurityOptions sec = SecurityOptions.createNoCertificateOptions();
     sec.setSslPort(getDefaultSslPort());
-    sec.setCertificateUserName(getDefaultSelfSignedName());
     setSecurityOptions(sec);
+
+    remoteWithNoReplicationPort = new HashMap<ServerDescriptor, Integer>();
   }
 
   /**
@@ -135,6 +146,24 @@
   }
 
   /**
+   * Sets the host name.
+   * @param hostName the server host name.
+   */
+  public void setHostName(String hostName)
+  {
+    this.hostName = hostName;
+  }
+
+  /**
+   * Returns the server host name.
+   * @return the server host name.
+   */
+  public String getHostName()
+  {
+    return hostName;
+  }
+
+  /**
    * Sets the server LDAP port.
    * @param serverPort the new server LDAP port.
    */
@@ -498,11 +527,34 @@
     }
     return defaultJMXPort;
   }
+
   /**
-   * Provides the default name for the self signed certificate that will be
-   * created.
+   * Provides the port that will be proposed to the user in the replication
+   * options panel of the installation wizard. It will check whether we can use
+   * ports of type X989 and if not it will return -1.
+   *
+   * @return the free port of type X989 if it is available and we can use and -1
+   * if not.
    */
-  private String getDefaultSelfSignedName()
+  static int getDefaultReplicationPort()
+  {
+    int defaultPort = -1;
+
+    for (int i=0;i<10000 && (defaultPort == -1);i+=1000)
+    {
+      int port = i + 8989;
+      if (Utils.canUseAsPort(port))
+      {
+        defaultPort = port;
+      }
+    }
+    return defaultPort;
+  }
+
+  /**
+   * Provides the default host name that will be displayed.
+   */
+  private String getDefaultHostName()
   {
     String name = "";
     try
@@ -514,4 +566,33 @@
     }
     return name;
   }
+
+  /**
+   * Returns a Map containing as key a ServerDescriptor and as value an Integer
+   * corresponding to the Replication Port chosen by the user.
+   *
+   * Only the servers that have no replication port appear on this map.
+   * @return a Map containing as key a ServerDescriptor and as value an Integer
+   * corresponding to the Replication Port chosen by the user.
+   */
+  public Map<ServerDescriptor, Integer> getRemoteWithNoReplicationPort()
+  {
+    HashMap<ServerDescriptor, Integer> copy =
+      new HashMap<ServerDescriptor, Integer>();
+    copy.putAll(remoteWithNoReplicationPort);
+    return copy;
+  }
+
+  /**
+   * Sets a the Replication Ports chosen by the user in the remote servers.
+   * @param remoteWithNoReplicationPort the Map containing as key a
+   * ServerDescriptor and as value an Integer corresponding to the Replication
+   * Port chosen by the user.
+   */
+  public void setRemoteWithNoReplicationPort(
+      Map<ServerDescriptor, Integer> remoteWithNoReplicationPort)
+  {
+    this.remoteWithNoReplicationPort.clear();
+    this.remoteWithNoReplicationPort.putAll(remoteWithNoReplicationPort);
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataCertificateException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataCertificateException.java
new file mode 100644
index 0000000..3d3727d4
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataCertificateException.java
@@ -0,0 +1,134 @@
+/*
+ * 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
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup;
+
+import java.security.cert.X509Certificate;
+
+/**
+ * This exception is used when there is a certificate issue and the user must
+ * be asked to accept it or not.
+ * It will be thrown by the class that is in charge of validating the user data
+ * (the Application class).
+ *
+ */
+public class UserDataCertificateException extends UserDataException
+{
+  private String host;
+  private int port;
+  private X509Certificate[] chain;
+  private String authType;
+  private Type type;
+  /**
+   * The enumeration for the different types of the exception.
+   */
+  public enum Type
+  {
+    /**
+     * The certificate was not trusted.
+     */
+    NOT_TRUSTED,
+    /**
+     * The certificate's subject DN's value and the host name we tried to
+     * connect to do not match.
+     */
+    HOST_NAME_MISMATCH
+  }
+
+  private static final long serialVersionUID = 6404258710409027956L;
+
+  /**
+   * Constructor for UserDataCertificateException.
+   * @param step the step in the wizard where the exception occurred.
+   * @param localizedMessage the localized message describing the error.
+   * @param t the root cause for this exception.
+   * @param host the host we tried to connect to.
+   * @param port the port we tried to connect to.
+   * @param chain the certificate chain.
+   * @param authType the authentication type.
+   * @param type the type of the exception.
+   */
+  public UserDataCertificateException(WizardStep step, String localizedMessage,
+      Throwable t, String host, int port, X509Certificate[] chain,
+      String authType, Type type)
+  {
+    super(step, localizedMessage);
+    initCause(t);
+    this.host = host;
+    this.port = port;
+    this.chain = chain;
+    this.authType = authType;
+    this.type = type;
+  }
+
+  /**
+   * Returns the host we tried to connect to when this exception was generated.
+   * @return the host we tried to connect to when this exception was generated.
+   */
+  public String getHost()
+  {
+    return host;
+  }
+
+  /**
+   * Returns the port we tried to connect to when this exception was generated.
+   * @return the port we tried to connect to when this exception was generated.
+   */
+  public int getPort()
+  {
+    return port;
+  }
+
+  /**
+   * Returns the auth type used when this certificate exception occurred.
+   * @return the auth type used when this certificate exception occurred.
+   */
+  public String getAuthType()
+  {
+    return authType;
+  }
+
+  /**
+   * Returns the type of exception.
+   * @return the type of exception.
+   */
+  public Type getType()
+  {
+    return type;
+  }
+
+  /**
+   * Returns the certificate chain received when this exception was generated.
+   * @return the certificate chain received when this exception was generated.
+   */
+  public X509Certificate[] getChain()
+  {
+    return chain;
+  }
+}
+
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataConfirmationException.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataConfirmationException.java
index c36e47f..951b493 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataConfirmationException.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/UserDataConfirmationException.java
@@ -38,7 +38,7 @@
   private static final long serialVersionUID = -2662491859817280513L;
 
   /**
-   * Constructor for UserDataException.
+   * Constructor for UserDataConfirmationException.
    * @param step the step in the wizard where the exception occurred.
    * @param localizedMessage the localized message describing the error.
    */
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/images/wait.gif b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/images/wait.gif
new file mode 100644
index 0000000..286e1bc
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/images/wait.gif
Binary files differ
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/DataReplicationOptions.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/DataReplicationOptions.java
index 32d4596..8a78b43 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/DataReplicationOptions.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/DataReplicationOptions.java
@@ -57,6 +57,7 @@
   }
 
   private Type type;
+  private int replicationPort;
   private AuthenticationData authenticationData;
 
   /**
@@ -80,6 +81,7 @@
     {
     case IN_EXISTING_TOPOLOGY:
       authenticationData = (AuthenticationData)args[0];
+      replicationPort = (Integer)args[1];
       break;
 
     default:
@@ -87,6 +89,7 @@
       if ((args != null) && (args.length > 0))
       {
         authenticationData = (AuthenticationData)args[0];
+        replicationPort = (Integer)args[1];
       }
     }
   }
@@ -112,5 +115,15 @@
   {
     return authenticationData;
   }
+
+  /**
+   * Returns the port that is going to be used for replication.
+   *
+   * @return the replication that must be used to configure replication.
+   */
+  public int getReplicationPort()
+  {
+    return replicationPort;
+  }
 }
 
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
index e9637d0..e4771ed 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallProgressStep.java
@@ -72,11 +72,31 @@
   IMPORTING_AUTOMATICALLY_GENERATED,
 
   /**
+   * Configuring replication.
+   */
+  CONFIGURING_REPLICATION,
+
+  /**
    * Starting Open DS server.
    */
   STARTING_SERVER,
 
   /**
+   * Stopping Open DS server.
+   */
+  STOPPING_SERVER,
+
+  /**
+   * Initialize Replicated Suffixes.
+   */
+  INITIALIZE_REPLICATED_SUFFIXES,
+
+  /**
+   * Configuring ADS.
+   */
+  CONFIGURING_ADS,
+
+  /**
    * Enabling Windows service.
    */
   ENABLING_WINDOWS_SERVICE,
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 0ec86d3..96e376a 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -31,23 +31,40 @@
 import java.io.File;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.net.URI;
 import java.security.KeyStoreException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateEncodingException;
 import java.util.*;
+import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.awt.event.WindowEvent;
 
+import javax.naming.AuthenticationException;
+import javax.naming.NameAlreadyBoundException;
+import javax.naming.NameNotFoundException;
+import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
 import javax.naming.NoPermissionException;
+import javax.naming.directory.Attribute;
+import javax.naming.directory.BasicAttribute;
+import javax.naming.directory.BasicAttributes;
+import javax.naming.directory.DirContext;
+import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
 import javax.naming.ldap.InitialLdapContext;
 
 import org.opends.admin.ads.ADSContext;
 import org.opends.admin.ads.ADSContextException;
+import org.opends.admin.ads.ReplicaDescriptor;
+import org.opends.admin.ads.ServerDescriptor;
 import org.opends.admin.ads.SuffixDescriptor;
+import org.opends.admin.ads.TopologyCache;
+import org.opends.admin.ads.TopologyCacheException;
+import org.opends.admin.ads.util.ApplicationTrustManager;
+import org.opends.admin.ads.util.ServerLoader;
 import org.opends.quicksetup.ui.*;
 import org.opends.quicksetup.util.Utils;
-import org.opends.quicksetup.util.InProcessServerController;
 import org.opends.quicksetup.*;
 import org.opends.server.util.CertificateManager;
 import org.opends.quicksetup.installer.ui.DataOptionsPanel;
@@ -55,6 +72,7 @@
 import org.opends.quicksetup.installer.ui.GlobalAdministratorPanel;
 import org.opends.quicksetup.installer.ui.InstallReviewPanel;
 import org.opends.quicksetup.installer.ui.InstallWelcomePanel;
+import org.opends.quicksetup.installer.ui.RemoteReplicationPortsPanel;
 import org.opends.quicksetup.installer.ui.ServerSettingsPanel;
 import org.opends.quicksetup.installer.ui.SuffixesToReplicatePanel;
 import org.opends.server.util.SetupUtils;
@@ -80,6 +98,7 @@
  *
  */
 public abstract class Installer extends GuiApplication {
+  private TopologyCache lastLoadedCache;
 
   /* Indicates that we've detected that there is something installed */
   boolean forceToDisplaySetup = false;
@@ -108,9 +127,11 @@
   private final HashSet<WizardStep> SUBSTEPS = new HashSet<WizardStep>();
   {
     SUBSTEPS.add(Step.CREATE_GLOBAL_ADMINISTRATOR);
-//  TODO: remove this comment once the replication code is in place.
     SUBSTEPS.add(Step.SUFFIXES_OPTIONS);
+    // TODO: remove this comment once we want to display the replication options
+    // in setup.
     //SUBSTEPS.add(Step.NEW_SUFFIX_OPTIONS);
+    SUBSTEPS.add(Step.REMOTE_REPLICATION_PORTS);
   }
 
   private HashMap<WizardStep, WizardStep> hmPreviousSteps =
@@ -128,10 +149,13 @@
   public Installer() {
     lstSteps.add(WELCOME);
     lstSteps.add(SERVER_SETTINGS);
+    // TODO: remove this comment once we want to display the replication options
+    // in setup.
     /*
     lstSteps.add(REPLICATION_OPTIONS);
     lstSteps.add(CREATE_GLOBAL_ADMINISTRATOR);
     lstSteps.add(SUFFIXES_OPTIONS);
+    lstSteps.add(REMOTE_REPLICATION_PORTS);
     */
     lstSteps.add(NEW_SUFFIX_OPTIONS);
     lstSteps.add(REVIEW);
@@ -247,11 +271,19 @@
         isVisible = false;
       }
     }
+    else if (step == REMOTE_REPLICATION_PORTS)
+    {
+      isVisible = isVisible(SUFFIXES_OPTIONS) &&
+      (getUserData().getRemoteWithNoReplicationPort().size() > 0) &&
+      (getUserData().getSuffixesToReplicateOptions().getType() ==
+        SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES);
+    }
     else
     {
       isVisible = true;
     }
-    // TODO: to delete the following line once the replication code works.
+    // TODO: remove this line once we want to display the replication options
+    // in setup.
     isVisible = true;
     return isVisible;
   }
@@ -388,6 +420,8 @@
       p = new GlobalAdministratorPanel(this);
     } else if (step == SUFFIXES_OPTIONS) {
       p = new SuffixesToReplicatePanel(this);
+    } else if (step == REMOTE_REPLICATION_PORTS) {
+      p = new RemoteReplicationPortsPanel(this);
     } else if (step == NEW_SUFFIX_OPTIONS) {
         p = new DataOptionsPanel(this);
     } else if (step == REVIEW) {
@@ -538,12 +572,24 @@
           getType())
       {
       case REPLICATE_WITH_EXISTING_SUFFIXES:
-        next = Step.REVIEW;
+
+        if (getUserData().getRemoteWithNoReplicationPort().size() > 0)
+        {
+          next = Step.REMOTE_REPLICATION_PORTS;
+        }
+        else
+        {
+          next = Step.REVIEW;
+        }
         break;
       default:
         next = Step.NEW_SUFFIX_OPTIONS;
       }
     }
+    else if (step == Step.REMOTE_REPLICATION_PORTS)
+    {
+      next = Step.REVIEW;
+    }
     else
     {
       int i = lstSteps.indexOf(step);
@@ -566,11 +612,13 @@
     LinkedHashSet<WizardStep> orderedSteps = new LinkedHashSet<WizardStep>();
     orderedSteps.add(WELCOME);
     orderedSteps.add(SERVER_SETTINGS);
-    // TODO: remove this comment once the replication code is in place.
+    // TODO: remove this comment once we want to display the replication options
+    // in setup.
     /*
     orderedSteps.add(REPLICATION_OPTIONS);
     orderedSteps.add(CREATE_GLOBAL_ADMINISTRATOR);
     orderedSteps.add(SUFFIXES_OPTIONS);
+    orderedSteps.add(REMOTE_REPLICATION_PORTS);
     */
     orderedSteps.add(NEW_SUFFIX_OPTIONS);
     orderedSteps.add(REVIEW);
@@ -637,6 +685,8 @@
     argList.add(String.valueOf(getUserData().getServerPort()));
 
     SecurityOptions sec = getUserData().getSecurityOptions();
+    // TODO: even if the user does not configure SSL maybe we should choose
+    // a secure port that is not being used and that we can actually use.
     if (sec.getEnableSSL())
     {
       argList.add("-P");
@@ -710,6 +760,17 @@
       argList.add("-b");
       argList.add(getUserData().getNewSuffixOptions().getBaseDn());
     }
+    else
+    {
+      Set<SuffixDescriptor> suffixesToReplicate =
+        getUserData().getSuffixesToReplicateOptions().getSuffixes();
+
+      for (SuffixDescriptor suffix: suffixesToReplicate)
+      {
+        argList.add("-b");
+        argList.add(suffix.getDN());
+      }
+    }
 
     String[] args = new String[argList.size()];
     argList.toArray(args);
@@ -755,7 +816,7 @@
             CertificateManager.KEY_STORE_TYPE_JKS,
             pwd);
         certManager.generateSelfSignedCertificate("server-cert",
-            getSelfSignedCertificateSubjectDN(sec),
+            getSelfSignedCertificateSubjectDN(),
             getSelfSignedCertificateValidity());
         exportCertificate(certManager, "server-cert",
             getTemporaryCertificatePath());
@@ -844,7 +905,7 @@
    * the UserData object provided in the constructor.
    * @throws ApplicationException if something goes wrong.
    */
-  protected void createBaseEntry() throws ApplicationException {
+  private void createBaseEntry() throws ApplicationException {
     String[] arg =
       { getUserData().getNewSuffixOptions().getBaseDn() };
     notifyListeners(getFormattedWithPoints(
@@ -897,7 +958,7 @@
    * the UserData object provided in the constructor.
    * @throws ApplicationException if something goes wrong.
    */
-  protected void importLDIF() throws ApplicationException {
+  private void importLDIF() throws ApplicationException {
     String[] arg =
       { getUserData().getNewSuffixOptions().getLDIFPath() };
     notifyListeners(getFormattedProgress(getMsg("progress-importing-ldif", arg))
@@ -941,7 +1002,7 @@
    * of the UserData object provided in the constructor.
    * @throws ApplicationException if something goes wrong.
    */
-  protected void importAutomaticallyGenerated() throws ApplicationException {
+  private void importAutomaticallyGenerated() throws ApplicationException {
     File templatePath = createTemplateFile();
     int nEntries = getUserData().getNewSuffixOptions().getNumberEntries();
     String[] arg =
@@ -987,6 +1048,190 @@
   }
 
   /**
+   * This method creates the replication configuration for the suffixes on the
+   * the local server (and eventually in the remote servers) to synchronize
+   * things.
+   * NOTE: this method assumes that the server is running.
+   * @throws ApplicationException if something goes wrong.
+   */
+  protected void configureReplication() throws ApplicationException
+  {
+    notifyListeners(getFormattedWithPoints(
+        getMsg("progress-configuring-replication")));
+
+    InstallerHelper helper = new InstallerHelper();
+    Set<Integer> knownServerIds = new HashSet<Integer>();
+    Set<Integer> knownReplicationServerIds = new HashSet<Integer>();
+    if (lastLoadedCache != null)
+    {
+      for (SuffixDescriptor suffix : lastLoadedCache.getSuffixes())
+      {
+        for (ReplicaDescriptor replica : suffix.getReplicas())
+        {
+          knownServerIds.add(replica.getReplicationId());
+        }
+      }
+      for (ServerDescriptor server : lastLoadedCache.getServers())
+      {
+        Object v = server.getServerProperties().get
+        (ServerDescriptor.ServerProperty.REPLICATION_SERVER_ID);
+        if (v != null)
+        {
+          knownReplicationServerIds.add((Integer)v);
+        }
+      }
+    }
+    else
+    {
+      /* There is no ADS anywhere.  Just use the SuffixDescriptors we found */
+      for (SuffixDescriptor suffix :
+        getUserData().getSuffixesToReplicateOptions().getAvailableSuffixes())
+      {
+        for (ReplicaDescriptor replica : suffix.getReplicas())
+        {
+          knownServerIds.add(replica.getReplicationId());
+          Object v = replica.getServer().getServerProperties().get
+          (ServerDescriptor.ServerProperty.REPLICATION_SERVER_ID);
+          if (v != null)
+          {
+            knownReplicationServerIds.add((Integer)v);
+          }
+        }
+      }
+    }
+    Set<String> dns = new HashSet<String>();
+    DataReplicationOptions rep = getUserData().getReplicationOptions();
+    String newReplicationServer = getLocalReplicationServer();
+
+    Map<String, Set<String>> replicationServers =
+      new HashMap<String, Set<String>>();
+
+    if (rep.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY)
+    {
+      String dn = getUserData().getNewSuffixOptions().getBaseDn();
+      dns.add(dn);
+      HashSet<String> h = new HashSet<String>();
+      h.add(newReplicationServer);
+      replicationServers.put(dn, h);
+    }
+    else
+    {
+      Set<SuffixDescriptor> suffixes =
+        getUserData().getSuffixesToReplicateOptions().getSuffixes();
+      for (SuffixDescriptor suffix : suffixes)
+      {
+        dns.add(suffix.getDN());
+        HashSet<String> h = new HashSet<String>();
+        h.addAll(suffix.getReplicationServers());
+        h.add(newReplicationServer);
+        for (ReplicaDescriptor replica : suffix.getReplicas())
+        {
+          ServerDescriptor server = replica.getServer();
+          Integer replicationPort = getUserData().
+          getRemoteWithNoReplicationPort().get(server);
+          if (replicationPort != null)
+          {
+            h.add(server.getHostName()+":"+replicationPort);
+          }
+        }
+        replicationServers.put(suffix.getDN(), h);
+      }
+    }
+
+    InitialLdapContext ctx = null;
+    try
+    {
+      ctx = createLocalContext();
+      helper.configureReplication(ctx, dns, replicationServers,
+          getUserData().getReplicationOptions().getReplicationPort(),
+          getLocalHostPort(),
+          knownReplicationServerIds, knownServerIds);
+    }
+    catch (ApplicationException ae)
+    {
+      throw ae;
+    }
+    catch (NamingException ne)
+    {
+      String failedMsg = getThrowableMsg("error-connecting-to-local", null, ne);
+      throw new ApplicationException(
+          ApplicationException.Type.CONFIGURATION_ERROR, failedMsg, ne);
+    }
+    finally
+    {
+      try
+      {
+        if (ctx != null)
+        {
+          ctx.close();
+        }
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    notifyListeners(getFormattedDone());
+
+    if (rep.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY)
+    {
+      Map<ServerDescriptor, Set<ReplicaDescriptor>> hm =
+        new HashMap<ServerDescriptor, Set<ReplicaDescriptor>>();
+      for (SuffixDescriptor suffix :
+        getUserData().getSuffixesToReplicateOptions().getSuffixes())
+      {
+        for (ReplicaDescriptor replica : suffix.getReplicas())
+        {
+          Set<ReplicaDescriptor> replicas = hm.get(replica.getServer());
+          if (replicas == null)
+          {
+            replicas = new HashSet<ReplicaDescriptor>();
+            hm.put(replica.getServer(), replicas);
+          }
+          replicas.add(replica);
+        }
+      }
+      for (ServerDescriptor server : hm.keySet())
+      {
+        notifyListeners(getLineBreak());
+        notifyListeners(getFormattedWithPoints(
+            getMsg("progress-configuring-replication-remote",
+                server.getHostPort(true))));
+        Integer v = (Integer)server.getServerProperties().get(
+            ServerDescriptor.ServerProperty.REPLICATION_SERVER_PORT);
+        int replicationPort;
+        if (v != null)
+        {
+          replicationPort = v;
+        }
+        else
+        {
+          replicationPort =
+            getUserData().getRemoteWithNoReplicationPort().get(server);
+        }
+        dns = new HashSet<String>();
+        for (ReplicaDescriptor replica : hm.get(server))
+        {
+          dns.add(replica.getSuffix().getDN());
+        }
+
+        ctx = getRemoteConnection(server, getTrustManager());
+        helper.configureReplication(ctx, dns, replicationServers,
+            replicationPort, server.getHostPort(true),
+            knownReplicationServerIds, knownServerIds);
+
+        try
+        {
+          ctx.close();
+        }
+        catch (Throwable t)
+        {
+        }
+        notifyListeners(getFormattedDone());
+      }
+    }
+  }
+
+  /**
    * This methods enables this server as a Windows service.
    * @throws ApplicationException if something goes wrong.
    */
@@ -1021,8 +1266,16 @@
         InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
         getFormattedSummary(
             getMsg("summary-importing-automatically-generated")));
+    hmSummary.put(InstallProgressStep.CONFIGURING_REPLICATION,
+        getFormattedSummary(getMsg("summary-configuring-replication")));
     hmSummary.put(InstallProgressStep.STARTING_SERVER,
         getFormattedSummary(getMsg("summary-starting")));
+    hmSummary.put(InstallProgressStep.STOPPING_SERVER,
+        getFormattedSummary(getMsg("summary-stopping")));
+    hmSummary.put(InstallProgressStep.CONFIGURING_ADS,
+        getFormattedSummary(getMsg("summary-configuring-ads")));
+    hmSummary.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES,
+        getFormattedSummary(getMsg("summary-initialize-replicated-suffixes")));
     hmSummary.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE,
         getFormattedSummary(getMsg("summary-enabling-windows-service")));
 
@@ -1083,6 +1336,10 @@
     {
       updateUserDataForSuffixesOptionsPanel(qs);
     }
+    else if (cStep == REMOTE_REPLICATION_PORTS)
+    {
+      updateUserDataForRemoteReplicationPorts(qs);
+    }
     else if (cStep == NEW_SUFFIX_OPTIONS)
     {
       updateUserDataForNewSuffixOptionsPanel(qs);
@@ -1139,80 +1396,157 @@
         break;
       }
     }
-    else
+  }
+
+  /**
+   * This method initialize the contents of the synchronized servers with the
+   * contents of the first server we find.
+   * @throws ApplicationException if something goes wrong.
+   */
+  protected void initializeSuffixes() throws ApplicationException
+  {
+    InitialLdapContext ctx = null;
+    try
     {
-      /* We must replicate some suffixes: for the moment just create them. */
-      /* TODO: replicate them. */
-      Set<SuffixDescriptor> suffixesToReplicate =
-        getUserData().getSuffixesToReplicateOptions().getAvailableSuffixes();
-      boolean startedServer = false;
-      if (suffixesToReplicate.size() > 0)
+      ctx = createLocalContext();
+    }
+    catch (Throwable t)
+    {
+      String failedMsg = getThrowableMsg("error-connecting-to-local", null, t);
+      try
       {
-        startServerWithoutConnectionHandlers();
-        startedServer = true;
-      }
-      for (SuffixDescriptor suffix: suffixesToReplicate)
-      {
-        // TODO: localize
-        notifyListeners(getFormattedWithPoints("Creating Suffix"));
-
-        ArrayList<String> argList = new ArrayList<String>();
-        argList.add("-C");
-        argList.add(CONFIG_CLASS_NAME);
-
-        argList.add("-c");
-        argList.add(getInstallation().getCurrentConfigurationFile().toString());
-
-        argList.add("-b");
-        argList.add(suffix.getDN());
-
-        String[] args = new String[argList.size()];
-        argList.toArray(args);
-        try
+        if (ctx != null)
         {
-          InstallerHelper helper = new InstallerHelper();
-          int result = helper.invokeConfigureServer(args);
+          ctx.close();
+        }
+      }
+      catch (Throwable t1)
+      {
+      }
+      throw new ApplicationException(
+          ApplicationException.Type.CONFIGURATION_ERROR, failedMsg, t);
+    }
 
-          if (result != 0)
+    Set<SuffixDescriptor> suffixes =
+      getUserData().getSuffixesToReplicateOptions().getSuffixes();
+    int i = 0;
+    for (SuffixDescriptor suffix : suffixes)
+    {
+      String dn = suffix.getDN();
+
+      ReplicaDescriptor replica = suffix.getReplicas().iterator().next();
+      ServerDescriptor server = replica.getServer();
+      String hostPort = server.getHostPort(true);
+
+      notifyListeners(getFormattedProgress(
+        getMsg("progress-initializing-suffix", dn, hostPort)));
+      notifyListeners(getLineBreak());
+      try
+      {
+        int replicationId = replica.getReplicationId();
+        if (replicationId == -1)
+        {
+          /**
+           * This occurs if the remote server had not replication configured.
+           */
+          InitialLdapContext rCtx = null;
+          try
           {
+            rCtx = getRemoteConnection(server, getTrustManager());
+            ServerDescriptor s = ServerDescriptor.createStandalone(rCtx);
+            for (ReplicaDescriptor r : s.getReplicas())
+            {
+              if (Utils.areDnsEqual(r.getSuffix().getDN(), dn))
+              {
+                replicationId = r.getReplicationId();
+              }
+            }
+          }
+          catch (NamingException ne)
+          {
+            String[] arg = {server.getHostPort(true)};
             throw new ApplicationException(
                 ApplicationException.Type.CONFIGURATION_ERROR,
-                getMsg("error-configuring"), null);
+                getMsg("cannot-connect-to-remote-generic", arg), ne);
           }
-        } catch (Throwable t)
-        {
-          throw new ApplicationException(
-              ApplicationException.Type.CONFIGURATION_ERROR,
-              getThrowableMsg("error-configuring", null, t), t);
+          finally
+          {
+            try
+            {
+              rCtx.close();
+            }
+            catch (Throwable t)
+            {
+            }
+          }
         }
-        notifyListeners(getFormattedDone());
-
-        // TODO: localize
-        notifyListeners(
-            getFormattedProgress("One day we will replicate the suffixes!"));
+        int nTries = 4;
+        boolean initDone = false;
+        while (!initDone)
+        {
+          try
+          {
+            initializeSuffix(ctx, replicationId, dn, true, hostPort);
+            initDone = true;
+          }
+          catch (PeerNotFoundException pnfe)
+          {
+            LOG.log(Level.INFO, "Peer could not be found");
+            if (nTries == 1)
+            {
+              throw new ApplicationException(
+                  ApplicationException.Type.APPLICATION,
+                  pnfe.getLocalizedMessage(), null);
+            }
+            try
+            {
+              Thread.sleep((5 - nTries) * 3000);
+            }
+            catch (Throwable t)
+            {
+            }
+          }
+          nTries--;
+        }
       }
-      if (startedServer)
+      catch (ApplicationException ae)
       {
-        new InProcessServerController(getInstallation()).stopServer();
+        try
+        {
+          if (ctx != null)
+          {
+            ctx.close();
+          }
+        }
+        catch (Throwable t1)
+        {
+        }
+        throw ae;
       }
+      if (i > 0)
+      {
+        notifyListeners(getLineBreak());
+      }
+      i++;
     }
   }
 
   /**
-   * This methods updates the ADS contents (and creates the according suffixes).
+   * This method updates the ADS contents (and creates the according suffixes).
+   * NOTE: this method assumes that the server is running.
    * @throws ApplicationException if something goes wrong.
    */
   protected void updateADS() throws ApplicationException
   {
-    if (true) return;
-    /* First check if the remote server contains an ADS: if it is the case the
+    /*
+     * First check if the remote server contains an ADS: if it is the case the
      * best is to update its contents with the new data and then configure the
      * local server to be replicated with the remote server.
      */
-    DataReplicationOptions repl =
-      getUserData().getReplicationOptions();
+    DataReplicationOptions repl = getUserData().getReplicationOptions();
     boolean remoteServer =
       repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY;
+    InitialLdapContext localCtx = null;
     if (remoteServer)
     {
       // Try to connect
@@ -1223,11 +1557,22 @@
       InitialLdapContext ctx = null;
       try
       {
-        ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
-            Utils.getDefaultLDAPTimeout(), null);
+        if (auth.useSecureConnection())
+        {
+          ApplicationTrustManager trustManager = getTrustManager();
+          trustManager.setHost(auth.getHostName());
+          ctx = Utils.createLdapsContext(ldapUrl, dn, pwd,
+              Utils.getDefaultLDAPTimeout(), null, trustManager);
+        }
+        else
+        {
+          ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
+              Utils.getDefaultLDAPTimeout(), null);
+        }
 
         ADSContext adsContext = new ADSContext(ctx);
-        if (adsContext.hasAdminData())
+        boolean hasAdminData = adsContext.hasAdminData();
+        if (hasAdminData)
         {
           /* Add global administrator if the user specified one. */
           if (getUserData().mustCreateAdministrator())
@@ -1236,9 +1581,10 @@
             {
               String[] arg = {getHostDisplay(auth)};
               notifyListeners(getFormattedWithPoints(
-                  getMsg("creating-administrator", arg)));
+                  getMsg("progress-creating-administrator", arg)));
               adsContext.createAdministrator(getAdministratorProperties());
               notifyListeners(getFormattedDone());
+              notifyListeners(getLineBreak());
             }
             catch (ADSContextException ade)
             {
@@ -1254,37 +1600,215 @@
               }
             }
           }
-
-          Map<ADSContext.ServerProperty, Object> serverProperties =
-            getNewServerProperties();
-
-          /* Register new server data. */
-          adsContext.registerServer(serverProperties);
-
-          /* Configure local server to have an ADS and replicate it */
-          // TODO
-          notifyListeners(getFormattedProgress(
-              "Here we create the new server ADS and we replicate it.\n"));
         }
         else
         {
-          /* TODO: We need to integrate in remote framework to make this work.
-           */
-          /*
+          notifyListeners(getFormattedWithPoints(
+              getMsg("progress-creating-ads-on-remote", getHostDisplay(auth))));
+
           adsContext.createAdminData();
           adsContext.createAdministrator(getAdministratorProperties());
           adsContext.registerServer(
-              getRemoteServerProperties(adsContext.getDirContext()));
-          adsContext.registerServer(getNewServerProperties());
-          */
-          notifyListeners(getFormattedProgress(
-              "Here we update the server in "+getHostDisplay(auth)+"\n"));
+              getRemoteServerProperties(auth.getHostName(),
+                  adsContext.getDirContext()));
 
-          /* Configure local server to have an ADS and replicate it */
-          // TODO
-          notifyListeners(getFormattedProgress(
-              "Here we create the new server ADS and we replicate it.\n"));
+          notifyListeners(getFormattedDone());
+          notifyListeners(getLineBreak());
+        }
+        /* Configure local server to have an ADS */
+        notifyListeners(getFormattedWithPoints(
+            getMsg("progress-creating-ads")));
+        try
+        {
+          localCtx = createLocalContext();
+        }
+        catch (Throwable t)
+        {
+          String failedMsg = getThrowableMsg("error-connecting-to-local", null,
+              t);
+          throw new ApplicationException(
+              ApplicationException.Type.CONFIGURATION_ERROR, failedMsg, t);
+        }
+        createLocalAds(localCtx);
+        notifyListeners(getFormattedDone());
+        notifyListeners(getLineBreak());
 
+        lastLoadedCache = new TopologyCache(adsContext, getTrustManager());
+        lastLoadedCache.reloadTopology();
+        Set<Integer> knownServerIds = new HashSet<Integer>();
+        Set<Integer> knownReplicationServerIds = new HashSet<Integer>();
+        Set<String> replicationServers = new HashSet<String>();
+        replicationServers.add(getLocalReplicationServer());
+        Set<ServerDescriptor> remoteWithAds = new HashSet<ServerDescriptor>();
+
+        for (SuffixDescriptor suffix : lastLoadedCache.getSuffixes())
+        {
+          for (ReplicaDescriptor replica : suffix.getReplicas())
+          {
+            knownServerIds.add(replica.getReplicationId());
+          }
+          if (Utils.areDnsEqual(suffix.getDN(),
+              ADSContext.getAdministrationSuffixDN()))
+          {
+            replicationServers.addAll(suffix.getReplicationServers());
+            for (ReplicaDescriptor replica : suffix.getReplicas())
+            {
+              ServerDescriptor server = replica.getServer();
+              Object e = server.getServerProperties().get
+              (ServerDescriptor.ServerProperty.IS_REPLICATION_SERVER);
+              if (Boolean.TRUE.equals(e))
+              {
+                replicationServers.add(server.getHostName()+":"+
+                    server.getServerProperties().get
+                    (ServerDescriptor.ServerProperty.REPLICATION_SERVER_PORT));
+              }
+              remoteWithAds.add(server);
+            }
+          }
+        }
+        for (ServerDescriptor server : lastLoadedCache.getServers())
+        {
+          Object v = server.getServerProperties().get
+          (ServerDescriptor.ServerProperty.REPLICATION_SERVER_ID);
+          if (v != null)
+          {
+            knownReplicationServerIds.add((Integer)v);
+          }
+        }
+        InstallerHelper helper = new InstallerHelper();
+        Set<String> dns = new HashSet<String>();
+        dns.add(ADSContext.getAdministrationSuffixDN());
+        Map <String, Set<String>>hmRepServers =
+          new HashMap<String, Set<String>>();
+        hmRepServers.put(ADSContext.getAdministrationSuffixDN(),
+            replicationServers);
+        for (ServerDescriptor server : remoteWithAds)
+        {
+          Integer replicationPort = (Integer)server.getServerProperties().get
+          (ServerDescriptor.ServerProperty.REPLICATION_SERVER_PORT);
+          if (replicationPort != null)
+          {
+            InitialLdapContext rCtx = getRemoteConnection(server,
+                getTrustManager());
+            helper.configureReplication(rCtx, dns, hmRepServers,
+                replicationPort, server.getHostPort(true),
+                knownReplicationServerIds, knownServerIds);
+            try
+            {
+              rCtx.close();
+            }
+            catch (Throwable t)
+            {
+            }
+          }
+        }
+        /* Register new server data. */
+        try
+        {
+          adsContext.registerServer(getNewServerAdsProperties());
+        }
+        catch (ADSContextException adse)
+        {
+          if (adse.getError() ==
+            ADSContextException.ErrorType.ALREADY_REGISTERED)
+          {
+            /* This might occur after registering and unregistering a server */
+            adsContext.unregisterServer(getNewServerAdsProperties());
+            adsContext.registerServer(getNewServerAdsProperties());
+          }
+          else
+          {
+            throw adse;
+          }
+        }
+
+        /* Configure replication on local server */
+        helper.configureReplication(localCtx, dns, hmRepServers,
+            getUserData().getReplicationOptions().getReplicationPort(),
+            getLocalHostPort(), knownReplicationServerIds, knownServerIds);
+
+        /* Initialize local ADS contents. */
+        ServerDescriptor server = ServerDescriptor.createStandalone(ctx);
+        for (ReplicaDescriptor replica : server.getReplicas())
+        {
+          if (Utils.areDnsEqual(replica.getSuffix().getDN(),
+              ADSContext.getAdministrationSuffixDN()))
+          {
+            notifyListeners(getFormattedWithPoints(
+                getMsg("progress-initializing-ads")));
+
+            int replicationId = replica.getReplicationId();
+            if (replicationId == -1)
+            {
+              /**
+               * This occurs if the remote server had not replication
+               * configured.
+               */
+              InitialLdapContext rCtx = null;
+              try
+              {
+                rCtx = getRemoteConnection(server, getTrustManager());
+                ServerDescriptor s = ServerDescriptor.createStandalone(rCtx);
+                for (ReplicaDescriptor r : s.getReplicas())
+                {
+                  if (Utils.areDnsEqual(r.getSuffix().getDN(), dn))
+                  {
+                    replicationId = r.getReplicationId();
+                  }
+                }
+              }
+              catch (NamingException ne)
+              {
+                String[] arg = {server.getHostPort(true)};
+                throw new ApplicationException(
+                    ApplicationException.Type.CONFIGURATION_ERROR,
+                    getMsg("cannot-connect-to-remote-generic", arg), ne);
+              }
+              finally
+              {
+                try
+                {
+                  rCtx.close();
+                }
+                catch (Throwable t)
+                {
+                }
+              }
+            }
+            int nTries = 4;
+            boolean initDone = false;
+            while (!initDone)
+            {
+              try
+              {
+                initializeSuffix(localCtx, replica.getReplicationId(),
+                    ADSContext.getAdministrationSuffixDN(),
+                    true, server.getHostPort(true));
+                initDone = true;
+              }
+              catch (PeerNotFoundException pnfe)
+              {
+                LOG.log(Level.INFO, "Peer could not be found");
+                if (nTries == 1)
+                {
+                  throw new ApplicationException(
+                      ApplicationException.Type.APPLICATION,
+                      pnfe.getLocalizedMessage(), null);
+                }
+                try
+                {
+                  Thread.sleep((5 - nTries) * 3000);
+                }
+                catch (Throwable t)
+                {
+                }
+              }
+              nTries--;
+            }
+            notifyListeners(getFormattedDone());
+            notifyListeners(getLineBreak());
+            break;
+          }
         }
       }
       catch (NoPermissionException x)
@@ -1301,6 +1825,14 @@
             ApplicationException.Type.CONFIGURATION_ERROR,
             getMsg("cannot-connect-to-remote-generic", arg), ne);
       }
+      catch (TopologyCacheException tpe)
+      {
+        LOG.log(Level.WARNING, "Error reloading topology cache to "+
+            "configure ADS replication.", tpe);
+        throw new ApplicationException(
+            ApplicationException.Type.CONFIGURATION_ERROR,
+            getMsg("bug-msg"), tpe);
+      }
       catch (ADSContextException ace)
       {
         String[] args = {getHostDisplay(auth), ace.toString()};
@@ -1320,27 +1852,75 @@
           {
           }
         }
+        if (localCtx != null)
+        {
+          try
+          {
+            localCtx.close();
+          }
+          catch (Throwable t)
+          {
+          }
+        }
       }
     }
     else
     {
-      notifyListeners(getFormattedWithPoints(getMsg("creating-ads")));
-      Map<ADSContext.ServerProperty, Object> serverProperties =
-        getNewServerProperties();
-      /*
       try
       {
-        ADSContext.createOfflineAdminData(serverProperties,
-            getUserData().getServerLocation(), getBackendName());
+        /* Configure local server to have an ADS */
+        notifyListeners(getFormattedWithPoints(
+            getMsg("progress-creating-ads")));
+        try
+        {
+          localCtx = createLocalContext();
+        }
+        catch (Throwable t)
+        {
+          String failedMsg = getThrowableMsg("error-connecting-to-local", null,
+              t);
+          throw new ApplicationException(
+              ApplicationException.Type.CONFIGURATION_ERROR, failedMsg, t);
+        }
+        createLocalAds(localCtx);
+        int replicationPort =
+          getUserData().getReplicationOptions().getReplicationPort();
+        Set<String> dns = new HashSet<String>();
+        dns.add(ADSContext.getAdministrationSuffixDN());
+        Map<String, Set<String>> hmReplicationServers =
+          new HashMap<String, Set<String>>();
+        HashSet<String> replicationServers = new HashSet<String>();
+        String newReplicationServer = getLocalReplicationServer();
+        replicationServers.add(newReplicationServer);
+        hmReplicationServers.put(ADSContext.getAdministrationSuffixDN(),
+            replicationServers);
+        InstallerHelper helper = new InstallerHelper();
+
+        helper.configureReplication(localCtx, dns, hmReplicationServers,
+            replicationPort, getLocalHostPort(),
+            new HashSet<Integer>(), new HashSet<Integer>());
+        notifyListeners(getFormattedDone());
+        notifyListeners(getLineBreak());
       }
       catch (ADSContextException ace)
       {
         throw new ApplicationException(
             ApplicationException.Type.CONFIGURATION_ERROR,
-            getMsg("local-ads-exception"), ace);
+            getMsg("ads-exception", ace.toString()), ace);
       }
-      */
-      notifyListeners(getFormattedDone());
+      finally
+      {
+        if (localCtx != null)
+        {
+          try
+          {
+            localCtx.close();
+          }
+          catch (Throwable t)
+          {
+          }
+        }
+      }
     }
   }
 
@@ -1350,7 +1930,7 @@
    * @return <CODE>true</CODE> if we must create a new suffix and
    * <CODE>false</CODE> otherwise.
    */
-  private boolean createNotReplicatedSuffix()
+  protected boolean createNotReplicatedSuffix()
   {
     boolean createSuffix;
 
@@ -1363,15 +1943,84 @@
     createSuffix =
       (repl.getType() == DataReplicationOptions.Type.FIRST_IN_TOPOLOGY) ||
       (repl.getType() == DataReplicationOptions.Type.STANDALONE) ||
-      (suf.getType() ==
-        SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY);
+      (suf.getType() == SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY);
 
     return createSuffix;
   }
 
+  /**
+   * Returns <CODE>true</CODE> if we must configure replication and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must configure replication and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean mustConfigureReplication()
+  {
+    return getUserData().getReplicationOptions().getType() !=
+      DataReplicationOptions.Type.STANDALONE;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must create the ADS and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must create the ADS and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean mustCreateAds()
+  {
+    return getUserData().getReplicationOptions().getType() !=
+      DataReplicationOptions.Type.STANDALONE;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must start the server and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must start the server and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean mustStart()
+  {
+    return getUserData().getStartServer() || mustCreateAds();
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must stop the server and
+   * <CODE>false</CODE> otherwise.
+   * The server might be stopped if the user asked not to start it at the
+   * end of the installation and it was started temporarily to update its
+   * configuration.
+   * @return <CODE>true</CODE> if we must stop the server and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean mustStop()
+  {
+    return !getUserData().getStartServer() && mustCreateAds();
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must initialize suffixes and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must initialize suffixes and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean mustInitializeSuffixes()
+  {
+    return getUserData().getReplicationOptions().getType() ==
+      DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY;
+  }
+
   private String getLdapUrl(AuthenticationData auth)
   {
-    return "ldap://"+auth.getHostName()+":"+auth.getPort();
+    String ldapUrl;
+    if (auth.useSecureConnection())
+    {
+      ldapUrl = "ldaps://"+auth.getHostName()+":"+auth.getPort();
+    }
+    else
+    {
+      ldapUrl = "ldap://"+auth.getHostName()+":"+auth.getPort();
+    }
+    return ldapUrl;
   }
 
   private String getHostDisplay(AuthenticationData auth)
@@ -1379,42 +2028,50 @@
     return auth.getHostName()+":"+auth.getPort();
   }
 
-  private Map<ADSContext.ServerProperty, Object> getNewServerProperties()
+  private Map<ADSContext.ServerProperty, Object> getNewServerAdsProperties()
   {
     Map<ADSContext.ServerProperty, Object> serverProperties =
       new HashMap<ADSContext.ServerProperty, Object>();
-    // TODO: this might not work
-    /*
-    try
-    {
-      serverProperties.put(ADSContext.ServerProperty.HOSTNAME,
-          java.net.InetAddress.getLocalHost().getHostName());
-    }
-    catch (Throwable t)
-    {
-      t.printStackTrace();
-    }
-    serverProperties.put(ADSContext.ServerProperty.PORT,
+    serverProperties.put(ADSContext.ServerProperty.HOST_NAME,
+          getUserData().getHostName());
+    serverProperties.put(ADSContext.ServerProperty.LDAP_PORT,
         String.valueOf(getUserData().getServerPort()));
     serverProperties.put(ADSContext.ServerProperty.LDAP_ENABLED, "true");
 
     // TODO: even if the user does not configure SSL maybe we should choose
     // a secure port that is not being used and that we can actually use.
-    serverProperties.put(ADSContext.ServerProperty.SECURE_PORT, "636");
-    serverProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "false");
+    SecurityOptions sec = getUserData().getSecurityOptions();
+    if (sec.getEnableSSL())
+    {
+      serverProperties.put(ADSContext.ServerProperty.LDAPS_PORT,
+          String.valueOf(sec.getSslPort()));
+      serverProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "true");
+    }
+    else
+    {
+      serverProperties.put(ADSContext.ServerProperty.LDAPS_PORT, "636");
+      serverProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "false");
+    }
 
-    serverProperties.put(ADSContext.ServerProperty.JMX_PORT,
-        String.valueOf(getUserData().getServerJMXPort()));
-    serverProperties.put(ADSContext.ServerProperty.JMX_ENABLED, "true");
+    serverProperties.put(ADSContext.ServerProperty.JMX_PORT, "1689");
+    serverProperties.put(ADSContext.ServerProperty.JMX_ENABLED, "false");
 
-    serverProperties.put(ADSContext.ServerProperty.INSTANCE_PATH,
-        getUserData().getServerLocation());
+    String path;
+    if (Utils.isWebStart())
+    {
+      path = getUserData().getServerLocation();
+    }
+    else
+    {
+      path = Utils.getInstallPathFromClasspath();
+    }
+    serverProperties.put(ADSContext.ServerProperty.INSTANCE_PATH, path);
 
-    String serverID = serverProperties.get(ADSContext.ServerProperty.HOSTNAME)+
+    String serverID = serverProperties.get(ADSContext.ServerProperty.HOST_NAME)+
     ":"+getUserData().getServerPort();
-    */
+
     /* TODO: do we want to ask this specifically to the user? */
-    //serverProperties.put(ADSContext.ServerProperty.ID, serverID);
+    serverProperties.put(ADSContext.ServerProperty.ID, serverID);
 
     serverProperties.put(ADSContext.ServerProperty.HOST_OS,
         Utils.getOSString());
@@ -1428,7 +2085,7 @@
       new HashMap<ADSContext.AdministratorProperty, Object>();
     adminProperties.put(ADSContext.AdministratorProperty.UID,
         getUserData().getGlobalAdministratorUID());
-    adminProperties.put(ADSContext.AdministratorProperty.UID,
+    adminProperties.put(ADSContext.AdministratorProperty.PASSWORD,
         getUserData().getGlobalAdministratorPassword());
     adminProperties.put(ADSContext.AdministratorProperty.DESCRIPTION,
         getMsg("global-administrator-description"));
@@ -1548,6 +2205,20 @@
       }
     }
 
+    // Check the host is not empty.
+    // TODO: check that the host name is valid...
+    String hostName = qs.getFieldStringValue(FieldName.HOST_NAME);
+    if ((hostName == null) || hostName.trim().isEmpty())
+    {
+      errorMsgs.add(getMsg("empty-host-name"));
+      qs.displayFieldInvalid(FieldName.HOST_NAME, true);
+    }
+    else
+    {
+      qs.displayFieldInvalid(FieldName.HOST_NAME, false);
+      getUserData().setHostName(hostName);
+    }
+
     // Check the port
     String sPort = qs.getFieldStringValue(FieldName.SERVER_PORT);
     int port = -1;
@@ -1722,10 +2393,13 @@
   private void updateUserDataForReplicationOptionsPanel(QuickSetup qs)
       throws UserDataException {
     boolean hasGlobalAdministrators = false;
+    Integer replicationPort = -1;
     String host = null;
     Integer port = null;
     String dn = null;
     String pwd = null;
+    boolean isSecure = Boolean.TRUE.equals(qs.getFieldValue(
+        FieldName.REMOTE_SERVER_IS_SECURE_PORT));
     ArrayList<String> errorMsgs = new ArrayList<String>();
 
     DataReplicationOptions.Type type = (DataReplicationOptions.Type)
@@ -1734,195 +2408,56 @@
     dn = qs.getFieldStringValue(FieldName.REMOTE_SERVER_DN);
     pwd = qs.getFieldStringValue(FieldName.REMOTE_SERVER_PWD);
 
+    if (type != DataReplicationOptions.Type.STANDALONE)
+    {
+      // Check replication port
+      replicationPort = checkReplicationPort(qs, errorMsgs);
+    }
+
+    UserDataConfirmationException confirmEx = null;
     switch (type)
     {
     case IN_EXISTING_TOPOLOGY:
     {
-      // Check host name
-      if ((host == null) || (host.length() == 0))
-      {
-        errorMsgs.add(getMsg("empty-remote-host"));
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true);
-      }
-      else
-      {
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, false);
-      }
-
-      // Check port
       String sPort = qs.getFieldStringValue(FieldName.REMOTE_SERVER_PORT);
-      try
-      {
-        port = Integer.parseInt(sPort);
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, false);
-      }
-      catch (Throwable t)
-      {
-        errorMsgs.add(getMsg("invalid-remote-port"));
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true);
-      }
-
-      // Check dn
-      if ((dn == null) || (dn.length() == 0))
-      {
-        errorMsgs.add(getMsg("empty-remote-dn"));
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
-      }
-      else
-      {
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, false);
-      }
-
-      // Check password
-      if ((pwd == null) || (pwd.length() == 0))
-      {
-        errorMsgs.add(getMsg("empty-remote-pwd"));
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
-      }
-      else
-      {
-        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, false);
-      }
+      checkRemoteHostPortDnAndPwd(host, sPort, dn, pwd, qs, errorMsgs);
 
       if (errorMsgs.size() == 0)
       {
+        port = Integer.parseInt(sPort);
         // Try to connect
-        String ldapUrl = "ldap://"+host+":"+port;
-        InitialLdapContext ctx = null;
+        boolean[] globalAdmin = {hasGlobalAdministrators};
+        String[] effectiveDn = {dn};
         try
         {
-          try
-          {
-            ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
-                Utils.getDefaultLDAPTimeout(), null);
-          }
-          catch (Throwable t)
-          {
-            // Try using a global administrator
-            dn = ADSContext.getAdministratorDN(dn);
-            ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
-                Utils.getDefaultLDAPTimeout(), null);
-          }
-
-          ADSContext adsContext = new ADSContext(ctx);
-          if (adsContext.hasAdminData())
-          {
-            /* Check if there are already global administrators */
-            Set administrators = adsContext.readAdministratorRegistry();
-            if (administrators.size() > 0)
-            {
-              hasGlobalAdministrators = true;
-            }
-            updateUserDataWithSuffixesInADS(adsContext);
-          }
-          else
-          {
-            getUserData().setSuffixesToReplicateOptions(
-                new SuffixesToReplicateOptions(
-                    SuffixesToReplicateOptions.Type.
-                    REPLICATE_WITH_EXISTING_SUFFIXES,
-                    staticSuffixes(),
-                    staticSuffixes()));
-          }
+          updateUserDataWithADS(host, port, dn, pwd, qs, errorMsgs,
+              globalAdmin, effectiveDn);
         }
-        catch (NoPermissionException x)
+        catch (UserDataConfirmationException e)
         {
-          String[] arg = {host+":"+port};
-          errorMsgs.add(getMsg("cannot-connect-to-remote-permissions", arg));
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+          confirmEx = e;
         }
-        catch (NamingException ne)
-        {
-          String[] arg = {host+":"+port};
-          errorMsgs.add(getMsg("cannot-connect-to-remote-generic", arg));
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true);
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true);
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
-          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
-        }
-        catch (ADSContextException ace)
-        {
-          String[] args = {host+":"+port, ace.toString()};
-          errorMsgs.add(getMsg("remote-ads-exception", args));
-        }
-        finally
-        {
-          if (ctx != null)
-          {
-            try
-            {
-              ctx.close();
-            }
-            catch (Throwable t)
-            {
-            }
-          }
-        }
+        hasGlobalAdministrators = globalAdmin[0];
+        dn = effectiveDn[0];
       }
       break;
     }
     case STANDALONE:
     {
-      Set<SuffixDescriptor> available;
-      SuffixesToReplicateOptions repl =
-        getUserData().getSuffixesToReplicateOptions();
-
-      if (repl != null)
-      {
-        available = repl.getAvailableSuffixes();
-      }
-      else
-      {
-        available = new HashSet<SuffixDescriptor>();
-      }
-
-      Set<SuffixDescriptor> chosen;
-      if (repl != null)
-      {
-        chosen = repl.getSuffixes();
-      }
-      else
-      {
-        chosen = new HashSet<SuffixDescriptor>();
-      }
-
       getUserData().setSuffixesToReplicateOptions(
           new SuffixesToReplicateOptions(
               SuffixesToReplicateOptions.Type.NO_SUFFIX_TO_REPLICATE,
-              available,
-              chosen));
+              new HashSet<SuffixDescriptor>(),
+              new HashSet<SuffixDescriptor>()));
       break;
     }
     case FIRST_IN_TOPOLOGY:
     {
-      Set<SuffixDescriptor> available;
-      SuffixesToReplicateOptions repl =
-        getUserData().getSuffixesToReplicateOptions();
-
-      if (repl != null)
-      {
-        available = repl.getAvailableSuffixes();
-      }
-      else
-      {
-        available = new HashSet<SuffixDescriptor>();
-      }
-
-      Set<SuffixDescriptor> chosen;
-      if (repl != null)
-      {
-        chosen = repl.getSuffixes();
-      }
-      else
-      {
-        chosen = new HashSet<SuffixDescriptor>();
-      }
       getUserData().setSuffixesToReplicateOptions(
           new SuffixesToReplicateOptions(
               SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY,
-              available,
-              chosen));
+              new HashSet<SuffixDescriptor>(),
+              new HashSet<SuffixDescriptor>()));
       break;
     }
     default:
@@ -1940,20 +2475,367 @@
       }
       auth.setDn(dn);
       auth.setPwd(pwd);
+      auth.setUseSecureConnection(isSecure);
 
       DataReplicationOptions repl = new DataReplicationOptions(type,
-          auth);
+          auth, replicationPort);
       getUserData().setReplicationOptions(repl);
 
       getUserData().createAdministrator(!hasGlobalAdministrators &&
       type == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY);
-
     }
     if (errorMsgs.size() > 0)
     {
       throw new UserDataException(Step.REPLICATION_OPTIONS,
           Utils.getStringFromCollection(errorMsgs, "\n"));
     }
+    if (confirmEx != null)
+    {
+      throw confirmEx;
+    }
+  }
+
+  private int checkReplicationPort(QuickSetup qs, ArrayList<String> errorMsgs)
+  {
+    int replicationPort = -1;
+    String sPort = qs.getFieldStringValue(FieldName.REPLICATION_PORT);
+    try
+    {
+      replicationPort = Integer.parseInt(sPort);
+      if ((replicationPort < MIN_PORT_VALUE) ||
+          (replicationPort > MAX_PORT_VALUE))
+      {
+        String[] args =
+        { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+        errorMsgs.add(getMsg("invalid-replication-port-value-range", args));
+        qs.displayFieldInvalid(FieldName.SERVER_PORT, true);
+      } else if (!Utils.canUseAsPort(replicationPort))
+      {
+        if (Utils.isPriviledgedPort(replicationPort))
+        {
+          errorMsgs.add(getMsg("cannot-bind-priviledged-port",
+              new String[] { String.valueOf(replicationPort) }));
+        } else
+        {
+          errorMsgs.add(getMsg("cannot-bind-port",
+              new String[] { String.valueOf(replicationPort) }));
+        }
+        qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true);
+
+      } else
+      {
+        /* Check that we did not chose this port for another protocol */
+        SecurityOptions sec = getUserData().getSecurityOptions();
+        if ((replicationPort == getUserData().getServerPort()) ||
+            (replicationPort == getUserData().getServerJMXPort()) ||
+            ((replicationPort == sec.getSslPort()) && sec.getEnableSSL()))
+        {
+          errorMsgs.add(
+              getMsg("replication-port-already-chosen-for-other-protocol"));
+          qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true);
+        }
+        else
+        {
+          qs.displayFieldInvalid(FieldName.REPLICATION_PORT, false);
+        }
+      }
+
+    } catch (NumberFormatException nfe)
+    {
+      String[] args =
+      { String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE) };
+      errorMsgs.add(getMsg("invalid-replication-port-value-range", args));
+      qs.displayFieldInvalid(FieldName.REPLICATION_PORT, true);
+    }
+    return replicationPort;
+  }
+
+  private void checkRemoteHostPortDnAndPwd(String host, String sPort, String dn,
+      String pwd, QuickSetup qs, ArrayList<String> errorMsgs)
+  {
+    // Check host
+    if ((host == null) || (host.length() == 0))
+    {
+      errorMsgs.add(getMsg("empty-remote-host"));
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true);
+    }
+    else
+    {
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, false);
+    }
+
+    // Check port
+    try
+    {
+      Integer.parseInt(sPort);
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, false);
+    }
+    catch (Throwable t)
+    {
+      errorMsgs.add(getMsg("invalid-remote-port"));
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true);
+    }
+
+    // Check dn
+    if ((dn == null) || (dn.length() == 0))
+    {
+      errorMsgs.add(getMsg("empty-remote-dn"));
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
+    }
+    else
+    {
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, false);
+    }
+
+    // Check password
+    if ((pwd == null) || (pwd.length() == 0))
+    {
+      errorMsgs.add(getMsg("empty-remote-pwd"));
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+    }
+    else
+    {
+      qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, false);
+    }
+  }
+
+  private void updateUserDataWithADS(String host, int port, String dn,
+      String pwd, QuickSetup qs, ArrayList<String> errorMsgs,
+      boolean[] hasGlobalAdministrators,
+      String[] effectiveDn) throws UserDataException
+  {
+    String ldapUrl;
+    host = Utils.getHostNameForLdapUrl(host);
+    boolean isSecure = Boolean.TRUE.equals(qs.getFieldValue(
+        FieldName.REMOTE_SERVER_IS_SECURE_PORT));
+    if (isSecure)
+    {
+      ldapUrl = "ldaps://"+host+":"+port;
+    }
+    else
+    {
+      ldapUrl = "ldap://"+host+":"+port;
+    }
+    InitialLdapContext ctx = null;
+
+    ApplicationTrustManager trustManager = getTrustManager();
+    trustManager.setHost(host);
+    trustManager.resetLastRefusedItems();
+    try
+    {
+      try
+      {
+        if (isSecure)
+        {
+          ctx = Utils.createLdapsContext(ldapUrl, dn, pwd,
+              Utils.getDefaultLDAPTimeout(), null, trustManager);
+        }
+        else
+        {
+          ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
+              Utils.getDefaultLDAPTimeout(), null);
+        }
+      }
+      catch (Throwable t)
+      {
+        if (!isCertificateException(t))
+        {
+          // Try using a global administrator
+          dn = ADSContext.getAdministratorDN(dn);
+          if (isSecure)
+          {
+            ctx = Utils.createLdapsContext(ldapUrl, dn, pwd,
+                Utils.getDefaultLDAPTimeout(), null, trustManager);
+          }
+          else
+          {
+            ctx = Utils.createLdapContext(ldapUrl, dn, pwd,
+                Utils.getDefaultLDAPTimeout(), null);
+          }
+        }
+        else
+        {
+          throw t;
+        }
+      }
+
+      ADSContext adsContext = new ADSContext(ctx);
+      if (adsContext.hasAdminData())
+      {
+        /* Check if there are already global administrators */
+        Set administrators = adsContext.readAdministratorRegistry();
+        if (administrators.size() > 0)
+        {
+          hasGlobalAdministrators[0] = true;
+        }
+        else
+        {
+          hasGlobalAdministrators[0] = false;
+        }
+        Set<TopologyCacheException> exceptions =
+        updateUserDataWithSuffixesInADS(adsContext, trustManager);
+        Set<String> exceptionMsgs = new LinkedHashSet<String>();
+        /* Check the exceptions and see if we throw them or not. */
+        for (TopologyCacheException e : exceptions)
+        {
+          switch (e.getType())
+          {
+          case NOT_GLOBAL_ADMINISTRATOR:
+            String errorMsg = getMsg("not-global-administrator-provided");
+            throw new UserDataException(Step.REPLICATION_OPTIONS, errorMsg);
+          case GENERIC_CREATING_CONNECTION:
+            if ((e.getCause() != null) &&
+                isCertificateException(e.getCause()))
+            {
+              UserDataCertificateException.Type excType;
+              ApplicationTrustManager.Cause cause =
+                trustManager.getLastRefusedCause();
+              LOG.log(Level.INFO, "Certificate exception cause: "+cause);
+              if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED)
+              {
+                excType = UserDataCertificateException.Type.NOT_TRUSTED;
+              }
+              else if (cause ==
+                ApplicationTrustManager.Cause.HOST_NAME_MISMATCH)
+              {
+                excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH;
+              }
+              else
+              {
+                excType = null;
+              }
+              if (excType != null)
+              {
+                String h;
+                int p;
+                try
+                {
+                  URI uri = new URI(e.getLdapUrl());
+                  h = uri.getHost();
+                  p = uri.getPort();
+                }
+                catch (Throwable t)
+                {
+                  LOG.log(Level.WARNING,
+                      "Error parsing ldap url of TopologyCacheException.", t);
+                  h = getMsg("not-available-label");
+                  p = -1;
+                }
+                throw new UserDataCertificateException(Step.REPLICATION_OPTIONS,
+                    getMsg("certificate-exception", h, String.valueOf(p)),
+                    e.getCause(), h, p,
+                    e.getTrustManager().getLastRefusedChain(),
+                    trustManager.getLastRefusedAuthType(), excType);
+              }
+            }
+          }
+          exceptionMsgs.add(getStringRepresentation(e));
+        }
+        if (exceptionMsgs.size() > 0)
+        {
+          String confirmationMsg =
+            getMsg("error-reading-registered-servers-confirm",
+              Utils.getStringFromCollection(exceptionMsgs, "\n"));
+          throw new UserDataConfirmationException(Step.REPLICATION_OPTIONS,
+              confirmationMsg);
+        }
+      }
+      else
+      {
+        updateUserDataWithSuffixesInServer(ctx);
+      }
+    }
+    catch (UserDataException ude)
+    {
+      throw ude;
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.INFO, "Error connecting to remote server.", t);
+      if (isCertificateException(t))
+      {
+        UserDataCertificateException.Type excType;
+        ApplicationTrustManager.Cause cause =
+          trustManager.getLastRefusedCause();
+        LOG.log(Level.INFO, "Certificate exception cause: "+cause);
+        if (cause == ApplicationTrustManager.Cause.NOT_TRUSTED)
+        {
+          excType = UserDataCertificateException.Type.NOT_TRUSTED;
+        }
+        else if (cause == ApplicationTrustManager.Cause.HOST_NAME_MISMATCH)
+        {
+          excType = UserDataCertificateException.Type.HOST_NAME_MISMATCH;
+        }
+        else
+        {
+          excType = null;
+        }
+
+        if (excType != null)
+        {
+          throw new UserDataCertificateException(Step.REPLICATION_OPTIONS,
+              getMsg("certificate-exception", host, String.valueOf(port)), t,
+              host, port, trustManager.getLastRefusedChain(),
+              trustManager.getLastRefusedAuthType(), excType);
+        }
+        else
+        {
+          String[] arg = {host+":"+port, t.toString()};
+          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true);
+          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true);
+          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
+          qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+          errorMsgs.add(getMsg("cannot-connect-to-remote-generic", arg));
+        }
+      }
+      else if (t instanceof AuthenticationException)
+      {
+        String[] arg = {host+":"+port};
+        errorMsgs.add(getMsg("cannot-connect-to-remote-authentication", arg));
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+      }
+      else if (t instanceof NoPermissionException)
+      {
+        String[] arg = {host+":"+port};
+        errorMsgs.add(getMsg("cannot-connect-to-remote-permissions", arg));
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+      }
+      else if (t instanceof NamingException)
+      {
+        String[] arg = {host+":"+port, t.toString()};
+        errorMsgs.add(getMsg("cannot-connect-to-remote-generic", arg));
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_HOST, true);
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PORT, true);
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_DN, true);
+        qs.displayFieldInvalid(FieldName.REMOTE_SERVER_PWD, true);
+      }
+      else if (t instanceof ADSContextException)
+      {
+        String[] args = {host+":"+port, t.toString()};
+        errorMsgs.add(getMsg("remote-ads-exception", args));
+      }
+      else
+      {
+        throw new UserDataException(Step.REPLICATION_OPTIONS,
+            getThrowableMsg("bug-msg", null, t));
+      }
+    }
+    finally
+    {
+      if (ctx != null)
+      {
+        try
+        {
+          ctx.close();
+        }
+        catch (Throwable t)
+        {
+        }
+      }
+    }
+    effectiveDn[0] = dn;
   }
 
   /**
@@ -2016,7 +2898,7 @@
 
     if (pwdValid)
     {
-      getUserData().setDirectoryManagerPwd(pwd1);
+      getUserData().setGlobalAdministratorPassword(pwd1);
       qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD, false);
       qs.displayFieldInvalid(FieldName.GLOBAL_ADMINISTRATOR_PWD_CONFIRM, false);
     }
@@ -2068,6 +2950,8 @@
               chosen);
         getUserData().setSuffixesToReplicateOptions(options);
       }
+      getUserData().setRemoteWithNoReplicationPort(
+          getRemoteWithNoReplicationPort(getUserData()));
     }
     else
     {
@@ -2091,6 +2975,77 @@
   }
 
   /**
+   * Validate the data provided by the user in the remote server replication
+   * port panel and update the userData object according to that content.
+   *
+   * @throws UserDataException if the data provided by the user is not
+   *           valid.
+   */
+  private void updateUserDataForRemoteReplicationPorts(QuickSetup qs)
+      throws UserDataException
+  {
+    ArrayList<String> errorMsgs = new ArrayList<String>();
+    Map<ServerDescriptor, Integer> servers =
+      getUserData().getRemoteWithNoReplicationPort();
+    Map hm = (Map) qs.getFieldValue(FieldName.REMOTE_REPLICATION_PORT);
+    for (ServerDescriptor server : servers.keySet())
+    {
+      String hostName = server.getHostName();
+      int replicationPort = -1;
+      String sPort = (String)hm.get(server.getId());
+      try
+      {
+        replicationPort = Integer.parseInt(sPort);
+        if ((replicationPort < MIN_PORT_VALUE) ||
+            (replicationPort > MAX_PORT_VALUE))
+        {
+          String[] args = { server.getHostPort(true),
+              String.valueOf(MIN_PORT_VALUE), String.valueOf(MAX_PORT_VALUE)};
+          errorMsgs.add(getMsg("invalid-remote-replication-port-value-range",
+              args));
+        }
+        if (hostName.equalsIgnoreCase(getUserData().getHostName()))
+        {
+          int securePort = -1;
+          if (getUserData().getSecurityOptions().getEnableSSL())
+          {
+            securePort = getUserData().getSecurityOptions().getSslPort();
+          }
+          if ((replicationPort == getUserData().getServerPort()) ||
+              (replicationPort == getUserData().getServerJMXPort()) ||
+              (replicationPort ==
+                getUserData().getReplicationOptions().getReplicationPort()) ||
+              (replicationPort == securePort))
+          {
+            errorMsgs.add(getMsg(
+                    "remote-replication-port-already-chosen-for-other-protocol",
+                    server.getHostPort(true)));
+          }
+        }
+        servers.put(server, replicationPort);
+      } catch (NumberFormatException nfe)
+      {
+        String[] args = { hostName, String.valueOf(MIN_PORT_VALUE),
+            String.valueOf(MAX_PORT_VALUE)};
+        errorMsgs.add(getMsg("invalid-remote-replication-port-value-range",
+            args));
+      }
+    }
+
+    if (errorMsgs.size() > 0)
+    {
+      qs.displayFieldInvalid(FieldName.REMOTE_REPLICATION_PORT, true);
+      throw new UserDataException(Step.REMOTE_REPLICATION_PORTS,
+          Utils.getStringFromCollection(errorMsgs, "\n"));
+    }
+    else
+    {
+      qs.displayFieldInvalid(FieldName.REMOTE_REPLICATION_PORT, false);
+      getUserData().setRemoteWithNoReplicationPort(servers);
+    }
+  }
+
+  /**
    * Validate the data provided by the user in the new suffix data options panel
    * and update the UserInstallData object according to that content.
    *
@@ -2239,22 +3194,125 @@
   }
 
   private Map<ADSContext.ServerProperty, Object> getRemoteServerProperties(
-      InitialLdapContext ctx) throws NamingException
+      String hostName, InitialLdapContext ctx) throws NamingException
   {
-    // TODO: use administration framework.
-    return new HashMap<ADSContext.ServerProperty, Object>();
+    ServerDescriptor server = ServerDescriptor.createStandalone(ctx);
+    Map<ADSContext.ServerProperty, Object> serverProperties =
+      new HashMap<ADSContext.ServerProperty, Object>();
+    serverProperties.put(ADSContext.ServerProperty.HOST_NAME, hostName);
+    ADSContext.ServerProperty[][] adsProperties =
+    {
+        {ADSContext.ServerProperty.LDAP_PORT,
+        ADSContext.ServerProperty.LDAP_ENABLED},
+        {ADSContext.ServerProperty.LDAPS_PORT,
+        ADSContext.ServerProperty.LDAPS_ENABLED},
+        {ADSContext.ServerProperty.JMX_PORT,
+        ADSContext.ServerProperty.JMX_ENABLED},
+        {ADSContext.ServerProperty.JMXS_PORT,
+        ADSContext.ServerProperty.JMXS_ENABLED}
+
+    };
+    ServerDescriptor.ServerProperty[][] properties =
+    {
+        {ServerDescriptor.ServerProperty.LDAP_PORT,
+         ServerDescriptor.ServerProperty.LDAP_ENABLED},
+        {ServerDescriptor.ServerProperty.LDAPS_PORT,
+         ServerDescriptor.ServerProperty.LDAPS_ENABLED},
+        {ServerDescriptor.ServerProperty.JMX_PORT,
+         ServerDescriptor.ServerProperty.JMX_ENABLED},
+        {ServerDescriptor.ServerProperty.JMXS_PORT,
+         ServerDescriptor.ServerProperty.JMXS_ENABLED}
+    };
+    for (int i=0; i<properties.length; i++)
+    {
+      ArrayList portNumbers =
+        (ArrayList)server.getServerProperties().get(properties[i][0]);
+      if (portNumbers != null)
+      {
+        ArrayList enabled =
+          (ArrayList)server.getServerProperties().get(properties[i][1]);
+        boolean enabledFound = false;
+        for (int j=0; j<enabled.size() && !enabledFound; j++)
+        {
+          if (Boolean.TRUE.equals(enabled.get(j)))
+          {
+            enabledFound = true;
+            serverProperties.put(adsProperties[i][0],
+                String.valueOf(portNumbers.get(j)));
+          }
+        }
+        if (!enabledFound && (portNumbers.size() > 0))
+        {
+          serverProperties.put(adsProperties[i][0],
+              String.valueOf(portNumbers.get(0)));
+        }
+        serverProperties.put(adsProperties[i][1], enabledFound?"true":"false");
+      }
+    }
+
+    serverProperties.put(ADSContext.ServerProperty.ID,
+        server.getHostPort(true));
+
+    return serverProperties;
   }
 
   /**
-   * Update the UserInstallData object according to the content of the review
-   * panel.
+   * Update the UserInstallData with the contents we discover in the ADS.
    */
-  private void updateUserDataWithSuffixesInADS(ADSContext adsContext)
+  private Set<TopologyCacheException> updateUserDataWithSuffixesInADS(
+      ADSContext adsContext, ApplicationTrustManager trustManager)
+  throws TopologyCacheException
+  {
+    Set<TopologyCacheException> exceptions =
+      new HashSet<TopologyCacheException>();
+    SuffixesToReplicateOptions suf =
+      getUserData().getSuffixesToReplicateOptions();
+    SuffixesToReplicateOptions.Type type;
+
+    if ((suf == null) || (suf.getType() ==
+      SuffixesToReplicateOptions.Type.NO_SUFFIX_TO_REPLICATE))
+    {
+      type = suf.getType();
+    }
+    else
+    {
+      type = SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY;
+    }
+    lastLoadedCache = new TopologyCache(adsContext, trustManager);
+    lastLoadedCache.reloadTopology();
+    Set<SuffixDescriptor> suffixes = lastLoadedCache.getSuffixes();
+
+    getUserData().setSuffixesToReplicateOptions(
+        new SuffixesToReplicateOptions(type, suffixes, suf.getSuffixes()));
+
+    /* Analyze if we had any exception while loading servers.  For the moment
+     * only throw the exception found if the user did not provide the
+     * Administrator DN and this caused a problem authenticating in one server
+     * or if there is a certificate problem.
+     */
+    Set<ServerDescriptor> servers = lastLoadedCache.getServers();
+    for (ServerDescriptor server : servers)
+    {
+      TopologyCacheException e = server.getLastException();
+      if (e != null)
+      {
+        exceptions.add(e);
+      }
+    }
+    return exceptions;
+  }
+
+  /**
+   * Update the UserInstallData object with the contents of the server to which
+   * we are connected with the provided InitialLdapContext.
+   */
+  private void updateUserDataWithSuffixesInServer(InitialLdapContext ctx)
+  throws NamingException
   {
     SuffixesToReplicateOptions suf =
       getUserData().getSuffixesToReplicateOptions();
     SuffixesToReplicateOptions.Type type;
-    Set<SuffixDescriptor> suffixes = null;
+    Set<SuffixDescriptor> suffixes = new HashSet<SuffixDescriptor>();
     if (suf == null)
     {
       type = SuffixesToReplicateOptions.Type.NEW_SUFFIX_IN_TOPOLOGY;
@@ -2263,117 +3321,14 @@
     {
       type = suf.getType();
     }
-    // TODO: get the suffixes using the adsContext.
-    if (suffixes == null)
+    ServerDescriptor s = ServerDescriptor.createStandalone(ctx);
+    Set<ReplicaDescriptor> replicas = s.getReplicas();
+    for (ReplicaDescriptor replica : replicas)
     {
-      suffixes = new HashSet<SuffixDescriptor>();
+      suffixes.add(replica.getSuffix());
     }
-    suffixes = staticSuffixes();
     getUserData().setSuffixesToReplicateOptions(
-        new SuffixesToReplicateOptions(type, suffixes, suffixes));
-  }
-
-  private Set<SuffixDescriptor> staticSuffixes()
-  {
-    /*
-    ServerDescriptor server1 = new ServerDescriptor();
-    Map<ADSContext.ServerProperty, Object> serverProp1 =
-      new HashMap<ADSContext.ServerProperty, Object>();
-    serverProp1.put(ADSContext.ServerProperty.HOSTNAME, "potato.france");
-    serverProp1.put(ADSContext.ServerProperty.PORT, "389");
-    serverProp1.put(ADSContext.ServerProperty.SECURE_PORT, "689");
-    serverProp1.put(ADSContext.ServerProperty.LDAP_ENABLED, "true");
-    serverProp1.put(ADSContext.ServerProperty.LDAPS_ENABLED, "false");
-    serverProp1.put(ADSContext.ServerProperty.INSTANCE_PATH, "/tmp/jvl1");
-    server1.setAdsProperties(serverProp1);
-
-    ServerDescriptor server2 = new ServerDescriptor();
-    Map<ADSContext.ServerProperty, Object> serverProp2 =
-      new HashMap<ADSContext.ServerProperty, Object>();
-    serverProp2.put(ADSContext.ServerProperty.HOSTNAME, "skalariak.france");
-    serverProp2.put(ADSContext.ServerProperty.PORT, "389");
-    serverProp2.put(ADSContext.ServerProperty.SECURE_PORT, "689");
-    serverProp2.put(ADSContext.ServerProperty.LDAP_ENABLED, "false");
-    serverProp2.put(ADSContext.ServerProperty.LDAPS_ENABLED, "true");
-    serverProp2.put(ADSContext.ServerProperty.INSTANCE_PATH, "/tmp/jvl2");
-    server2.setAdsProperties(serverProp2);
-
-    SuffixDescriptor suffix1 = new SuffixDescriptor();
-    suffix1.setDN("dc=example,dc=com");
-    Set<ReplicaDescriptor> replicas1 = new HashSet<ReplicaDescriptor>();
-
-    SuffixDescriptor suffix2 = new SuffixDescriptor();
-    suffix2.setDN("dc=for real,dc=com");
-    Set<ReplicaDescriptor> replicas2 = new HashSet<ReplicaDescriptor>();
-
-    SuffixDescriptor suffix3 = new SuffixDescriptor();
-    suffix3.setDN("dc=s3,dc=com");
-    Set<ReplicaDescriptor> replicas3 = new HashSet<ReplicaDescriptor>();
-
-    SuffixDescriptor suffix4 = new SuffixDescriptor();
-    suffix4.setDN("dc=s4,dc=com");
-    Set<ReplicaDescriptor> replicas4 = new HashSet<ReplicaDescriptor>();
-
-
-    ReplicaDescriptor replica1 = new ReplicaDescriptor();
-    replica1.setSuffix(suffix1);
-    replica1.setServer(server1);
-    replica1.setEntries(1002);
-    replicas1.add(replica1);
-
-    ReplicaDescriptor replica2 = new ReplicaDescriptor();
-    replica2.setSuffix(suffix1);
-    replica2.setServer(server2);
-    replica2.setEntries(1003);
-    replicas1.add(replica2);
-
-    suffix1.setReplicas(replicas1);
-
-    ReplicaDescriptor replica3 = new ReplicaDescriptor();
-    replica3.setSuffix(suffix2);
-    replica3.setServer(server2);
-    replicas2.add(replica3);
-
-    suffix2.setReplicas(replicas2);
-
-    ReplicaDescriptor replica5 = new ReplicaDescriptor();
-    replica5.setSuffix(suffix3);
-    replica5.setServer(server1);
-    replica5.setEntries(1003);
-    replicas3.add(replica5);
-
-    ReplicaDescriptor replica6 = new ReplicaDescriptor();
-    replica6.setSuffix(suffix3);
-    replica6.setServer(server2);
-    replica6.setEntries(1003);
-    replicas3.add(replica6);
-
-    suffix3.setReplicas(replicas3);
-
-    ReplicaDescriptor replica7 = new ReplicaDescriptor();
-    replica7.setSuffix(suffix4);
-    replica7.setServer(server1);
-    replica7.setEntries(1003);
-    replicas4.add(replica7);
-
-    ReplicaDescriptor replica8 = new ReplicaDescriptor();
-    replica8.setSuffix(suffix3);
-    replica8.setServer(server2);
-    replica8.setEntries(1003);
-    replicas4.add(replica8);
-
-    suffix4.setReplicas(replicas4);
-     */
-    Set<SuffixDescriptor> suffixes = new HashSet<SuffixDescriptor>();
-    /*
-    suffixes.add(suffix1);
-    suffixes.add(suffix2);
-    suffixes.add(suffix3);
-    suffixes.add(suffix4);
-*/
-    //suffixes.clear();
-
-    return suffixes;
+        new SuffixesToReplicateOptions(type, suffixes, suf.getSuffixes()));
   }
 
   /**
@@ -2441,9 +3396,9 @@
    * Returns the Subject DN to be used to generate the self-signed certificate.
    * @return the Subject DN to be used to generate the self-signed certificate.
    */
-  private String getSelfSignedCertificateSubjectDN(SecurityOptions sec)
+  private String getSelfSignedCertificateSubjectDN()
   {
-    return "cn="+Rdn.escapeValue(sec.getSelfSignedCertificateName())+
+    return "cn="+Rdn.escapeValue(getUserData().getHostName())+
     ",O=OpenDS Self-Signed Certificate";
   }
 
@@ -2522,6 +3477,385 @@
     return generatedChar;
   }
 
+  private boolean isCertificateException(Throwable t)
+  {
+    return Utils.isCertificateException(t);
+  }
+
+  private String getStringRepresentation(TopologyCacheException e)
+  {
+    StringBuilder buf = new StringBuilder();
+
+    String ldapUrl = e.getLdapUrl();
+    if (ldapUrl != null)
+    {
+      String hostName = ldapUrl.substring(ldapUrl.indexOf("://") + 3);
+      buf.append(getMsg("server-error", hostName) + " ");
+    }
+    if (e.getCause() instanceof NamingException)
+    {
+      buf.append(getThrowableMsg("bug-msg", null, e.getCause()));
+    }
+    else
+    {
+      // This is unexpected.
+      buf.append(getThrowableMsg("bug-msg", null, e.getCause()));
+    }
+    return buf.toString();
+  }
+
+  private Map<ServerDescriptor, Integer> getRemoteWithNoReplicationPort(
+      UserData userData)
+  {
+    Map<ServerDescriptor, Integer> servers =
+      new HashMap<ServerDescriptor, Integer>();
+    Set<SuffixDescriptor> suffixes =
+      userData.getSuffixesToReplicateOptions().getSuffixes();
+    for (SuffixDescriptor suffix : suffixes)
+    {
+      for (ReplicaDescriptor replica : suffix.getReplicas())
+      {
+        ServerDescriptor server = replica.getServer();
+        Object v = server.getServerProperties().get(
+            ServerDescriptor.ServerProperty.IS_REPLICATION_SERVER);
+        if (!Boolean.TRUE.equals(v))
+        {
+          servers.put(server, 8989);
+        }
+      }
+    }
+    return servers;
+  }
+
+  private InitialLdapContext createLocalContext() throws NamingException
+  {
+    String ldapUrl = "ldap://"+getUserData().getHostName()+":"+
+    getUserData().getServerPort();
+    String dn = getUserData().getDirectoryManagerDn();
+    String pwd = getUserData().getDirectoryManagerPwd();
+    return Utils.createLdapContext(ldapUrl, dn, pwd,
+        Utils.getDefaultLDAPTimeout(), null);
+  }
+  private void createLocalAds(InitialLdapContext ctx)
+  throws ApplicationException, ADSContextException
+  {
+    try
+    {
+      ADSContext adsContext = new ADSContext(ctx);
+      adsContext.createAdminData();
+      adsContext.registerServer(getNewServerAdsProperties());
+      if (getUserData().mustCreateAdministrator())
+      {
+        adsContext.createAdministrator(getAdministratorProperties());
+      }
+    }
+    catch (ADSContextException ace)
+    {
+      throw ace;
+    }
+    catch (Throwable t)
+    {
+      String failedMsg = getThrowableMsg("bug-msg", null, t);
+      throw new ApplicationException(
+          ApplicationException.Type.CONFIGURATION_ERROR, failedMsg, t);
+    }
+  }
+
+  private InitialLdapContext getRemoteConnection(ServerDescriptor server,
+      ApplicationTrustManager trustManager) throws ApplicationException
+  {
+    Map<ADSContext.ServerProperty, Object> adsProperties;
+    AuthenticationData auth =
+      getUserData().getReplicationOptions().getAuthenticationData();
+    if (!server.isRegistered())
+    {
+      /* Create adsProperties to be able to use the class ServerLoader to
+       * get the connection.  Just update the connection parameters with what
+       * the user chose in the Topology Options panel (i.e. even if SSL
+       * is enabled on the remote server, use standard LDAP to connect to the
+       * server if the user specified the LDAP port: this avoids having an
+       * issue with the certificate if it has not been accepted previously
+       * by the user).
+       */
+      adsProperties = new HashMap<ADSContext.ServerProperty, Object>();
+      adsProperties.put(ADSContext.ServerProperty.HOST_NAME,
+          server.getHostName());
+      if (auth.useSecureConnection())
+      {
+        adsProperties.put(ADSContext.ServerProperty.LDAPS_PORT,
+          String.valueOf(auth.getPort()));
+        adsProperties.put(ADSContext.ServerProperty.LDAPS_ENABLED, "true");
+      }
+      else
+      {
+        adsProperties.put(ADSContext.ServerProperty.LDAP_PORT,
+            String.valueOf(auth.getPort()));
+        adsProperties.put(ADSContext.ServerProperty.LDAP_ENABLED, "true");
+      }
+    }
+    else
+    {
+      adsProperties = server.getAdsProperties();
+    }
+
+    ServerLoader loader = new ServerLoader(adsProperties, auth.getDn(),
+        auth.getPwd(), trustManager);
+
+    InitialLdapContext ctx = null;
+    try
+    {
+      ctx = loader.createContext();
+    }
+    catch (NamingException ne)
+    {
+      System.out.println("dn: "+auth.getDn());
+      System.out.println("dn: "+auth.getDn());
+
+      String errorMessage = getMsg("cannot-connect-to-remote-generic",
+          server.getHostPort(true), ne.toString(true));
+      throw new ApplicationException(
+          ApplicationException.Type.CONFIGURATION_ERROR, errorMessage, ne);
+    }
+    return ctx;
+  }
+
+  private void initializeSuffix(InitialLdapContext ctx, int replicaId,
+      String suffixDn, boolean displayProgress, String sourceServerDisplay)
+  throws ApplicationException, PeerNotFoundException
+  {
+    boolean taskCreated = false;
+    int i = 1;
+    boolean isOver = false;
+    String dn = null;
+    BasicAttributes attrs = new BasicAttributes();
+    Attribute oc = new BasicAttribute("objectclass");
+    oc.add("top");
+    oc.add("ds-task");
+    oc.add("ds-task-initialize-from-remote-replica");
+    attrs.put(oc);
+    attrs.put("ds-task-class-name", "org.opends.server.tasks.InitializeTask");
+    attrs.put("ds-task-initialize-domain-dn", suffixDn);
+    attrs.put("ds-task-initialize-replica-server-id",
+        String.valueOf(replicaId));
+    while (!taskCreated)
+    {
+      String id = "quicksetup-initialize"+i;
+      dn = "ds-task-id="+id+",cn=Scheduled Tasks,cn=Tasks";
+      attrs.put("ds-task-id", id);
+      try
+      {
+        DirContext dirCtx = ctx.createSubcontext(dn, attrs);
+        taskCreated = true;
+        LOG.log(Level.INFO, "created task entry: "+attrs);
+        dirCtx.close();
+      }
+      catch (NameAlreadyBoundException x)
+      {
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.SEVERE, "Error creating task "+attrs, ne);
+        String[] arg = {sourceServerDisplay};
+        throw new ApplicationException(ApplicationException.Type.APPLICATION,
+            getThrowableMsg("error-launching-initialization", arg, ne), ne);
+      }
+      i++;
+    }
+    // Wait until it is over
+    SearchControls searchControls = new SearchControls();
+    searchControls.setCountLimit(1);
+    searchControls.setSearchScope(
+        SearchControls. OBJECT_SCOPE);
+    String filter = "objectclass=*";
+    searchControls.setReturningAttributes(
+        new String[] {
+            "ds-task-unprocessed-entry-count",
+            "ds-task-processed-entry-count",
+            "ds-task-log-message",
+            "ds-task-state"
+        });
+    String lastDisplayedMsg = null;
+    String lastLogMsg = null;
+    long lastTimeMsgDisplayed = -1;
+    int totalEntries = 0;
+    while (!isOver)
+    {
+      try
+      {
+        Thread.sleep(500);
+      }
+      catch (Throwable t)
+      {
+      }
+      try
+      {
+        NamingEnumeration res = ctx.search(dn, filter, searchControls);
+        SearchResult sr = (SearchResult)res.next();
+        if (displayProgress)
+        {
+          // Display the number of entries that have been handled and
+          // a percentage...
+          String msg;
+          String sProcessed = getFirstValue(sr,
+          "ds-task-processed-entry-count");
+          String sUnprocessed = getFirstValue(sr,
+          "ds-task-unprocessed-entry-count");
+          int processed = -1;
+          int unprocessed = -1;
+          if (sProcessed != null)
+          {
+            processed = Integer.parseInt(sProcessed);
+          }
+          if (sUnprocessed != null)
+          {
+            unprocessed = Integer.parseInt(sUnprocessed);
+          }
+          totalEntries = Math.max(totalEntries, processed+unprocessed);
+
+          if ((processed != -1) && (unprocessed != -1))
+          {
+            if (processed + unprocessed > 0)
+            {
+              int perc = (100 * processed) / (processed + unprocessed);
+              msg = getMsg("initialize-progress-with-percentage", sProcessed,
+                  String.valueOf(perc));
+            }
+            else
+            {
+              //msg = getMsg("no-entries-to-initialize");
+              msg = null;
+            }
+          }
+          else if (processed != -1)
+          {
+            msg = getMsg("initialize-progress-with-processed", sProcessed);
+          }
+          else if (unprocessed != -1)
+          {
+            msg = getMsg("initialize-progress-with-unprocessed",
+                sUnprocessed);
+          }
+          else
+          {
+            msg = lastDisplayedMsg;
+          }
+
+          if (msg != null)
+          {
+            long currentTime = System.currentTimeMillis();
+            /* Refresh period: to avoid having too many lines in the log */
+            long minRefreshPeriod;
+            if (totalEntries < 100)
+            {
+              minRefreshPeriod = 0;
+            }
+            else if (totalEntries < 1000)
+            {
+              minRefreshPeriod = 1000;
+            }
+            else if (totalEntries < 10000)
+            {
+              minRefreshPeriod = 5000;
+            }
+            else
+            {
+              minRefreshPeriod = 10000;
+            }
+            if (!msg.equals(lastDisplayedMsg) &&
+                ((currentTime - minRefreshPeriod) > lastTimeMsgDisplayed))
+            {
+              notifyListeners(getFormattedProgress(msg));
+              lastDisplayedMsg = msg;
+              notifyListeners(getLineBreak());
+              lastTimeMsgDisplayed = currentTime;
+            }
+          }
+        }
+        String logMsg = getFirstValue(sr, "ds-task-log-message");
+        if (logMsg != null)
+        {
+          if (!logMsg.equals(lastLogMsg))
+          {
+            LOG.log(Level.INFO, logMsg);
+            lastLogMsg = logMsg;
+          }
+        }
+        InstallerHelper helper = new InstallerHelper();
+        String state = getFirstValue(sr, "ds-task-state");
+
+        if (helper.isDone(state) || helper.isStoppedByError(state))
+        {
+          isOver = true;
+          String errorMsg;
+          if (lastLogMsg == null)
+          {
+            errorMsg = getMsg("error-during-initialization-no-log",
+                sourceServerDisplay);
+          }
+          else
+          {
+            errorMsg = getMsg("error-during-initialization-log",
+                sourceServerDisplay, lastLogMsg);
+          }
+
+          if (helper.isCompletedWithErrors(state))
+          {
+            notifyListeners(getFormattedWarning(errorMsg));
+          }
+          else if (!helper.isSuccessful(state) ||
+              helper.isStoppedByError(state))
+          {
+            ApplicationException ae = new ApplicationException(
+                ApplicationException.Type.APPLICATION, errorMsg, null);
+            if ((lastLogMsg != null) &&
+                helper.isPeersNotFoundError(lastLogMsg))
+            {
+              throw new PeerNotFoundException(errorMsg);
+            }
+            else
+            {
+              throw ae;
+            }
+          }
+          else if (displayProgress)
+          {
+            notifyListeners(getFormattedProgress(
+                getMsg("suffix-initialized-successfully")));
+          }
+        }
+      }
+      catch (NameNotFoundException x)
+      {
+        isOver = true;
+        notifyListeners(getFormattedProgress(
+            getMsg("suffix-initialized-successfully")));
+      }
+      catch (NamingException ne)
+      {
+        String[] arg = {sourceServerDisplay};
+        throw new ApplicationException(ApplicationException.Type.APPLICATION,
+            getThrowableMsg("error-pooling-initialization", arg, ne), ne);
+      }
+    }
+  }
+
+  private String getFirstValue(SearchResult entry, String attrName)
+  throws NamingException
+  {
+    return Utils.getFirstValue(entry, attrName);
+  }
+
+  private String getLocalReplicationServer()
+  {
+    return getUserData().getHostName()+":"+
+    getUserData().getReplicationOptions().getReplicationPort();
+  }
+
+  private String getLocalHostPort()
+  {
+    return getUserData().getHostName()+":"+getUserData().getServerPort();
+  }
+
   private static int getRandomInt(Random random,int modulo)
   {
     int value = 0;
@@ -2529,3 +3863,22 @@
     return value;
   }
 }
+
+/**
+ * The exception that is thrown during initialization if the peer specified
+ * could not be found.
+ *
+ */
+class PeerNotFoundException extends Exception
+{
+  private static final long serialVersionUID = -362726764261560341L;
+
+  /**
+   * The constructor for the exception.
+   * @param localizedMsg the localized message.
+   */
+  PeerNotFoundException(String localizedMsg)
+  {
+    super(localizedMsg);
+  }
+}
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
index 15ab091..7ee27c9 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -29,26 +29,67 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.Set;
+import java.util.logging.Logger;
+
+import javax.naming.ldap.InitialLdapContext;
 
 import org.opends.quicksetup.ApplicationException;
 import org.opends.quicksetup.i18n.ResourceProvider;
 import org.opends.quicksetup.webstart.JnlpProperties;
 import org.opends.quicksetup.util.Utils;
+import org.opends.server.admin.DefaultBehaviorException;
+import org.opends.server.admin.ManagedObjectNotFoundException;
+import org.opends.server.admin.client.ManagementContext;
+import org.opends.server.admin.client.ldap.LDAPManagementContext;
+import org.opends.server.admin.client.ldap.JNDIDirContextAdaptor;
+import org.opends.server.admin.std.client.*;
+import org.opends.server.admin.std.meta.*;
+import org.opends.server.backends.task.TaskState;
+import org.opends.server.core.DirectoryServer;
+import org.opends.server.extensions.ConfigFileHandler;
+import org.opends.server.messages.CoreMessages;
+import org.opends.server.messages.ReplicationMessages;
+import org.opends.server.tools.ConfigureDS;
+import org.opends.server.tools.ConfigureWindowsService;
+import org.opends.server.tools.ImportLDIF;
+import org.opends.server.types.Attribute;
+import org.opends.server.types.AttributeType;
+import org.opends.server.types.AttributeValue;
+import org.opends.server.types.DN;
+import org.opends.server.types.DirectoryException;
+import org.opends.server.types.Entry;
+import org.opends.server.types.ExistingFileBehavior;
+import org.opends.server.types.LDIFExportConfig;
+import org.opends.server.types.ObjectClass;
+import org.opends.server.util.LDIFException;
+import org.opends.server.util.LDIFWriter;
+import org.opends.server.util.StaticUtils;
 
 /**
  * This is the only class that uses classes in org.opends.server (excluding the
- * case of org.opends.server.util.DynamicConstants and
- * org.opends.server.util.SetupUtils which are already included in
- * quicksetup.jar).
+ * case of DynamicConstants, SetupUtils, OperatingSystem and CertificateManager
+ * which are already included in quicksetup.jar).
  *
- * Important note: do not include references to the classes in package
- * org.opends.server in the import. These classes must be loaded during
- * Runtime.
+ * Important note: do not include references to this class until OpenDS.jar has
+ * been loaded. These classes must be loaded during Runtime.
  * The code is written in a way that when we execute the code that uses these
  * classes the required jar files are already loaded. However these jar files
  * are not necessarily loaded when we create this class.
  */
 public class InstallerHelper implements JnlpProperties {
+  private static final Logger LOG = Logger.getLogger(
+      InstallerHelper.class.getName());
+
+  private static final int MAX_ID_VALUE = Short.MAX_VALUE;
+  private static final String DOMAIN_BASE_NAME = "domain ";
 
   /**
    * Invokes the method ConfigureDS.configMain with the provided parameters.
@@ -58,7 +99,7 @@
    * @see org.opends.server.tools.ConfigureDS#configMain(String[]).
    */
   public int invokeConfigureServer(String[] args) throws ApplicationException {
-    return org.opends.server.tools.ConfigureDS.configMain(args);
+    return ConfigureDS.configMain(args);
   }
 
   /**
@@ -69,7 +110,7 @@
    * @see org.opends.server.tools.ImportLDIF#mainImportLDIF(String[]).
    */
   public int invokeImportLDIF(String[] args) throws ApplicationException {
-    return org.opends.server.tools.ImportLDIF.mainImportLDIF(args);
+    return ImportLDIF.mainImportLDIF(args);
   }
 
   /**
@@ -78,8 +119,7 @@
    */
   public String getStartedId()
   {
-    return String.valueOf(org.opends.server.messages.CoreMessages.
-        MSGID_DIRECTORY_SERVER_STARTED);
+    return String.valueOf(CoreMessages.MSGID_DIRECTORY_SERVER_STARTED);
   }
 
   /**
@@ -87,18 +127,16 @@
    * @throws ApplicationException if something goes wrong.
    */
   public void enableWindowsService() throws ApplicationException {
-    int code = org.opends.server.tools.ConfigureWindowsService.enableService(
-    System.out, System.err);
+    int code = ConfigureWindowsService.enableService(System.out, System.err);
 
-    String errorMessage = ResourceProvider.getInstance().getMsg(
-    "error-enabling-windows-service");
+    String errorMessage = getMsg("error-enabling-windows-service");
 
     switch (code) {
       case
-      org.opends.server.tools.ConfigureWindowsService.SERVICE_ENABLE_SUCCESS:
+        ConfigureWindowsService.SERVICE_ENABLE_SUCCESS:
         break;
       case
-      org.opends.server.tools.ConfigureWindowsService.SERVICE_ALREADY_ENABLED:
+        ConfigureWindowsService.SERVICE_ALREADY_ENABLED:
         break;
       default:
         throw new ApplicationException(
@@ -141,26 +179,21 @@
 
     try
     {
-      org.opends.server.types.LDIFExportConfig exportConfig =
-          new org.opends.server.types.LDIFExportConfig(ldifFile
-              .getAbsolutePath(),
-              org.opends.server.types.ExistingFileBehavior.OVERWRITE);
+      LDIFExportConfig exportConfig = new LDIFExportConfig(
+          ldifFile.getAbsolutePath(), ExistingFileBehavior.OVERWRITE);
 
-      org.opends.server.util.LDIFWriter writer =
-          new org.opends.server.util.LDIFWriter(exportConfig);
+      LDIFWriter writer = new LDIFWriter(exportConfig);
 
-      org.opends.server.types.DN dn =
-        org.opends.server.types.DN.decode(baseDn);
-      org.opends.server.types.Entry entry =
-          org.opends.server.util.StaticUtils.createEntry(dn);
+      DN dn = DN.decode(baseDn);
+      Entry entry = StaticUtils.createEntry(dn);
 
       writer.writeEntry(entry);
       writer.close();
-    } catch (org.opends.server.types.DirectoryException de) {
+    } catch (DirectoryException de) {
       throw new ApplicationException(
               ApplicationException.Type.CONFIGURATION_ERROR,
               getThrowableMsg("error-importing-ldif", null, de), de);
-    } catch (org.opends.server.util.LDIFException le) {
+    } catch (LDIFException le) {
       throw new ApplicationException(
               ApplicationException.Type.CONFIGURATION_ERROR,
               getThrowableMsg("error-importing-ldif", null, le), le);
@@ -175,4 +208,357 @@
     }
     return ldifFile;
   }
+
+  /**
+   * Configures the replication on a given server.
+   * @param remoteCtx the conection to the server where we want to configure
+   * the replication.
+   * @param dns the suffix base dns for which we want to configure the
+   * replication.
+   * @param replicationServers a Map where the key value is the base dn and
+   * the value is the list of replication servers for that base dn (or domain).
+   * @param replicationPort the replicationPort of the server that is being
+   * configured (it might not exist and the user specified it in the setup).
+   * @param serverDisplay the server display.
+   * @param usedReplicationServerIds the list of replication server ids that
+   * are already used.
+   * @param usedServerIds the list of server ids (domain ids) that
+   * are already used.
+   * @throws ApplicationException if something goes wrong.
+   */
+  public void configureReplication(InitialLdapContext remoteCtx,
+      Set<String> dns, Map<String,Set<String>> replicationServers,
+      int replicationPort, String serverDisplay,
+      Set<Integer> usedReplicationServerIds, Set<Integer> usedServerIds)
+  throws ApplicationException
+  {
+    try
+    {
+      ManagementContext mCtx = LDAPManagementContext.createFromContext(
+          JNDIDirContextAdaptor.adapt(remoteCtx));
+      RootCfgClient root = mCtx.getRootConfiguration();
+
+      /*
+       * Configure Synchronization plugin.
+       */
+      MultimasterSynchronizationProviderCfgClient sync = null;
+      try
+      {
+        sync = (MultimasterSynchronizationProviderCfgClient)
+        root.getSynchronizationProvider("Multimaster Synchronization");
+      }
+      catch (ManagedObjectNotFoundException monfe)
+      {
+        // It does not exist.
+      }
+      if (sync == null)
+      {
+        MultimasterSynchronizationProviderCfgDefn provider =
+          MultimasterSynchronizationProviderCfgDefn.getInstance();
+        sync = root.createSynchronizationProvider(provider,
+            "Multimaster Synchronization",
+            new ArrayList<DefaultBehaviorException>());
+        sync.setJavaImplementationClass(
+            "org.opends.server.replication.plugin.MultimasterReplication");
+      }
+      sync.setEnabled(Boolean.TRUE);
+      sync.commit();
+
+      /*
+       * Configure the replication server.
+       */
+      ReplicationServerCfgClient replicationServer = null;
+
+      if (!sync.hasReplicationServer())
+      {
+        int id = getReplicationId(usedReplicationServerIds);
+        usedReplicationServerIds.add(id);
+        replicationServer = sync.createReplicationServer(
+            ReplicationServerCfgDefn.getInstance(),
+            new ArrayList<DefaultBehaviorException>());
+        replicationServer.setReplicationServerId(id);
+        replicationServer.setReplicationPort(replicationPort);
+      }
+      else
+      {
+        replicationServer = sync.getReplicationServer();
+        usedReplicationServerIds.add(
+            replicationServer.getReplicationServerId());
+      }
+
+      Set<String> servers = replicationServer.getReplicationServer();
+      if (servers == null)
+      {
+        servers = new HashSet<String>();
+      }
+      for (Set<String> rs : replicationServers.values())
+      {
+        servers.addAll(rs);
+      }
+
+      replicationServer.setReplicationServer(servers);
+
+      replicationServer.commit();
+
+      /*
+       * Create the domains
+       */
+      String[] domainNames = sync.listMultimasterDomains();
+      if (domainNames == null)
+      {
+        domainNames = new String[]{};
+      }
+      MultimasterDomainCfgClient[] domains =
+        new MultimasterDomainCfgClient[domainNames.length];
+      for (int i=0; i<domains.length; i++)
+      {
+        domains[i] = sync.getMultimasterDomain(domainNames[i]);
+      }
+      for (String dn : dns)
+      {
+        MultimasterDomainCfgClient domain = null;
+        for (int i=0; i<domains.length && (domain == null); i++)
+        {
+          if (Utils.areDnsEqual(dn,
+              domains[i].getReplicationDN().toString()))
+          {
+            domain = domains[i];
+          }
+        }
+        if (domain == null)
+        {
+          int domainId = getReplicationId(usedServerIds);
+          usedServerIds.add(domainId);
+          String domainName = getDomainName(domainNames, domainId);
+          domain = sync.createMultimasterDomain(
+              MultimasterDomainCfgDefn.getInstance(), domainName,
+              new ArrayList<DefaultBehaviorException>());
+          domain.setServerId(domainId);
+          domain.setReplicationDN(DN.decode(dn));
+        }
+        domain.setReplicationServer(replicationServers.get(dn));
+        usedServerIds.add(domain.getServerId());
+
+        domain.commit();
+      }
+    }
+    catch (Throwable t)
+    {
+      String errorMessage = getMsg("error-configuring-remote-generic",
+          serverDisplay, t.toString());
+      throw new ApplicationException(
+          ApplicationException.Type.CONFIGURATION_ERROR, errorMessage, t);
+    }
+  }
+
+  /**
+   * For the given state provided by a Task tells if the task is done or not.
+   * @param sState the String representing the task state.
+   * @return <CODE>true</CODE> if the task is done and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isDone(String sState)
+  {
+    TaskState state = TaskState.fromString(sState);
+    return TaskState.isDone(state);
+  }
+
+  /**
+   * For the given state provided by a Task tells if the task is successful or
+   * not.
+   * @param sState the String representing the task state.
+   * @return <CODE>true</CODE> if the task is successful and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean isSuccessful(String sState)
+  {
+    TaskState state = TaskState.fromString(sState);
+    return TaskState.isSuccessful(state);
+  }
+
+  /**
+   * For the given state provided by a Task tells if the task is complete with
+   * errors or not.
+   * @param sState the String representing the task state.
+   * @return <CODE>true</CODE> if the task is complete with errors and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isCompletedWithErrors(String sState)
+  {
+    TaskState state = TaskState.fromString(sState);
+    return state == TaskState.COMPLETED_WITH_ERRORS;
+  }
+
+  /**
+   * For the given state provided by a Task tells if the task is stopped by
+   * error or not.
+   * @param sState the String representing the task state.
+   * @return <CODE>true</CODE> if the task is stopped by error and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isStoppedByError(String sState)
+  {
+    TaskState state = TaskState.fromString(sState);
+    return state == TaskState.STOPPED_BY_ERROR;
+  }
+
+  /**
+   * Tells whether the provided log message corresponds to a peers not found
+   * error during the initialization of a replica or not.
+   * @param logMsg the log message.
+   * @return <CODE>true</CODE> if the log message corresponds to a peers not
+   * found error during initialization and <CODE>false</CODE> otherwise.
+   */
+  public boolean isPeersNotFoundError(String logMsg)
+  {
+    return logMsg.indexOf(
+        "="+ReplicationMessages.MSGID_NO_REACHABLE_PEER_IN_THE_DOMAIN) != -1;
+  }
+  private void addConfigEntry(ConfigFileHandler configFileHandler, DN dn,
+      String[] ocs, String[] attributeNames, String[][] attributeValues)
+  throws DirectoryException
+  {
+    HashMap<ObjectClass,String> objectClasses =
+      new HashMap<ObjectClass,String>();
+    HashMap<AttributeType,List<Attribute>> userAttributes =
+      new HashMap<AttributeType,List<Attribute>>();
+    HashMap<AttributeType,List<Attribute>> operationalAttributes =
+      new HashMap<AttributeType,List<Attribute>>();
+
+    for (int j=0; j<ocs.length; j++)
+    {
+      String ocName = ocs[j];
+      ObjectClass objectClass = DirectoryServer.getObjectClass(ocName);
+      if (objectClass == null)
+      {
+        objectClass = DirectoryServer.getDefaultObjectClass(ocName);
+      }
+      objectClasses.put(objectClass, ocName);
+    }
+    for (int j=0; j<attributeNames.length; j++)
+    {
+      String attrName = attributeNames[j];
+      AttributeType attrType = DirectoryServer.getAttributeType(attrName);
+      if (attrType == null)
+      {
+        attrType = DirectoryServer.getDefaultAttributeType(attrName);
+      }
+      String[] attrValues = attributeValues[j];
+      LinkedHashSet<AttributeValue> valueSet =
+        new LinkedHashSet<AttributeValue>();
+      for (int k=0; k<attrValues.length; k++)
+      {
+        AttributeValue attributeValue = new AttributeValue(attrType,
+            attrValues[k]);
+        valueSet.add(attributeValue);
+      }
+      ArrayList<Attribute> attrList = new ArrayList<Attribute>();
+      attrList.add(new Attribute(attrType, attrName, null, valueSet));
+      userAttributes.put(attrType, attrList);
+    }
+    Entry entry = new Entry(dn, objectClasses, userAttributes,
+        operationalAttributes);
+    configFileHandler.addEntry(entry, null);
+  }
+
+  private int getReplicationId(Set<Integer> usedIds)
+  {
+    Random r = new Random();
+    int id = 0;
+    while ((id == 0) || usedIds.contains(id))
+    {
+      id = r.nextInt(MAX_ID_VALUE);
+    }
+    return id;
+  }
+
+  private String getMsg(String key, String ... args)
+  {
+    return ResourceProvider.getInstance().getMsg(key, args);
+  }
+
+  private String getDomainName(String[] existingDomains, int newDomainId)
+  {
+    String domainName = DOMAIN_BASE_NAME+newDomainId;
+    boolean nameExists = true;
+    int j = 0;
+    while (nameExists)
+    {
+      boolean found = false;
+      for (int i=0; i<existingDomains.length && !found; i++)
+      {
+        found = existingDomains[i].equalsIgnoreCase(domainName);
+      }
+      if (found)
+      {
+        domainName = DOMAIN_BASE_NAME+newDomainId+"-"+j;
+      }
+      else
+      {
+        nameExists = false;
+      }
+      j++;
+    }
+    return domainName;
+  }
 }
+
+/**
+ * A class describing a replication domain.
+ *
+ */
+class DomainEntry
+{
+  private String name;
+  private int replicationId;
+  private String baseDn;
+  private Set<String> replicationServers;
+  /**
+   * The constructor of the domain entry.
+   * @param name the name of the domain.
+   * @param replicationId the replicationId of the domain.
+   * @param baseDn the base dn of the domain.
+   * @param replicationServers the list of replication servers for the domain.
+   */
+  public DomainEntry(String name, int replicationId, String baseDn,
+      Set<String> replicationServers)
+  {
+    this.name = name;
+    this.replicationId = replicationId;
+    this.baseDn = baseDn;
+    this.replicationServers = replicationServers;
+  }
+  /**
+   * Returns the base dn of the domain.
+   * @return the base dn of the domain.
+   */
+  public String getBaseDn()
+  {
+    return baseDn;
+  }
+  /**
+   * Returns the name of the domain.
+   * @return the name of the domain.
+   */
+  public String getName()
+  {
+    return name;
+  }
+  /**
+   * Returns the replication Id of the domain.
+   * @return the replication Id of the domain.
+   */
+  public int getReplicationId()
+  {
+    return replicationId;
+  }
+  /**
+   * Returns the list of replication servers of the domain.
+   * @return the list of replication servers of the domain.
+   */
+  public Set<String> getReplicationServers()
+  {
+    return replicationServers;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
index bcee79c..cf2dc2f 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/offline/OfflineInstaller.java
@@ -30,6 +30,8 @@
 import java.io.PrintStream;
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import org.opends.quicksetup.ApplicationException;
 import org.opends.quicksetup.ProgressStep;
@@ -62,6 +64,8 @@
   private HashMap<InstallProgressStep, String> hmSummary =
       new HashMap<InstallProgressStep, String>();
 
+  private static final Logger LOG =
+    Logger.getLogger(OfflineInstaller.class.getName());
   /**
    * Actually performs the install in this thread.  The thread is blocked.
    *
@@ -84,8 +88,6 @@
 
       createData();
 
-      updateADS();
-
       writeJavaHome();
 
       if (Utils.isWindows())
@@ -95,29 +97,64 @@
           enableWindowsService();
       }
 
-      if (getUserData().getStartServer())
+      if (mustStart())
       {
         notifyListeners(getTaskSeparator());
         setStatus(InstallProgressStep.STARTING_SERVER);
         new ServerController(this).startServer();
       }
 
+      if (mustConfigureReplication())
+      {
+        setStatus(InstallProgressStep.CONFIGURING_REPLICATION);
+        notifyListeners(getTaskSeparator());
+
+        configureReplication();
+      }
+
+      if (mustInitializeSuffixes())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+        initializeSuffixes();
+      }
+
+      if (mustCreateAds())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.CONFIGURING_ADS);
+        updateADS();
+      }
+
+      if (mustStop())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.STOPPING_SERVER);
+        new ServerController(this).stopServer();
+      }
+
       setStatus(InstallProgressStep.FINISHED_SUCCESSFULLY);
       notifyListeners(null);
 
     } catch (ApplicationException ex)
     {
+      notifyListeners(getLineBreak());
+      notifyListenersOfLog();
       setStatus(InstallProgressStep.FINISHED_WITH_ERROR);
       String html = getFormattedError(ex, true);
       notifyListeners(html);
+      LOG.log(Level.SEVERE, "Error installing.", ex);
     }
     catch (Throwable t)
     {
+      notifyListeners(getLineBreak());
+      notifyListenersOfLog();
       setStatus(InstallProgressStep.FINISHED_WITH_ERROR);
       ApplicationException ex = new ApplicationException(
           ApplicationException.Type.BUG, getThrowableMsg("bug-msg", t), t);
       String msg = getFormattedError(ex, true);
       notifyListeners(msg);
+      LOG.log(Level.SEVERE, "Error installing.", t);
     }
     System.setErr(origErr);
     System.setOut(origOut);
@@ -158,43 +195,76 @@
     hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
     hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
     hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
-    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
-        20);
+    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED, 20);
+    hmTime.put(InstallProgressStep.CONFIGURING_REPLICATION, 10);
     hmTime.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, 5);
     hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+    hmTime.put(InstallProgressStep.STOPPING_SERVER, 5);
+    hmTime.put(InstallProgressStep.CONFIGURING_ADS, 5);
+    hmTime.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES, 25);
 
     int totalTime = 0;
     ArrayList<InstallProgressStep> steps =
         new ArrayList<InstallProgressStep>();
     totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
     steps.add(InstallProgressStep.CONFIGURING_SERVER);
-    switch (getUserData().getNewSuffixOptions().getType())
+    if (createNotReplicatedSuffix())
     {
-    case CREATE_BASE_ENTRY:
-      steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
-      totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
-      break;
-    case IMPORT_FROM_LDIF_FILE:
-      steps.add(InstallProgressStep.IMPORTING_LDIF);
-      totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
-      break;
-    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
-      steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
-      totalTime += hmTime.get(
-              InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
-      break;
+      switch (getUserData().getNewSuffixOptions().getType())
+      {
+      case CREATE_BASE_ENTRY:
+        steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+        totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+        break;
+      case IMPORT_FROM_LDIF_FILE:
+        steps.add(InstallProgressStep.IMPORTING_LDIF);
+        totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+        break;
+      case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+        steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+        totalTime += hmTime.get(
+            InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+        break;
+      }
     }
+
     if (Utils.isWindows())
     {
       totalTime += hmTime.get(InstallProgressStep.ENABLING_WINDOWS_SERVICE);
       steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE);
     }
-    if (getUserData().getStartServer())
+
+    if (mustStart())
     {
       totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
       steps.add(InstallProgressStep.STARTING_SERVER);
     }
 
+    if (mustConfigureReplication())
+    {
+      steps.add(InstallProgressStep.CONFIGURING_REPLICATION);
+      totalTime += hmTime.get(InstallProgressStep.CONFIGURING_REPLICATION);
+    }
+
+    if (mustInitializeSuffixes())
+    {
+      totalTime += hmTime.get(
+          InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+      steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+    }
+
+    if (mustCreateAds())
+    {
+      totalTime += hmTime.get(InstallProgressStep.CONFIGURING_ADS);
+      steps.add(InstallProgressStep.CONFIGURING_ADS);
+    }
+
+    if (mustStop())
+    {
+      totalTime += hmTime.get(InstallProgressStep.STOPPING_SERVER);
+      steps.add(InstallProgressStep.STOPPING_SERVER);
+    }
+
     int cumulatedTime = 0;
     for (InstallProgressStep s : steps)
     {
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/DataReplicationPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/DataReplicationPanel.java
index be58712..c441344 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/DataReplicationPanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/DataReplicationPanel.java
@@ -68,6 +68,7 @@
   private JRadioButton rbStandalone;
   private JRadioButton rbReplicated;
   private JCheckBox cbTopologyExists;
+  private JCheckBox cbRemoteServerPortSecure;
   private HashMap<FieldName, JLabel> hmLabels =
     new HashMap<FieldName, JLabel>();
   private HashMap<FieldName, JTextComponent> hmFields =
@@ -111,6 +112,17 @@
         value = DataReplicationOptions.Type.FIRST_IN_TOPOLOGY;
       }
     }
+    else if (fieldName == FieldName.REMOTE_SERVER_IS_SECURE_PORT)
+    {
+      if (cbRemoteServerPortSecure.isSelected())
+      {
+        value = Boolean.TRUE;
+      }
+      else
+      {
+        value = Boolean.FALSE;
+      }
+    }
     else
     {
       JTextComponent field = getField(fieldName);
@@ -165,10 +177,31 @@
 
     gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
     gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
-    panel.add(cbTopologyExists, gbc);
-
     JPanel auxPanel = new JPanel(new GridBagLayout());
     auxPanel.setOpaque(false);
+    panel.add(auxPanel, gbc);
+    panel.add(cbTopologyExists, gbc);
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.gridwidth = 3;
+    gbc.weightx = 0.0;
+    gbc.insets.left = 0;
+    gbc.anchor = GridBagConstraints.WEST;
+    auxPanel.add(getLabel(FieldName.REPLICATION_PORT), gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.weightx = 0.0;
+    auxPanel.add(getField(FieldName.REPLICATION_PORT), gbc);
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = 0;
+    gbc.weightx = 1.0;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    auxPanel.add(Box.createHorizontalGlue(), gbc);
+
+    auxPanel = new JPanel(new GridBagLayout());
+    auxPanel.setOpaque(false);
     gbc.insets.left = 2 * UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
     panel.add(auxPanel, gbc);
 
@@ -200,12 +233,26 @@
 
       JPanel aux2Panel = new JPanel(new GridBagLayout());
       aux2Panel.setOpaque(false);
-      gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+      if (fields[i] == FieldName.REMOTE_SERVER_PORT)
+      {
+        gbc.gridwidth = 3;
+      }
+      else
+      {
+        gbc.gridwidth = GridBagConstraints.RELATIVE;
+      }
       gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
       gbc.fill = GridBagConstraints.HORIZONTAL;
       gbc.weightx = 0.0;
       aux2Panel.add(getField(fields[i]), gbc);
 
+      if (fields[i] == FieldName.REMOTE_SERVER_PORT)
+      {
+        gbc.gridwidth = GridBagConstraints.RELATIVE;
+        aux2Panel.add(cbRemoteServerPortSecure, gbc);
+      }
+
       gbc.gridwidth = GridBagConstraints.REMAINDER;
       gbc.insets.left = 0;
       gbc.weightx = 1.0;
@@ -264,6 +311,10 @@
       defaultUserData.getReplicationOptions().getAuthenticationData();
     switch (fieldName)
     {
+    case REPLICATION_PORT:
+      value = defaultUserData.getReplicationOptions().getReplicationPort();
+      break;
+
     case REMOTE_SERVER_DN:
       value = auth.getDn();
       break;
@@ -324,6 +375,13 @@
     HashMap<FieldName, LabelFieldDescriptor> hm =
         new HashMap<FieldName, LabelFieldDescriptor>();
 
+    hm.put(FieldName.REPLICATION_PORT, new LabelFieldDescriptor(
+        getMsg("replication-port-label"),
+        getMsg("replication-port-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.SECONDARY,
+        UIFactory.PORT_FIELD_SIZE));
+
     hm.put(FieldName.REMOTE_SERVER_DN, new LabelFieldDescriptor(
         getMsg("remote-server-dn-label"), getMsg("remote-server-dn-tooltip"),
         LabelFieldDescriptor.FieldType.TEXTFIELD,
@@ -392,6 +450,10 @@
       DataReplicationOptions.Type.STANDALONE);
     cbTopologyExists.setSelected(type ==
       DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY);
+    cbRemoteServerPortSecure = UIFactory.makeJCheckBox(
+        getMsg("remote-server-port-is-secure-label"),
+        getMsg("remote-server-port-is-secure-tooltip"),
+        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
     checkEnablingState();
   }
 
@@ -449,7 +511,10 @@
         if (lastFocusComponent instanceof JTextComponent)
         {
           rbReplicated.setSelected(true);
-          cbTopologyExists.setSelected(true);
+          if (lastFocusComponent != getField(FieldName.REPLICATION_PORT))
+          {
+            cbTopologyExists.setSelected(true);
+          }
         }
       }
 
@@ -515,6 +580,9 @@
     }
 
     cbTopologyExists.setEnabled(rbReplicated.isSelected());
+    getLabel(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected());
+    getField(FieldName.REPLICATION_PORT).setEnabled(rbReplicated.isSelected());
+    cbRemoteServerPortSecure.setEnabled(enableFields);
   }
 
   /**
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/InstallReviewPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/InstallReviewPanel.java
index 07296a3..10f7b90 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/InstallReviewPanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/InstallReviewPanel.java
@@ -27,6 +27,7 @@
 
 package org.opends.quicksetup.installer.ui;
 
+import org.opends.admin.ads.ServerDescriptor;
 import org.opends.admin.ads.SuffixDescriptor;
 import org.opends.quicksetup.UserData;
 import org.opends.quicksetup.installer.DataReplicationOptions;
@@ -37,8 +38,12 @@
 import javax.swing.*;
 import javax.swing.text.JTextComponent;
 import java.awt.*;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
 import java.util.HashMap;
+import java.util.Map;
 import java.util.Set;
+import java.util.TreeSet;
 
 /**
  * This is the panel that contains the Review Panel.
@@ -55,7 +60,9 @@
 
   private HashMap<FieldName, JTextComponent> hmFields =
       new HashMap<FieldName, JTextComponent>();
+  private JPanel bottomComponent;
   private JCheckBox checkBox;
+  private JLabel warningLabel;
 
   /**
    * Constructor of the panel.
@@ -97,6 +104,21 @@
       getField(FieldName.GLOBAL_ADMINISTRATOR_UID).setVisible(false);
       getLabel(FieldName.GLOBAL_ADMINISTRATOR_UID).setVisible(false);
     }
+
+    if (userData.getReplicationOptions().getType() ==
+      DataReplicationOptions.Type.STANDALONE)
+    {
+      getField(FieldName.REPLICATION_PORT).setVisible(false);
+      getLabel(FieldName.REPLICATION_PORT).setVisible(false);
+    }
+    else
+    {
+      setFieldValue(FieldName.REPLICATION_PORT,
+          getReplicationPortString(userData));
+      getField(FieldName.REPLICATION_PORT).setVisible(true);
+      getLabel(FieldName.REPLICATION_PORT).setVisible(true);
+    }
+    checkStartWarningLabel();
   }
 
   /**
@@ -169,6 +191,12 @@
         getMsg("directory-data-label"), null,
         LabelFieldDescriptor.FieldType.READ_ONLY,
         LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
+    hm.put(FieldName.REPLICATION_PORT, new LabelFieldDescriptor(
+        getMsg("replication-port-label"), null,
+        LabelFieldDescriptor.FieldType.READ_ONLY,
+        LabelFieldDescriptor.LabelType.PRIMARY, 0));
+
     for (FieldName fieldName : hm.keySet())
     {
       LabelFieldDescriptor desc = hm.get(fieldName);
@@ -216,6 +244,7 @@
     getField(fieldName).setText(value);
   }
 
+
   /**
    * Returns the localized string describing the DataOptions chosen by the user.
    * @param options the DataOptions of the user.
@@ -289,7 +318,49 @@
 
     return msg;
   }
+   /**
+    * Returns the String representing the replication port configuration.
+    * @param options the DataOptions of the user.
+    * @return the localized string describing the Replication Ports chosen by
+    * the user.
+    */
+  private String getReplicationPortString(UserData userInstallData)
+  {
+    StringBuilder buf = new StringBuilder();
 
+    DataReplicationOptions repl =
+      userInstallData.getReplicationOptions();
+
+    SuffixesToReplicateOptions suf =
+      userInstallData.getSuffixesToReplicateOptions();
+
+    Map<ServerDescriptor, Integer> remotePorts =
+      userInstallData.getRemoteWithNoReplicationPort();
+
+    if ((repl.getType() == DataReplicationOptions.Type.IN_EXISTING_TOPOLOGY) &&
+      (suf.getType() ==
+        SuffixesToReplicateOptions.Type.REPLICATE_WITH_EXISTING_SUFFIXES) &&
+        remotePorts.size() > 0)
+    {
+      buf.append(userInstallData.getReplicationOptions().getReplicationPort());
+      TreeSet<String> remoteServerLines = new TreeSet<String>();
+      for (ServerDescriptor server : remotePorts.keySet())
+      {
+        String[] args = {String.valueOf(remotePorts.get(server)),
+            server.getHostPort(true)};
+        remoteServerLines.add(getMsg("remote-server-replication-port", args));
+      }
+      for (String line : remoteServerLines)
+      {
+        buf.append("\n"+line);
+      }
+    }
+    else
+    {
+      buf.append(userInstallData.getReplicationOptions().getReplicationPort());
+    }
+    return buf.toString();
+  }
   /**
    * Returns and creates the fields panel.
    * @return the fields panel.
@@ -308,7 +379,8 @@
           {
             FieldName.SERVER_LOCATION, FieldName.SERVER_PORT,
             FieldName.SECURITY_OPTIONS, FieldName.DIRECTORY_MANAGER_DN,
-            FieldName.GLOBAL_ADMINISTRATOR_UID, FieldName.DATA_OPTIONS
+            FieldName.GLOBAL_ADMINISTRATOR_UID, FieldName.DATA_OPTIONS,
+            FieldName.REPLICATION_PORT
           };
     }
     else
@@ -318,7 +390,7 @@
           {
             FieldName.SERVER_PORT, FieldName.SECURITY_OPTIONS,
             FieldName.DIRECTORY_MANAGER_DN, FieldName.GLOBAL_ADMINISTRATOR_UID,
-            FieldName.DATA_OPTIONS
+            FieldName.DATA_OPTIONS, FieldName.REPLICATION_PORT
           };
     }
 
@@ -359,7 +431,37 @@
   /**
    * {@inheritDoc}
    */
-  protected JCheckBox getCheckBox()
+  protected JComponent getBottomComponent()
+  {
+    if (bottomComponent == null)
+    {
+      bottomComponent = new JPanel(new GridBagLayout());
+      GridBagConstraints gbc = new GridBagConstraints();
+      gbc.gridwidth = 3;
+      bottomComponent.add(getCheckBox(), gbc);
+      gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      bottomComponent.add(getWarningLabel(), gbc);
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.insets.left = 0;
+      gbc.weightx = 1.0;
+      bottomComponent.add(Box.createHorizontalGlue(), gbc);
+    }
+    return bottomComponent;
+  }
+
+  private JLabel getWarningLabel()
+  {
+    if (warningLabel == null)
+    {
+      warningLabel = UIFactory.makeJLabel(UIFactory.IconType.WARNING,
+          getMsg("install-server-must-be-temporarily-started"),
+          UIFactory.TextStyle.READ_ONLY);
+    }
+    return warningLabel;
+  }
+
+  private JCheckBox getCheckBox()
   {
     if (checkBox == null)
     {
@@ -367,7 +469,30 @@
           UIFactory.makeJCheckBox(getMsg("start-server-label"),
               getMsg("start-server-tooltip"), UIFactory.TextStyle.CHECKBOX);
       checkBox.setSelected(getApplication().getUserData().getStartServer());
+      checkBox.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent ev)
+        {
+          checkStartWarningLabel();
+        }
+      });
     }
     return checkBox;
   }
+
+  /**
+   * Depending on whether we want to replicate or not, we do have to start
+   * the server temporarily to update its configuration and initialize data.
+   */
+  private void checkStartWarningLabel()
+  {
+    boolean visible = !getCheckBox().isSelected();
+    if (visible)
+    {
+      UserData userData = getApplication().getUserData();
+      DataReplicationOptions rep = userData.getReplicationOptions();
+      visible = rep.getType() != DataReplicationOptions.Type.STANDALONE;
+    }
+    getWarningLabel().setVisible(visible);
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RemoteReplicationPortsPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RemoteReplicationPortsPanel.java
new file mode 100644
index 0000000..9a918f9
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/RemoteReplicationPortsPanel.java
@@ -0,0 +1,310 @@
+/*
+ * 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
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.installer.ui;
+
+import java.awt.Component;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+
+import javax.swing.Box;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.EmptyBorder;
+import javax.swing.text.JTextComponent;
+
+import org.opends.admin.ads.ServerDescriptor;
+
+import org.opends.quicksetup.UserData;
+import org.opends.quicksetup.ui.FieldName;
+import org.opends.quicksetup.ui.GuiApplication;
+import org.opends.quicksetup.ui.LabelFieldDescriptor;
+import org.opends.quicksetup.ui.QuickSetupStepPanel;
+import org.opends.quicksetup.ui.UIFactory;
+
+/**
+ * This class is used to provide a data model for the list of servers for which
+ * we must provide a replication port.
+ */
+public class RemoteReplicationPortsPanel extends QuickSetupStepPanel
+implements Comparator<ServerDescriptor>
+{
+  private static final long serialVersionUID = -3742350600617826375L;
+  private Component lastFocusComponent;
+  private HashMap<String, JLabel> hmLabels =
+    new HashMap<String, JLabel>();
+  private HashMap<String, JTextComponent> hmFields =
+    new HashMap<String, JTextComponent>();
+  private JScrollPane scroll;
+  private JPanel fieldsPanel;
+  private TreeSet<ServerDescriptor> orderedServers =
+    new TreeSet<ServerDescriptor>(this);
+  /**
+   * Constructor of the panel.
+   * @param application Application represented by this panel and used to
+   * initialize the fields of the panel.
+   */
+  public RemoteReplicationPortsPanel(GuiApplication application)
+  {
+    super(application);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public Object getFieldValue(FieldName fieldName)
+  {
+    Object value = null;
+
+    if (fieldName == FieldName.REMOTE_REPLICATION_PORT)
+    {
+      Map<String, String> hm = new HashMap<String, String>();
+      for (String id : hmFields.keySet())
+      {
+        hm.put(id, hmFields.get(id).getText());
+      }
+      value = hm;
+    }
+    return value;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void displayFieldInvalid(FieldName fieldName, boolean invalid)
+  {
+    if (fieldName == FieldName.REMOTE_REPLICATION_PORT)
+    {
+      for (String id : hmLabels.keySet())
+      {
+        UIFactory.setTextStyle(hmLabels.get(id),
+            UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+      }
+      if (invalid)
+      {
+        for (String id : hmLabels.keySet())
+        {
+          String sPort = hmFields.get(id).getText();
+          boolean isValid = false;
+          try
+          {
+            int replicationPort = Integer.parseInt(sPort);
+            if ((replicationPort >= 1) &&
+                (replicationPort <= 65535))
+            {
+              isValid = true;
+            }
+          }
+          catch (Throwable t)
+          {
+          }
+          if (!isValid)
+          {
+            UIFactory.setTextStyle(hmLabels.get(id),
+              UIFactory.TextStyle.SECONDARY_FIELD_INVALID);
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int compare(ServerDescriptor desc1, ServerDescriptor desc2)
+  {
+    return desc1.getHostPort(true).compareTo(desc2.getHostPort(true));
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected Component createInputPanel()
+  {
+    JPanel panel = new JPanel(new GridBagLayout());
+    panel.setOpaque(false);
+
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.weightx = 1.0;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.weighty = 1.0;
+    gbc.fill = GridBagConstraints.BOTH;
+    fieldsPanel = new JPanel(new GridBagLayout());
+    fieldsPanel.setOpaque(false);
+    scroll = new JScrollPane(fieldsPanel);
+    scroll.setBorder(new EmptyBorder(0, 0, 0, 0));
+    scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0));
+    scroll.setOpaque(false);
+    scroll.getViewport().setOpaque(false);
+
+    panel.add(scroll, gbc);
+
+    return panel;
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getInstructions()
+  {
+    return getMsg("remote-replication-port-instructions");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  protected String getTitle()
+  {
+    return getMsg("remote-replication-port-title");
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void beginDisplay(UserData data)
+  {
+    TreeSet<ServerDescriptor> array = orderServers(
+        data.getRemoteWithNoReplicationPort().keySet());
+    if (!array.equals(orderedServers))
+    {
+      /**
+       * Adds the required focus listeners to the fields.
+       */
+      final FocusListener l = new FocusListener()
+      {
+        public void focusGained(FocusEvent e)
+        {
+          lastFocusComponent = e.getComponent();
+        }
+
+        public void focusLost(FocusEvent e)
+        {
+        }
+      };
+      lastFocusComponent = null;
+      HashMap<String, String> hmOldValues = new HashMap<String, String>();
+      for (String id : hmFields.keySet())
+      {
+        hmOldValues.put(id, hmFields.get(id).getText());
+      }
+      orderedServers.clear();
+      orderedServers.addAll(array);
+      hmFields.clear();
+      hmLabels.clear();
+      for (ServerDescriptor server : orderedServers)
+      {
+        LabelFieldDescriptor desc = new LabelFieldDescriptor(
+            server.getHostPort(true), getMsg("replication-port-tooltip"),
+            LabelFieldDescriptor.FieldType.TEXTFIELD,
+            LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.PORT_FIELD_SIZE);
+        Integer defaultValue =
+          data.getRemoteWithNoReplicationPort().get(server);
+        JTextComponent field = UIFactory.makeJTextComponent(desc,
+            String.valueOf(defaultValue));
+        String oldValue = hmOldValues.get(server.getId());
+        if (oldValue != null)
+        {
+          field.setText(oldValue);
+        }
+
+        JLabel label = UIFactory.makeJLabel(desc);
+
+        hmFields.put(server.getId(), field);
+        label.setLabelFor(field);
+        field.addFocusListener(l);
+        if (lastFocusComponent == null)
+        {
+          lastFocusComponent = field;
+        }
+
+        hmLabels.put(server.getId(), label);
+      }
+      populateFieldsPanel();
+    }
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public void endDisplay()
+  {
+    if (lastFocusComponent != null)
+    {
+      lastFocusComponent.requestFocusInWindow();
+    }
+  }
+
+  private void populateFieldsPanel()
+  {
+    fieldsPanel.removeAll();
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    boolean first = true;
+    for (ServerDescriptor server : orderedServers)
+    {
+      gbc.insets.left = 0;
+      gbc.weightx = 0.0;
+      if (!first)
+      {
+        gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
+      }
+      gbc.gridwidth = 3;
+      fieldsPanel.add(hmLabels.get(server.getId()), gbc);
+      gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+      gbc.gridwidth = GridBagConstraints.RELATIVE;
+      fieldsPanel.add(hmFields.get(server.getId()), gbc);
+      gbc.gridwidth = GridBagConstraints.REMAINDER;
+      gbc.weightx = 1.0;
+      fieldsPanel.add(Box.createHorizontalGlue(), gbc);
+      first = false;
+    }
+    addVerticalGlue(fieldsPanel);
+  }
+
+  private TreeSet<ServerDescriptor> orderServers(
+  Set<ServerDescriptor> servers)
+  {
+    TreeSet<ServerDescriptor> ordered = new TreeSet<ServerDescriptor>(this);
+    ordered.addAll(servers);
+
+    return ordered;
+  }
+}
+
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
index f9e844f..0101bc4 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SecurityOptionsDialog.java
@@ -77,8 +77,6 @@
   private JTextField tfPort;
   private JRadioButton rbUseSelfSignedCertificate;
   private JRadioButton rbUseExistingCertificate;
-  private JLabel lSelfSignedName;
-  private JTextField tfSelfSignedName;
   private JLabel lKeystoreType;
   private JRadioButton rbPKCS11;
   private JRadioButton rbJKS;
@@ -163,8 +161,6 @@
     }
     UIFactory.setTextStyle(cbEnableSSL,
         UIFactory.TextStyle.SECONDARY_FIELD_VALID);
-    UIFactory.setTextStyle(lSelfSignedName,
-        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
     UIFactory.setTextStyle(lKeystorePath,
         UIFactory.TextStyle.SECONDARY_FIELD_VALID);
     UIFactory.setTextStyle(lKeystorePwd,
@@ -203,7 +199,7 @@
       if (rbUseSelfSignedCertificate.isSelected())
       {
         ops = SecurityOptions.createSelfSignedCertificateOptions(
-            tfSelfSignedName.getText(), enableSSL, enableStartTLS, sslPort);
+            enableSSL, enableStartTLS, sslPort);
       }
       else if (rbJKS.isSelected())
       {
@@ -365,15 +361,6 @@
         getMsg("use-self-signed-tooltip"),
         UIFactory.TextStyle.SECONDARY_FIELD_VALID);
     rbUseSelfSignedCertificate.addActionListener(l);
-    lSelfSignedName = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
-        getMsg("self-signed-certificate-name-label"),
-        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
-    lSelfSignedName.setOpaque(false);
-    String selfSignedName = securityOptions.getSelfSignedCertificateName();
-    tfSelfSignedName = UIFactory.makeJTextField(selfSignedName,
-        getMsg("self-signed-certificate-name-tooltip"),
-        UIFactory.HOST_FIELD_SIZE, UIFactory.TextStyle.TEXTFIELD);
-    lSelfSignedName.setLabelFor(tfSelfSignedName);
     rbUseExistingCertificate = UIFactory.makeJRadioButton(
         getMsg("use-existing-certificate-label"),
         getMsg("use-existing-certificate-tooltip"),
@@ -517,22 +504,6 @@
 
     aux2Panel = new JPanel(new GridBagLayout());
     aux2Panel.setOpaque(false);
-    gbc.weightx = 0.0;
-    gbc.gridwidth = 3;
-    aux2Panel.add(lSelfSignedName, gbc);
-    gbc.gridwidth = GridBagConstraints.RELATIVE;
-    gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
-    aux2Panel.add(tfSelfSignedName, gbc);
-    gbc.weightx = 1.0;
-    gbc.gridwidth = GridBagConstraints.REMAINDER;
-    gbc.insets.left = 0;
-    aux2Panel.add(Box.createHorizontalGlue(), gbc);
-    gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
-    gbc.insets.left = UIFactory.LEFT_INSET_RADIO_SUBORDINATE;
-    auxPanel.add(aux2Panel, gbc);
-
-    aux2Panel = new JPanel(new GridBagLayout());
-    aux2Panel.setOpaque(false);
     gbc.gridwidth = GridBagConstraints.RELATIVE;
     gbc.insets = UIFactory.getEmptyInsets();
     gbc.weightx = 0.0;
@@ -679,8 +650,6 @@
 
         errorMsgs.addAll(checkPort());
 
-        errorMsgs.addAll(checkSelfSigned());
-
         errorMsgs.addAll(checkKeystore());
 
         return errorMsgs;
@@ -796,7 +765,6 @@
 
     case SELF_SIGNED_CERTIFICATE:
       rbUseSelfSignedCertificate.setSelected(true);
-      tfSelfSignedName.setText(securityOptions.getSelfSignedCertificateName());
       break;
 
     case JKS:
@@ -851,10 +819,6 @@
     tfPort.setEnabled(enableSSL);
 
     rbUseSelfSignedCertificate.setEnabled(useSSL);
-    lSelfSignedName.setEnabled(
-        rbUseSelfSignedCertificate.isSelected() && useSSL);
-    tfSelfSignedName.setEnabled(
-        rbUseSelfSignedCertificate.isSelected() && useSSL);
 
     rbUseExistingCertificate.setEnabled(useSSL);
     lKeystoreType.setEnabled(
@@ -965,38 +929,6 @@
   }
 
   /**
-   * Checks the self-signed certificate parameters.
-   * @return the error messages found while checking self-signed certificate
-   * parameters.
-   */
-  private ArrayList<String> checkSelfSigned()
-  {
-    ArrayList<String> errorMsgs = new ArrayList<String>();
-
-    if (rbUseSelfSignedCertificate.isSelected() &&
-        (cbEnableSSL.isSelected() || cbEnableStartTLS.isSelected()))
-    {
-      String name = tfSelfSignedName.getText();
-      if ((name != null) && (name.length() > 0))
-      {
-        /* TODO: We might try to do something to check if the user provided a
-         * valid host name, but we cannot guarantee that the check will be valid
-         * AND we might want to allow the user to use a common name for the
-         * certificate that is not the host name.
-         */
-      }
-      else
-      {
-        errorMsgs.add(getMsg("no-self-signed-cert-name-provided"));
-      }
-    }
-
-    setValidLater(lSelfSignedName, errorMsgs.size() == 0);
-
-    return errorMsgs;
-  }
-
-  /**
    * Checks the existing keystore parameters.
    * @return the error messages found while checking existing keystore
    * parameters.
@@ -1045,7 +977,6 @@
 
       if (pathValid && pwdValid)
       {
-        // TODO: put the password in a temporary file to do the checks.
         try
         {
           CertificateManager certManager;
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
index e81db0a..9060834 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/ServerSettingsPanel.java
@@ -53,6 +53,7 @@
 import org.opends.quicksetup.util.Utils;
 import org.opends.quicksetup.SecurityOptions;
 import org.opends.quicksetup.UserData;
+import org.opends.server.util.CertificateManager;
 
 /**
  * This is the panel that contains the Server Settings: the port, the Directory
@@ -103,8 +104,7 @@
     super(application);
     this.defaultUserData = application.getUserData();
     this.displayServerLocation = isWebStart();
-    canUpdateSecurity =
-      org.opends.server.util.CertificateManager.mayUseCertificateManager();
+    canUpdateSecurity = CertificateManager.mayUseCertificateManager();
     securityOptions = defaultUserData.getSecurityOptions();
     populateLabelAndFieldMaps();
     addFocusListeners();
@@ -185,6 +185,7 @@
 
     FieldName[] fieldNames =
     {
+        FieldName.HOST_NAME,
         FieldName.SERVER_PORT,
         FieldName.SECURITY_OPTIONS,
         FieldName.DIRECTORY_MANAGER_DN,
@@ -376,6 +377,10 @@
       value = defaultUserData.getServerLocation();
       break;
 
+    case HOST_NAME:
+      value = defaultUserData.getHostName();
+      break;
+
     case SERVER_PORT:
       if (defaultUserData.getServerPort() > 0)
       {
@@ -420,6 +425,11 @@
     HashMap<FieldName, LabelFieldDescriptor> hm =
         new HashMap<FieldName, LabelFieldDescriptor>();
 
+    hm.put(FieldName.HOST_NAME, new LabelFieldDescriptor(
+        getMsg("host-name-label"), getMsg("host-name-tooltip"),
+        LabelFieldDescriptor.FieldType.TEXTFIELD,
+        LabelFieldDescriptor.LabelType.PRIMARY, UIFactory.HOST_FIELD_SIZE));
+
     hm.put(FieldName.SERVER_PORT, new LabelFieldDescriptor(
         getMsg("server-port-label"), getMsg("server-port-tooltip"),
         LabelFieldDescriptor.FieldType.TEXTFIELD,
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SuffixesToReplicatePanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SuffixesToReplicatePanel.java
index 063bc26..e0b179f 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SuffixesToReplicatePanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/ui/SuffixesToReplicatePanel.java
@@ -51,17 +51,18 @@
 import javax.swing.SwingConstants;
 import javax.swing.border.EmptyBorder;
 
+import org.opends.admin.ads.ADSContext;
 import org.opends.admin.ads.ReplicaDescriptor;
 import org.opends.admin.ads.ServerDescriptor;
 import org.opends.admin.ads.SuffixDescriptor;
 
-
 import org.opends.quicksetup.UserData;
 import org.opends.quicksetup.installer.SuffixesToReplicateOptions;
 import org.opends.quicksetup.ui.FieldName;
 import org.opends.quicksetup.ui.GuiApplication;
 import org.opends.quicksetup.ui.QuickSetupStepPanel;
 import org.opends.quicksetup.ui.UIFactory;
+import org.opends.quicksetup.util.Utils;
 
 /**
  * This class is used to provide a data model for the list of suffixes that
@@ -75,8 +76,8 @@
   private UserData defaultUserData;
   private TreeSet<SuffixDescriptor> orderedSuffixes =
     new TreeSet<SuffixDescriptor>(this);
-  private HashMap<SuffixDescriptor, JCheckBox> hmCheckBoxes =
-    new HashMap<SuffixDescriptor, JCheckBox>();
+  private HashMap<String, JCheckBox> hmCheckBoxes =
+    new HashMap<String, JCheckBox>();
   private Set<JEditorPane> suffixLabels = new HashSet<JEditorPane>();
 
   private JRadioButton rbCreateNewSuffix;
@@ -123,7 +124,7 @@
       Set<SuffixDescriptor> suffixes = new HashSet<SuffixDescriptor>();
       for (SuffixDescriptor suffix:orderedSuffixes)
       {
-        if (hmCheckBoxes.get(suffix).isSelected())
+        if (hmCheckBoxes.get(suffix.getId()).isSelected())
         {
           suffixes.add(suffix);
         }
@@ -244,12 +245,23 @@
   {
     TreeSet<SuffixDescriptor> array = orderSuffixes(
         data.getSuffixesToReplicateOptions().getAvailableSuffixes());
-    Set<SuffixDescriptor> chosen =
-      data.getSuffixesToReplicateOptions().getSuffixes();
+
     if (!array.equals(orderedSuffixes))
     {
+      HashMap<String, Boolean> hmOldValues = new HashMap<String, Boolean>();
+      for (String id : hmCheckBoxes.keySet())
+      {
+        hmOldValues.put(id, hmCheckBoxes.get(id).isSelected());
+      }
       orderedSuffixes.clear();
-      orderedSuffixes.addAll(array);
+      for (SuffixDescriptor suffix : array)
+      {
+        if (!Utils.areDnsEqual(suffix.getDN(),
+            ADSContext.getAdministrationSuffixDN()))
+        {
+          orderedSuffixes.add(suffix);
+        }
+      }
       hmCheckBoxes.clear();
       for (SuffixDescriptor suffix : orderedSuffixes)
       {
@@ -257,7 +269,11 @@
             getMsg("suffixes-to-replicate-dn-tooltip"),
             UIFactory.TextStyle.SECONDARY_FIELD_VALID);
         cb.setOpaque(false);
-        cb.setSelected(chosen.contains(suffix));
+        Boolean v = hmOldValues.get(suffix.getId());
+        if (v != null)
+        {
+          cb.setSelected(v);
+        }
         cb.addActionListener(new ActionListener()
         {
           public void actionPerformed(ActionEvent ev)
@@ -268,15 +284,16 @@
             }
           }
         });
-        hmCheckBoxes.put(suffix, cb);
+        hmCheckBoxes.put(suffix.getId(), cb);
       }
       populateCheckBoxPanel();
-      boolean display = orderedSuffixes.size() > 0;
-
-      noSuffixLabel.setVisible(!display);
-      labelGlue.setVisible(!display);
-      scroll.setVisible(display);
     }
+    boolean display = orderedSuffixes.size() > 0;
+
+    noSuffixLabel.setVisible(!display);
+    labelGlue.setVisible(!display);
+    scroll.setVisible(display);
+
     checkEnablingState();
   }
 
@@ -371,7 +388,7 @@
         gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
       }
       gbc.gridwidth = GridBagConstraints.RELATIVE;
-      JCheckBox cb = hmCheckBoxes.get(suffix);
+      JCheckBox cb = hmCheckBoxes.get(suffix.getId());
       cb.setVerticalAlignment(SwingConstants.TOP);
       checkBoxPanel.add(cb, gbc);
       gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
@@ -419,7 +436,7 @@
 
     ServerDescriptor server = replica.getServer();
 
-    String serverDisplay = getServerDisplay(server);
+    String serverDisplay = server.getHostPort(true);
 
     int nEntries = replica.getEntries();
 
@@ -428,24 +445,23 @@
       String[] args = {serverDisplay, String.valueOf(nEntries)};
       display = getMsg("suffix-list-replica-display-entries", args);
     }
-    else
+    else if (nEntries == 0)
     {
       String[] arg = {serverDisplay};
       display = getMsg("suffix-list-replica-display-no-entries", arg);
     }
+    else
+    {
+      String[] arg = {serverDisplay};
+      display = getMsg("suffix-list-replica-display-entries-not-available",
+          arg);
+    }
 
     return display;
   }
 
-
-  //TODO: only handles server that have ADSProperties.
-  private String getServerDisplay(ServerDescriptor server)
-  {
-    return server.getHostPort(true);
-  }
-
   private TreeSet<SuffixDescriptor> orderSuffixes(
-  Set<SuffixDescriptor> suffixes)
+      Set<SuffixDescriptor> suffixes)
   {
     TreeSet<SuffixDescriptor> ordered = new TreeSet<SuffixDescriptor>(this);
     ordered.addAll(suffixes);
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
index a6b6264..8dc716a 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/webstart/WebStartInstaller.java
@@ -139,8 +139,6 @@
       configureServer();
       createData();
 
-      updateADS();
-
       if (Utils.isWindows())
       {
           notifyListeners(getTaskSeparator());
@@ -148,29 +146,64 @@
           enableWindowsService();
       }
 
-      if (getUserData().getStartServer())
+      if (mustStart())
       {
         notifyListeners(getTaskSeparator());
         setStatus(InstallProgressStep.STARTING_SERVER);
         new ServerController(this).startServer();
       }
 
+      if (mustConfigureReplication())
+      {
+        setStatus(InstallProgressStep.CONFIGURING_REPLICATION);
+        notifyListeners(getTaskSeparator());
+
+        configureReplication();
+      }
+
+      if (mustInitializeSuffixes())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+        initializeSuffixes();
+      }
+
+      if (mustCreateAds())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.CONFIGURING_ADS);
+        updateADS();
+      }
+
+      if (mustStop())
+      {
+        notifyListeners(getTaskSeparator());
+        setStatus(InstallProgressStep.STOPPING_SERVER);
+        new ServerController(this).stopServer();
+      }
+
       setStatus(InstallProgressStep.FINISHED_SUCCESSFULLY);
       notifyListeners(null);
 
     } catch (ApplicationException ex)
     {
+      notifyListeners(getLineBreak());
+      notifyListenersOfLog();
       setStatus(InstallProgressStep.FINISHED_WITH_ERROR);
       String html = getFormattedError(ex, true);
       notifyListeners(html);
+      LOG.log(Level.SEVERE, "Error installing.", ex);
     }
     catch (Throwable t)
     {
+      notifyListeners(getLineBreak());
+      notifyListenersOfLog();
       setStatus(InstallProgressStep.FINISHED_WITH_ERROR);
       ApplicationException ex = new ApplicationException(
           ApplicationException.Type.BUG, getThrowableMsg("bug-msg", t), t);
       String msg = getFormattedError(ex, true);
       notifyListeners(msg);
+      LOG.log(Level.SEVERE, "Error installing.", t);
     }
     System.setErr(origErr);
     System.setOut(origOut);
@@ -219,10 +252,13 @@
     hmTime.put(InstallProgressStep.CONFIGURING_SERVER, 5);
     hmTime.put(InstallProgressStep.CREATING_BASE_ENTRY, 10);
     hmTime.put(InstallProgressStep.IMPORTING_LDIF, 20);
-    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED,
-        20);
+    hmTime.put(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED, 20);
+    hmTime.put(InstallProgressStep.CONFIGURING_REPLICATION, 10);
     hmTime.put(InstallProgressStep.ENABLING_WINDOWS_SERVICE, 5);
     hmTime.put(InstallProgressStep.STARTING_SERVER, 10);
+    hmTime.put(InstallProgressStep.STOPPING_SERVER, 5);
+    hmTime.put(InstallProgressStep.CONFIGURING_ADS, 5);
+    hmTime.put(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES, 25);
 
     int totalTime = 0;
     ArrayList<InstallProgressStep> steps =
@@ -234,33 +270,62 @@
     totalTime += hmTime.get(InstallProgressStep.CONFIGURING_SERVER);
     steps.add(InstallProgressStep.CONFIGURING_SERVER);
 
-    switch (getUserData().getNewSuffixOptions().getType())
+    if (createNotReplicatedSuffix())
     {
-    case CREATE_BASE_ENTRY:
-      steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
-      totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
-      break;
-    case IMPORT_FROM_LDIF_FILE:
-      steps.add(InstallProgressStep.IMPORTING_LDIF);
-      totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
-      break;
-    case IMPORT_AUTOMATICALLY_GENERATED_DATA:
-      steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
-      totalTime +=hmTime.get(
-              InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
-      break;
+      switch (getUserData().getNewSuffixOptions().getType())
+      {
+      case CREATE_BASE_ENTRY:
+        steps.add(InstallProgressStep.CREATING_BASE_ENTRY);
+        totalTime += hmTime.get(InstallProgressStep.CREATING_BASE_ENTRY);
+        break;
+      case IMPORT_FROM_LDIF_FILE:
+        steps.add(InstallProgressStep.IMPORTING_LDIF);
+        totalTime += hmTime.get(InstallProgressStep.IMPORTING_LDIF);
+        break;
+      case IMPORT_AUTOMATICALLY_GENERATED_DATA:
+        steps.add(InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+        totalTime +=hmTime.get(
+            InstallProgressStep.IMPORTING_AUTOMATICALLY_GENERATED);
+        break;
+      }
     }
+
     if (Utils.isWindows())
     {
         totalTime += hmTime.get(InstallProgressStep.ENABLING_WINDOWS_SERVICE);
         steps.add(InstallProgressStep.ENABLING_WINDOWS_SERVICE);
     }
-    if (getUserData().getStartServer())
+    if (mustStart())
     {
       totalTime += hmTime.get(InstallProgressStep.STARTING_SERVER);
       steps.add(InstallProgressStep.STARTING_SERVER);
     }
 
+    if (mustConfigureReplication())
+    {
+      steps.add(InstallProgressStep.CONFIGURING_REPLICATION);
+      totalTime += hmTime.get(InstallProgressStep.CONFIGURING_REPLICATION);
+    }
+
+    if (mustInitializeSuffixes())
+    {
+      totalTime += hmTime.get(
+          InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+      steps.add(InstallProgressStep.INITIALIZE_REPLICATED_SUFFIXES);
+    }
+
+    if (mustCreateAds())
+    {
+      totalTime += hmTime.get(InstallProgressStep.CONFIGURING_ADS);
+      steps.add(InstallProgressStep.CONFIGURING_ADS);
+    }
+
+    if (mustStop())
+    {
+      totalTime += hmTime.get(InstallProgressStep.STOPPING_SERVER);
+      steps.add(InstallProgressStep.STOPPING_SERVER);
+    }
+
     int cumulatedTime = 0;
     for (InstallProgressStep s : steps)
     {
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
index 7091a63..38bb0fb 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/resources/Resources.properties
@@ -242,19 +242,19 @@
 sure you want to close the Uninstall Window?
 confirm-cancel-upgrade-title=Confirmation Required
 confirm-cancel-upgrade-msg=OpenDS QuickUpgrade has not yet completed.\nIf you \
-  click 'Yes' any changes that have been\nmade to the server being upgraded \
-  will\nbe backed out.\n\nAre you sure you want to close the QuickUpgrade Window?\n
+  click 'Yes' any changes that have been made to the server being upgraded \
+  will be backed out.\n\nAre you sure you want to close the QuickUpgrade Window?\n
 confirm-quit-upgrade-title=Confirmation Required
 confirm-quit-upgrade-msg=Are you sure you want to quit OpenDS \
 QuickUpgrade?\nIf you click 'Yes' nothing will be upgraded on your system.
 confirm-uninstall-server-not-running-msg=Confirm Uninstall\n\
-All selected files will be permanently deleted, are you sure you\n\
+All selected files will be permanently deleted, are you sure you \
 want to continue?
 confirm-uninstall-server-not-running-title=Confirm Uninstall
 confirm-uninstall-server-running-msg=Server is Running\n\
-The OpenDS server is currently running and must be stopped before\n\
-uninstallation can continue. Do you want the uninstaller to stop\n\
-the server for you and continue with the uninstall? If you click\n\
+The OpenDS server is currently running and must be stopped before \
+uninstallation can continue. Do you want the uninstaller to stop \
+the server for you and continue with the uninstall? If you click \
 No, you will need to stop the server manually to continue.
 confirm-uninstall-server-running-title=Server is Running
 confirm-cancel-title=Confirmation Required
@@ -311,7 +311,7 @@
 # Data validation errors
 #
 # Server Settings
-empty-server-location=Invalid Directory Selected\nYou must provide a valid \
+empty-server-location=Invalid Directory Selected You must provide a valid \
   OpenDS root installation directory.
 parent-directory-could-not-be-found=Could not find a parent directory for {0}.
 parent-directory-does-not-exist-confirmation=The parent directory of {0} does \
@@ -322,6 +322,7 @@
 You must have file right access on the Installation directory.
 not-enough-disk-space=There is not enough free disk space under {0}.\nAt \
 least {1} megabytes of free disk space are required to install OpenDS.
+empty-host-name=You must provide the name of the host.
 invalid-port-value-range=The LDAP Listener Port must be an integer between \
 {0} and {1}.
 invalid-secure-port-value-range=The LDAPS Listener Port must be an \
@@ -340,17 +341,46 @@
 not-equal-pwd=The passwords you have provided do not match.
 pwd-too-short=The minimum length required for the Administrative User \
 password is {0} characters.
+
+#
 # Data Replication Panel
+#
+invalid-replication-port-value-range=The Replication Port must be an integer \
+between {0} and {1}.
+invalid-remote-replication-port-value-range=The Replication Port on {0} must \
+be an integer between {1} and {2}.
+equal-ports=You must specify different ports LDAP and LDAPS communication.
+replication-port-already-chosen-for-other-protocol=You must specify a \
+different Replication port than those you chose for LDAP and LDAPS \
+communication.
+remote-replication-port-already-chosen-for-other-protocol=You must specify a \
+different Replication port for existing server {0}.  The specified port has \
+already been chosen to configure the new server.
 empty-remote-host=You must provide the fully qualified name of the host.
 invalid-remote-port=The provided port is not valid.
 empty-remote-dn=You must provide a value for the Administrative User.
 empty-remote-pwd=You must provide an Admin User password.
+not-global-administrator-provided=You must provide the Global Administrator ID \
+to be able to access the configuration of all the remote servers that have \
+been previously installed.
+server-error=Error on {0}:
+error-reading-server-configuration=Error reading configuration.  Details:\n{0}
+error-reading-registered-servers-confirm=The following errors where \
+encountered reading the configuration of the existing servers:\n{0}\n\nDo you \
+want to continue?
+certificate-exception=You must accept the certificate presented by {0}:{1}.
+cannot-connect-to-remote-authentication=The provided credentials are not valid.
 cannot-connect-to-remote-permissions=You do not have enough access rights \
 to read the configuration in {0}. \nProvide credentials with enough rights.
-cannot-connect-to-remote-generic=Could not connect to {0}. \nCheck that the \
-server is running and that the provided credentials are valid.
-remote-ads-exception=An unexpected error occurred reading the \
-configuration in {0}.\nThe error is: {1}
+cannot-connect-to-remote-generic=Could not connect to {0}. The error message \
+received is:\n{1}\nCheck that the server is running and that the provided \
+credentials are valid.
+error-configuring-remote-generic=An unexpected error occurred configuring \
+server {0}.\nThe error is: {1}
+remote-ads-exception=An unexpected error occurred managing the \
+registration information in {0}.\nThe error is: {1}
+ads-exception=An unexpected error occurred managing the registration \
+information.\nThe error is: {0}
 no-suffixes-chosen-to-replicate=You must select at least one suffix to \
 replicate contents with.
 # Create Global Administrator Panel
@@ -391,6 +421,7 @@
 data-replication-step=Topology Options
 create-global-administrator-step=Global Administrator
 suffixes-step=Data Replication
+remote-replication-ports-step=Replication Port
 data-options-step=Directory Data
 review-step=Review
 progress-step=Progress
@@ -446,6 +477,7 @@
 opends-small-icon=images/opends_logo_small.png
 help-small-icon=images/help_small.gif
 wait-tiny=images/wait_tiny.png
+wait=images/wait.gif
 
 #
 # Colors: the meaning of colors is not universal.  That is why they are included
@@ -527,6 +559,8 @@
 where the server files will be stored
 server-location-relative-tooltip=Enter the relative path to the location \
 where the server files will be stored
+host-name-label=Host Name:
+host-name-tooltip=Enter the name of the host.
 server-port-label=LDAP Listener Port:
 server-port-tooltip=Enter the port number that the server will use to listen \
 for LDAP requests
@@ -563,6 +597,9 @@
 data-replication-options-panel-title=Topology Options
 data-replication-options-panel-instructions=Choose the Data \
 Replication Options.
+replication-port-label=Replication Port:
+replication-port-tooltip=The port that will be used to send and receive \
+replication updates between this server and the other servers.
 remote-server-dn-label=Admin User:
 remote-server-dn-tooltip=The DN or the UID of an administrator in the OpenDS \
 you want to replicate data with.
@@ -575,6 +612,9 @@
 remote-server-port-label=Port:
 remote-server-port-tooltip=The LDAP port of the OpenDS you want to \
 replicate data with.
+remote-server-port-is-secure-label=Secure Port
+remote-server-port-is-secure-tooltip=Check this is the provided port is the \
+LDAPS port.
 standalone-server-label=This will be a standalone server
 standalone-server-tooltip=Check this if you do not want to replicate the \
 data on the server that you are creating with other servers.
@@ -586,6 +626,56 @@
 topology-exists-tooltip=Check this if you already created a server that you \
 want to replicate data with.
 
+
+#
+# The accept certificate dialog.
+#
+certificate-dialog-title=Certificate Not Trusted
+certificate-title=Certificate Not Trusted
+#
+# Double apostrophes required for this item.
+#
+certificate-not-trusted-text=The Certificate presented by the server {0}:{1} \
+could not be trusted.<br><br>Possible reasons for this error:\
+<br>&nbsp;&nbsp;&nbsp;&nbsp;-The Certificate Authority that issued the \
+certificate is not recognized.<br>&nbsp;&nbsp;&nbsp;&nbsp;-The server''s \
+certificate is incomplete due to a misconfiguration.\
+<br>&nbsp;&nbsp;&nbsp;&nbsp;-The server''s certificate has expired.<br>Before \
+accepting this certificate, you should examine the server''s certificate \
+carefully.<br><br>Are you willing to accept this certificate for the purpose \
+of identifying the server {0}:{1}?
+#
+# Double apostrophes required for this item.
+#
+certificate-name-mismatch-text=The Certificate presented by the server {0}:{1} \
+could not be trusted.<br><br>There is a name mismatch between the name of the \
+server ({0}) and the subject DN of the certificate.  This could be caused \
+because you are connected to a server pretending to be {0}:{1}.<br><br>\
+Before accepting this certificate, you should examine the server''s \
+certificate carefully.<br><br>Are you willing to accept this certificate for \
+the purpose of identifying the server {0}:{1}?
+certificate-show-details-text=<br><br><a href="">Show Certificate Details</a>
+certificate-hide-details-text=<br><br><a href="">Hide Certificate Details</a>
+certificate-dialog-ok-button-tooltip=Close this dialog and accept the \
+certificate.
+certificate-dialog-cancel-button-tooltip=Close this dialog and do not accept \
+the certificate.
+certificate-chain-label=Certificate Chain:
+certificate-chain-combo-tooltip=To view the details of a given certificate \
+select it.
+certificate-not-valid-yet={0} - Not valid yet
+certificate-expired={0} - Expired
+certificate-subject-label=Subject:
+certificate-issued-by-label=Issued By:
+certificate-valid-from-label=Valid From:
+certificate-expires-on-label=Expires On:
+certificate-type-label=Type:
+certificate-serial-number-label=Serial Number:
+certificate-signature-label=Signature:
+certificate-signature-algorithm-label=Signature Algorithm:
+certificate-version-label=Version:
+certificate-public-key-label=Public Key:
+
 #
 # Global Administrator specific labels
 #
@@ -603,6 +693,15 @@
 Global Administrator.
 
 #
+# Remote Replication Ports panel
+#
+remote-replication-port-instructions=You must provide the ports that will be \
+used to replicate data for the remote servers specified below.<br>The \
+specified ports must be free on the remote hosts and the user that is being \
+used to run the Directory Servers must have access rights to them.
+remote-replication-port-title=Replication Port of Remote Servers
+
+#
 # Suffixes to Replicate Panel specific labels
 #
 suffixes-to-replicate-panel-instructions=Choose whether to create suffixes \
@@ -618,6 +717,8 @@
 to replicate.
 suffix-list-replica-display-entries={0}  ({1} entries)
 suffix-list-replica-display-no-entries={0}  (no entries)
+suffix-list-replica-display-entries-not-available={0} (number of entries not \
+available)
 suffix-list-unknown-label=<unknown>
 suffix-list-empty=-No Suffixes Found-
 
@@ -641,9 +742,6 @@
 testing only)
 use-self-signed-tooltip=Create a new Self-Signed Certificate to encrypt \
 communication.
-self-signed-certificate-name-label=Host Name:
-self-signed-certificate-name-tooltip=The host name will be used to name the \
-certificate.
 use-existing-certificate-label=Use an Existing Certificate:
 use-existing-certificate-tooltip=Select this if you have already a certificate \
 you want the new server to use.
@@ -662,28 +760,26 @@
 ssl-access-label=SSL Access:
 starttls-access-label=StartTLS Access:
 certificate-label=Certificate:
-no-self-signed-cert-name-provided=You must provide the host name for the \
-Self-Signed Certificate.
 keystore-path-not-provided=You must provide the path of the key store.
 keystore-path-does-not-exist=The provided key store path does not exist.
 keystore-path-not-a-file=The provided key store path is not a file.
 keystore-pwd-empty=You must provide the password of the key store.
 error-accessing-jks-keystore=Could not access the JKS key store.  Check that \
-the contents of the file\ncorrespond to a valid JKS key store, that you have \
-access rights to it and\nthat the provided password is valid.
+the contents of the file correspond to a valid JKS key store, that you have \
+access rights to it and that the provided password is valid.
 error-accessing-pkcs11-keystore=Could not access the PKCS#11 key store.  Check \
-that is installed and that the\nprovided password is valid.
+that is installed and that the provided password is valid.
 error-accessing-pkcs12-keystore=Could not access the PKCS#12 key store.  Check \
-that the contents of the file\ncorrespond to a valid PKCS#12 key store, that \
-you have access rights to it and\nthat the provided password is valid.
+that the contents of the file correspond to a valid PKCS#12 key store, that \
+you have access rights to it and that the provided password is valid.
 pkcs11-keystore-does-not-exist=No certificates for the PCKS#11 key store could \
-be found.  Check that is\ninstalled, that you have access rights to it and \
+be found.  Check that is installed, that you have access rights to it and \
 that the key store contains certificates.
 pkcs12-keystore-does-not-exist=No certificates for the PCKS#12 key store could \
-be found.  Check that the\nprovided path and password are valid and that the \
+be found.  Check that the provided path and password are valid and that the \
 key store contains certificates.
 jks-keystore-does-not-exist=No certificates for the Java Key Store could be \
-found.  Check that the provided\npath is valid.
+found.  Check that the provided path is valid.
 
 #
 # Select Alias dialog specific labels
@@ -739,6 +835,9 @@
 start-server-label=Start Server when Configuration has Completed
 start-server-tooltip=Check this check box if you want to start the server once \
 the installation and configuration has completed
+remote-server-replication-port={0} - To be configured on remote server {1}
+install-server-must-be-temporarily-started=The Server will be temporarily \
+started.
 
 #
 # Progress Panel specific labels
@@ -813,8 +912,12 @@
 summary-importing-ldif=Importing LDIF File...
 summary-importing-automatically-generated=Importing Automatically-Generated \
 Data...
+summary-configuring-replication=Configuring Replication...
 summary-starting=Starting Directory Server...
 summary-enabling-windows-service=Enabling Windows Service...
+summary-configuring-ads=Creating Registration Configuration...
+summary-initialize-replicated-suffixes=Initializing Contents of Replicated \
+Suffixes...
 summary-install-finished-successfully=<b>OpenDS QuickSetup Completed \
 Successfully.</b><br>OpenDS is now installed in {0}.<br><br>Visit the \
 <a href="https://www.opends.org/wiki/page/QuickReferenceGuide"> \
@@ -915,6 +1018,9 @@
 upgrading-ratio=Downloading: {0}% Completed - Upgrading file: {1} % Completed.
 progress-creating-base-entry=Creating Base Entry {0}
 progress-importing-ldif=Importing LDIF file {0}:
+progress-configuring-replication=Configuring Replication
+
+progress-configuring-replication-remote=Configuring Replication on {0}
 progress-import-automatically-generated=Importing Automatically-Generated Data \
 ({0} Entries):
 progress-starting=Starting Directory Server:
@@ -933,6 +1039,16 @@
 progress-server-waiting-to-stop=Waiting for Server to stop...
 progress-server-stopped=Server stopped.
 file-does-not-exist=Path {0} does not exist.
+progress-creating-administrator=Creating Global Administrator
+administrator-already-registered=Administrator already registered.
+progress-creating-ads=Creating Registration Configuration
+progress-creating-ads-on-remote=Creating Registration Configuration on {0}
+progress-initializing-ads=Initializing Registration information
+progress-initializing-suffix=Initializing suffix {0} with the contents from \
+{1}:
+suffix-initialized-successfully=Suffix initialized successfully.
+global-administrator-description=The Administrator that can manage all the \
+OpenDS instances.
 
 #
 # Progress errors
@@ -960,7 +1076,7 @@
 error-creating-base-entry=Error Creating Base Entry.
 error-importing-ldif=Error Importing LDIF File.
 error-import-automatically-generated=Error Importing Automatically- Generated \
-Data when invoked with arguments: {0}".
+Data when invoked with arguments: {0}.
 error-starting-server-with-no-connection-handlers=Error Starting Server with \
 no connection handlers: {0}.
 error-starting-server=Error Starting Directory Server.
@@ -982,6 +1098,21 @@
 using it.
 error-copying-file=Error copying file {0} to {1}.
 info-ignoring-file=Ignoring {0} since {1} exists.
+error-connecting-to-local=An unexpected error occurred connecting to the server.
+error-launching-initialization=Error launching initialization with contents \
+from server {0}.
+initialize-progress-with-percentage={0} entries processed ({1} % complete).
+no-entries-to-initialize=No entries found to initialize.
+initialize-progress-with-processed= {0} entries processed.
+initialize-progress-with-unprocessed={0} remaining to be processed.
+error-during-initialization-no-log=Error during the initialization with \
+contents from server {0}.  Check the error logs of {0} for more information.
+error-during-initialization-log=Error during the initialization with \
+contents from server {0}.  Last log details: {1}.  Check the error logs of the \
+server for more information.
+error-pooling-initialization=Error reading the progress of the initialization \
+with contents from server {0}.
+
 
 # Upgrade errors
 error-failed-to-create-stage-directory=Failed to create staging directory {0}.
@@ -1171,7 +1302,9 @@
 
 general-loading=Loading...
 general-see-for-details=See {0} for a detailed log of this operation.
+not-available-label=<not available>
 general-build-id=Build ID
 general-unset=Unset
 general-none=None
 general-unspecified=Unspecified
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CertificateDialog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CertificateDialog.java
new file mode 100644
index 0000000..6475f9e
--- /dev/null
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/CertificateDialog.java
@@ -0,0 +1,655 @@
+/*
+ * 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
+ *
+ *
+ *      Portions Copyright 2007 Sun Microsystems, Inc.
+ */
+
+package org.opends.quicksetup.ui;
+
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.GridBagConstraints;
+import java.awt.GridBagLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.security.cert.X509Certificate;
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.naming.ldap.LdapName;
+import javax.naming.ldap.Rdn;
+import javax.swing.Box;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JComponent;
+import javax.swing.JDialog;
+import javax.swing.JEditorPane;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+import javax.swing.border.EmptyBorder;
+import javax.swing.event.HyperlinkEvent;
+import javax.swing.event.HyperlinkListener;
+
+import org.opends.quicksetup.UserDataCertificateException;
+import org.opends.quicksetup.event.MinimumSizeComponentListener;
+import org.opends.quicksetup.i18n.ResourceProvider;
+import org.opends.quicksetup.util.Utils;
+
+/**
+ * This class is used to present the user a certificate to the user in order
+ * it to be accepted.
+ */
+public class CertificateDialog extends JDialog implements HyperlinkListener
+{
+  private static final long serialVersionUID = -8989965057591475064L;
+  private boolean isAccepted;
+  private UserDataCertificateException ce;
+  private JButton cancelButton;
+  private JButton okButton;
+  private JComponent certificateDetails;
+  private JEditorPane explanationPane;
+  private boolean detailsAlreadyClicked;
+  private String explanationWithHideDetails;
+  private String explanationWithShowDetails;
+
+  private static final Logger LOG = Logger.getLogger(
+      CertificateDialog.class.getName());
+
+  /**
+   * Constructor of the certificate dialog.
+   * @param parent the parent frame for this dialog.
+   * @param ce the UserDataCertificateException we use to get the informations
+   * about the certificate that was presented and the reason why it was
+   * rejected.
+   */
+  public CertificateDialog(JFrame parent, UserDataCertificateException ce)
+  {
+    super(parent);
+    this.ce = ce;
+    setTitle(getMsg("certificate-dialog-title"));
+    getContentPane().add(createPanel());
+    setModal(true);
+    pack();
+    if (getPreferredSize().width > parent.getWidth())
+    {
+      setPreferredSize(new Dimension(parent.getWidth() - 20,
+          getPreferredSize().height));
+    }
+    pack();
+    int minWidth = (int) getPreferredSize().getWidth();
+    int minHeight = (int) getPreferredSize().getHeight();
+    addComponentListener(new MinimumSizeComponentListener(this, minWidth,
+        minHeight));
+    getRootPane().setDefaultButton(cancelButton);
+
+    addWindowListener(new WindowAdapter()
+    {
+      public void windowClosing(WindowEvent e)
+      {
+        cancelClicked();
+      }
+    });
+    setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
+
+    Utils.centerOnComponent(this, parent);
+  }
+
+  /**
+   * Wheter the user accepted the certificate or not.
+   * @return <CODE>true</CODE> ir the user accepted the certificate and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isAccepted()
+  {
+    return isAccepted;
+  }
+
+  /**
+   * Implements HyperlinkListener.  When the user clicks on a link we assume
+   * that is the show details/hide details and we update the visible components
+   * accordingly.
+   *
+   * @param e the HyperlinkEvent.
+   */
+  public void hyperlinkUpdate(HyperlinkEvent e)
+  {
+    if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED)
+    {
+      boolean detailsVisible = !certificateDetails.isVisible();
+      explanationPane.setText(detailsVisible?
+          explanationWithHideDetails:explanationWithShowDetails);
+      certificateDetails.setVisible(detailsVisible);
+      if (detailsVisible && !detailsAlreadyClicked)
+      {
+        detailsAlreadyClicked = true;
+        pack();
+      }
+    }
+  }
+
+  /* The following three methods are just commodity methods to retrieve
+   * localized messages */
+  private String getMsg(String key)
+  {
+    return getI18n().getMsg(key);
+  }
+
+  private String getMsg(String key, String... args)
+  {
+    return getI18n().getMsg(key, args);
+  }
+
+  private ResourceProvider getI18n()
+  {
+    return ResourceProvider.getInstance();
+  }
+
+  /**
+   * Creates and returns the panel of the dialog.
+   * @return the panel of the dialog.
+   */
+  private JPanel createPanel()
+  {
+    GridBagConstraints gbc = new GridBagConstraints();
+
+    JPanel contentPanel = new JPanel(new GridBagLayout());
+    contentPanel.setBackground(UIFactory.DEFAULT_BACKGROUND);
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.weightx = 1.0;
+
+    JPanel topPanel = new JPanel(new GridBagLayout());
+    topPanel.setBorder(UIFactory.DIALOG_PANEL_BORDER);
+    topPanel.setBackground(UIFactory.CURRENT_STEP_PANEL_BACKGROUND);
+
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getCurrentStepPanelInsets();
+    topPanel.add(createTitlePanel(), gbc);
+    gbc.insets.top = UIFactory.TOP_INSET_INSTRUCTIONS_SUBPANEL;
+    topPanel.add(createTextPane(), gbc);
+    certificateDetails = createCertificateDetailsPane();
+    gbc.insets.top = 0;
+    gbc.insets.bottom = 0;
+    topPanel.add(Box.createHorizontalStrut(
+        certificateDetails.getPreferredSize().width), gbc);
+    gbc.insets.top = 0;
+    gbc.insets.bottom = UIFactory.TOP_INSET_INPUT_SUBPANEL;
+    gbc.weighty = 1.0;
+    topPanel.add(certificateDetails, gbc);
+    certificateDetails.setVisible(false);
+    gbc.weighty = 0.2;
+    gbc.insets = UIFactory.getEmptyInsets();
+    topPanel.add(Box.createVerticalGlue(), gbc);
+    contentPanel.add(topPanel, gbc);
+    gbc.weighty = 0.0;
+    gbc.insets = UIFactory.getButtonsPanelInsets();
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    contentPanel.add(createButtonsPanel(), gbc);
+
+    return contentPanel;
+  }
+
+  /**
+   * Creates and returns the title sub panel.
+   * @return the title sub panel.
+   */
+  private Component createTitlePanel()
+  {
+    JPanel titlePanel = new JPanel(new GridBagLayout());
+    GridBagConstraints gbc = new GridBagConstraints();
+    titlePanel.setOpaque(false);
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.weightx = 0.0;
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+
+    String title = getMsg("certificate-title");
+    JLabel l =
+        UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, title,
+            UIFactory.TextStyle.TITLE);
+    l.setOpaque(false);
+    titlePanel.add(l, gbc);
+
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = 0;
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    titlePanel.add(Box.createHorizontalGlue(), gbc);
+
+    return titlePanel;
+  }
+
+  /**
+   * Creates and returns the text sub panel.
+   * @return the text sub panel.
+   */
+  private Component createTextPane()
+  {
+    String text;
+    if (ce.getType() == UserDataCertificateException.Type.NOT_TRUSTED)
+    {
+      text = getMsg("certificate-not-trusted-text", ce.getHost(),
+          String.valueOf(ce.getPort()));
+    }
+    else
+    {
+      text = getMsg("certificate-name-mismatch-text",
+          ce.getHost(), String.valueOf(ce.getPort()));
+    }
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.anchor = GridBagConstraints.NORTHWEST;
+    p.add(UIFactory.makeJLabel(UIFactory.IconType.WARNING_LARGE, null,
+        UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 1.0;
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.fill = GridBagConstraints.BOTH;
+    gbc.insets.left = UIFactory.LEFT_INSET_PRIMARY_FIELD;
+    gbc.insets.bottom = 0;
+    explanationPane = UIFactory.makeHtmlPane(null, UIFactory.INSTRUCTIONS_FONT);
+    explanationPane.setOpaque(false);
+    explanationPane.setEditable(false);
+    explanationPane.addHyperlinkListener(this);
+    p.add(explanationPane, gbc);
+    if ((ce.getChain() != null) && (ce.getChain().length > 0))
+    {
+      explanationWithShowDetails = UIFactory.applyFontToHtml(text +
+          getMsg("certificate-show-details-text"), UIFactory.INSTRUCTIONS_FONT);
+      explanationWithHideDetails = UIFactory.applyFontToHtml(text +
+          getMsg("certificate-hide-details-text"), UIFactory.INSTRUCTIONS_FONT);
+
+      explanationPane.setText(explanationWithShowDetails);
+    }
+    else
+    {
+      explanationPane.setText(text);
+    }
+    return p;
+  }
+
+  /**
+   * Creates and returns the buttons OK/CANCEL sub panel.
+   * @return the buttons OK/CANCEL sub panel.
+   */
+  private Component createButtonsPanel()
+  {
+    JPanel buttonsPanel = new JPanel(new GridBagLayout());
+    buttonsPanel.setOpaque(false);
+    GridBagConstraints gbc = new GridBagConstraints();
+    gbc.fill = GridBagConstraints.HORIZONTAL;
+    gbc.gridwidth = 4;
+    gbc.insets = UIFactory.getEmptyInsets();
+    gbc.insets.left = UIFactory.getCurrentStepPanelInsets().left;
+    buttonsPanel.add(UIFactory.makeJLabel(UIFactory.IconType.OPENDS_SMALL,
+        null, UIFactory.TextStyle.NO_STYLE), gbc);
+    gbc.weightx = 1.0;
+    gbc.gridwidth--;
+    gbc.insets.left = 0;
+    buttonsPanel.add(Box.createHorizontalGlue(), gbc);
+    gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.fill = GridBagConstraints.NONE;
+    gbc.weightx = 0.0;
+    okButton =
+      UIFactory.makeJButton(getMsg("ok-button-label"),
+          getMsg("certificate-dialog-ok-button-tooltip"));
+    buttonsPanel.add(okButton, gbc);
+    okButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        okClicked();
+      }
+    });
+
+    gbc.gridwidth = GridBagConstraints.REMAINDER;
+    gbc.insets.left = UIFactory.HORIZONTAL_INSET_BETWEEN_BUTTONS;
+    cancelButton =
+      UIFactory.makeJButton(getMsg("cancel-button-label"),
+          getMsg("certificate-dialog-cancel-button-tooltip"));
+    buttonsPanel.add(cancelButton, gbc);
+    cancelButton.addActionListener(new ActionListener()
+    {
+      public void actionPerformed(ActionEvent ev)
+      {
+        cancelClicked();
+      }
+    });
+
+    return buttonsPanel;
+  }
+
+  /**
+   * Creates the panel containing a representation of the certificate chain.
+   * @return the panel containing a representation of the certificate chain.
+   */
+  private JComponent createCertificateDetailsPane()
+  {
+    JPanel p = new JPanel(new GridBagLayout());
+    p.setOpaque(false);
+    if ((ce.getChain() != null) && (ce.getChain().length > 0))
+    {
+      final JComboBox combo = new JComboBox();
+      combo.setToolTipText(getMsg("certificate-chain-combo-tooltip"));
+      final CardLayout cl = new CardLayout();
+      final JPanel cardPanel = new JPanel(cl);
+      final Map<String, JPanel> hmPanels = new HashMap<String, JPanel>();
+
+      String[] labels =
+      {
+          getMsg("certificate-subject-label"),
+          getMsg("certificate-issued-by-label"),
+          getMsg("certificate-valid-from-label"),
+          getMsg("certificate-expires-on-label"),
+          getMsg("certificate-type-label"),
+          getMsg("certificate-serial-number-label"),
+          getMsg("certificate-signature-label"),
+          getMsg("certificate-signature-algorithm-label"),
+          getMsg("certificate-version-label"),
+          getMsg("certificate-public-key-label")
+      };
+
+      for (int i=0; i<ce.getChain().length; i++)
+      {
+        X509Certificate cert = ce.getChain()[i];
+        JComponent[] components =
+        {
+            createSubjectComponent(cert),
+            createIssuedByComponent(cert),
+            createValidFromComponent(cert),
+            createExpiresOnComponent(cert),
+            createTypeComponent(cert),
+            createSerialNumberComponent(cert),
+            createSignatureComponent(cert),
+            createSignatureAlgorithmComponent(cert),
+            createVersionComponent(cert),
+            createPublicKeyComponent(cert)
+        };
+        JPanel certPanel = new JPanel(new GridBagLayout());
+        GridBagConstraints gbc = new GridBagConstraints();
+        gbc.anchor = GridBagConstraints.NORTHWEST;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+
+        for (int j=0; j<labels.length; j++)
+        {
+          JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+              labels[j], UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+
+          l.setLabelFor(components[j]);
+          if (j > 0)
+          {
+            gbc.insets.top = UIFactory.TOP_INSET_SECONDARY_FIELD;
+          }
+          gbc.gridwidth = GridBagConstraints.RELATIVE;
+          gbc.weightx = 0.0;
+          gbc.insets.left = 0;
+          certPanel.add(l, gbc);
+          gbc.gridwidth = GridBagConstraints.REMAINDER;
+          gbc.weightx = 1.0;
+          gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+          certPanel.add(components[j], gbc);
+        }
+        String name = getName(cert);
+        hmPanels.put(name, certPanel);
+        cardPanel.add(name, certPanel);
+        combo.addItem(name);
+      }
+      GridBagConstraints gbc = new GridBagConstraints();
+      if (ce.getChain().length == 1)
+      {
+        gbc.gridwidth = GridBagConstraints.REMAINDER;
+        gbc.weightx = 1.0;
+        gbc.fill = GridBagConstraints.BOTH;
+        p.add(cardPanel, gbc);
+
+        gbc.weighty = 1.0;
+        p.add(Box.createVerticalGlue(), gbc);
+      }
+      else
+      {
+        gbc.anchor = GridBagConstraints.WEST;
+        gbc.gridwidth = 3;
+        gbc.fill = GridBagConstraints.HORIZONTAL;
+        JPanel auxPanel = new JPanel(new GridBagLayout());
+        JLabel l = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON,
+            getMsg("certificate-chain-label"),
+            UIFactory.TextStyle.PRIMARY_FIELD_VALID);
+        auxPanel.add(l, gbc);
+        gbc.gridwidth = GridBagConstraints.RELATIVE;
+        gbc.insets.left = UIFactory.LEFT_INSET_SECONDARY_FIELD;
+        auxPanel.add(combo, gbc);
+        l.setLabelFor(combo);
+        gbc.gridwidth = GridBagConstraints.REMAINDER;
+        gbc.insets.left = 0;
+        gbc.weightx = 1.0;
+        auxPanel.add(Box.createHorizontalGlue(), gbc);
+
+        p.add(auxPanel, gbc);
+
+        gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
+        gbc.fill = GridBagConstraints.BOTH;
+        p.add(cardPanel, gbc);
+
+        gbc.weighty = 1.0;
+        p.add(Box.createVerticalGlue(), gbc);
+      }
+
+      combo.addActionListener(new ActionListener()
+      {
+        public void actionPerformed(ActionEvent ev)
+        {
+          String selectedItem = (String)combo.getSelectedItem();
+          cl.show(hmPanels.get(selectedItem), selectedItem);
+        }
+      });
+    }
+    JScrollPane scroll = new JScrollPane(p);
+    scroll.setViewportBorder(new EmptyBorder(0, 0, 0, 0));
+    scroll.setOpaque(false);
+    scroll.getViewport().setOpaque(false);
+    scroll.setPreferredSize(new Dimension(scroll.getPreferredSize().width,
+        175));
+    return scroll;
+  }
+
+  private JComponent createSubjectComponent(X509Certificate cert)
+  {
+    String dn = cert.getSubjectX500Principal().getName();
+    return makeValueLabel(dn);
+  }
+
+  private JComponent createIssuedByComponent(X509Certificate cert)
+  {
+    String dn = cert.getIssuerX500Principal().getName();
+    return makeValueLabel(dn);
+  }
+
+  private JComponent createValidFromComponent(X509Certificate cert)
+  {
+    JComponent c;
+
+    Date date = cert.getNotBefore();
+    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+    DateFormat.SHORT);
+    String value = df.format(date);
+    boolean isNotValidYet = false;
+    long t1 = System.currentTimeMillis();
+    long t2 = date.getTime();
+    isNotValidYet = t1 < t2;
+
+    if (isNotValidYet)
+    {
+      c = UIFactory.makeJLabel(UIFactory.IconType.ERROR,
+          getMsg("certificate-not-valid-yet", value),
+          UIFactory.TextStyle.SECONDARY_FIELD_INVALID);
+    }
+    else
+    {
+      c = makeValueLabel(value);
+    }
+    return c;
+  }
+
+  private JComponent createExpiresOnComponent(X509Certificate cert)
+  {
+    JComponent c;
+
+    Date date = cert.getNotAfter();
+    DateFormat df = DateFormat.getDateTimeInstance(DateFormat.SHORT,
+    DateFormat.SHORT);
+    String value = df.format(date);
+    boolean isExpired = false;
+    long t1 = System.currentTimeMillis();
+    long t2 = date.getTime();
+    isExpired = t1 > t2;
+
+    if (isExpired)
+    {
+      c = UIFactory.makeJLabel(UIFactory.IconType.ERROR,
+          getMsg("certificate-expired", value),
+          UIFactory.TextStyle.SECONDARY_FIELD_INVALID);
+    }
+    else
+    {
+      c = makeValueLabel(value);
+    }
+    return c;
+  }
+
+  private JComponent createTypeComponent(X509Certificate cert)
+  {
+    String type = cert.getType();
+    return makeValueLabel(type);
+  }
+
+  private JComponent createSerialNumberComponent(X509Certificate cert)
+  {
+    String serialNumber = String.valueOf(cert.getSerialNumber());
+    return makeValueLabel(serialNumber);
+  }
+
+  private JComponent createSignatureComponent(X509Certificate cert)
+  {
+    String signature = String.valueOf(cert.getSignature());
+    return makeValueLabel(signature);
+  }
+
+  private JComponent createSignatureAlgorithmComponent(X509Certificate cert)
+  {
+    String signature = String.valueOf(cert.getSigAlgName());
+    return makeValueLabel(signature);
+  }
+
+  private JComponent createVersionComponent(X509Certificate cert)
+  {
+    String version = String.valueOf(cert.getVersion());
+    return makeValueLabel(version);
+  }
+
+  private JComponent createPublicKeyComponent(X509Certificate cert)
+  {
+    return UIFactory.makeTextPane(cert.getPublicKey().toString(),
+        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+  }
+
+  private JLabel makeValueLabel(String value)
+  {
+    if (value == null)
+    {
+      value = getMsg("not-available-label");
+    }
+    return UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, value,
+        UIFactory.TextStyle.SECONDARY_FIELD_VALID);
+  }
+
+  private String getName(X509Certificate cert)
+  {
+    String name = cert.getSubjectX500Principal().getName();
+    try
+    {
+      LdapName dn = new LdapName(name);
+      Rdn rdn = dn.getRdn(0);
+      name = rdn.getValue().toString();
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.WARNING, "Error parsing subject dn: "+
+          cert.getSubjectX500Principal(), t);
+    }
+    return name;
+  }
+
+  /**
+   * Method called when user clicks on ok.
+   *
+   */
+  private void okClicked()
+  {
+    isAccepted = true;
+    dispose();
+  }
+
+  /**
+   * Method called when user clicks on cancel.
+   *
+   */
+  private void cancelClicked()
+  {
+    isAccepted = false;
+    dispose();
+  }
+
+  /**
+   * Method written for testing purposes.
+   * @param args the arguments to be passed to the test program.
+   */
+  /*
+  public static void main(String[] args)
+  {
+    try
+    {
+      // TODO
+    } catch (Exception ex)
+    {
+      ex.printStackTrace();
+    }
+  }
+  */
+}
+
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FieldName.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FieldName.java
index 5415ca7..72bb85f 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FieldName.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FieldName.java
@@ -48,6 +48,10 @@
   /**
    * The value associated with this is a String.
    */
+  HOST_NAME,
+  /**
+   * The value associated with this is a String.
+   */
   SERVER_PORT,
   /**
    * The value associated with this is a String.
@@ -96,6 +100,10 @@
   /**
    * The value associated with this is a String.
    */
+  REPLICATION_PORT,
+  /**
+   * The value associated with this is a String.
+   */
   REMOTE_SERVER_DN,
   /**
    * The value associated with this is a String.
@@ -110,6 +118,11 @@
    */
   REMOTE_SERVER_PORT,
   /**
+   * Whether the Remote Server Port is a secure port or not.  The value
+   * associated with this is a Boolean.
+   */
+  REMOTE_SERVER_IS_SECURE_PORT,
+  /**
    * The value associated with this is a String.
    */
   GLOBAL_ADMINISTRATOR_UID,
@@ -122,6 +135,11 @@
    */
   GLOBAL_ADMINISTRATOR_PWD_CONFIRM,
   /**
+   * The value associated with this is a Map where the key is a ServerDescriptor
+   * and the value an Integer.
+   */
+  REMOTE_REPLICATION_PORT,
+  /**
    * The value associated with this is a Boolean.
    */
   SERVER_START,
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
index e006439..93a2cb4 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/FramePanel.java
@@ -35,8 +35,8 @@
 import java.awt.GridBagConstraints;
 import java.awt.GridBagLayout;
 
-import javax.swing.Box;
 import javax.swing.Icon;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 
 /**
@@ -64,6 +64,8 @@
 
   private int stepsPanelHorizontalInsets;
 
+  private JLabel progressLabel;
+
   /**
    * The constructor of the FramePanel.
    * @param stepsPanel the steps panel that on the top-left side of the
@@ -108,10 +110,17 @@
     gbc.insets = UIFactory.getEmptyInsets();
     add(currentPanelContainer, gbc);
 
+    progressLabel = UIFactory.makeJLabel(UIFactory.IconType.NO_ICON, null,
+        UIFactory.TextStyle.READ_ONLY);
+    gbc.weighty = 0.0;
+    gbc.insets.left = UIFactory.getStepsPanelInsets().left;
+    gbc.insets.bottom = UIFactory.getButtonsPanelInsets().bottom;
+    add(progressLabel, gbc);
     gbc.gridwidth = GridBagConstraints.RELATIVE;
+    gbc.anchor = GridBagConstraints.WEST;
     gbc.weightx = 0.0;
     gbc.weighty = 0.0;
-    add(Box.createHorizontalGlue(), gbc);
+    add(progressLabel, gbc);
 
     gbc.gridwidth = GridBagConstraints.REMAINDER;
     gbc.weightx = 1.0;
@@ -142,6 +151,19 @@
   }
 
   /**
+   * This method sets up an icon on the bottom left side of the dialog.
+   * Generally this method is called with an animated gif that is passed to
+   * display progress.
+   * @param iconType the icon type to be set.
+   */
+  public void setProgressIcon(UIFactory.IconType iconType)
+  {
+    // For the moment we are lacking of a decent progress dialog to be
+    // displayed.
+    //progressLabel.setIcon(UIFactory.getImageIcon(iconType));
+  }
+
+  /**
    * {@inheritDoc}
    *
    * This method has been overwritten to be able to have a transparency effect
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
index 3a69f96..440b5be 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/GuiApplication.java
@@ -38,6 +38,7 @@
 import java.awt.event.WindowEvent;
 import java.io.IOException;
 import java.io.File;
+import java.security.cert.X509Certificate;
 import java.util.LinkedHashSet;
 import java.util.Set;
 import java.util.logging.Level;
@@ -389,6 +390,43 @@
   }
 
   /**
+   * Updates the list of certificates accepted by the user in the trust manager
+   * based on the information stored in the UserDataCertificateException we got
+   * when trying to connect in secure mode.
+   * @param ce the UserDataCertificateException that contains the information to
+   * be used.
+   */
+  protected void acceptCertificateForException(UserDataCertificateException ce)
+  {
+    X509Certificate[] chain = ce.getChain();
+    String authType = ce.getAuthType();
+    String host = ce.getHost();
+
+    if ((chain != null) && (authType != null) && (host != null))
+    {
+      getTrustManager().acceptCertificate(chain, authType, host);
+    }
+    else
+    {
+      if (chain == null)
+      {
+        LOG.log(Level.WARNING,
+            "The chain is null for the UserDataCertificateException");
+      }
+      if (authType == null)
+      {
+        LOG.log(Level.WARNING,
+            "The auth type is null for the UserDataCertificateException");
+      }
+      if (host == null)
+      {
+        LOG.log(Level.WARNING,
+            "The host is null for the UserDataCertificateException");
+      }
+    }
+  }
+
+  /**
    * Begins downloading webstart jars in another thread
    * for WebStart applications only.
    */
@@ -511,8 +549,10 @@
   protected void notifyListenersOfLog() {
     File logFile = QuickSetupLog.getLogFile();
     if (logFile != null) {
-      notifyListeners(getMsg("general-see-for-details", logFile.getPath()) +
-                  formatter.getLineBreak());
+      notifyListeners(
+          getFormattedProgress(getMsg("general-see-for-details",
+              logFile.getPath())) +
+          formatter.getLineBreak());
     }
   }
 
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java
index 94e94b4..50276d2 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetup.java
@@ -248,7 +248,9 @@
   {
     final WizardStep cStep = getCurrentStep();
     application.nextClicked(cStep, this);
-    updateUserData(cStep);
+    BackgroundTask worker = new NextClickedBackgroundTask(cStep);
+    getDialog().workerStarted();
+    worker.startBackgroundTask();
   }
 
   private void updateUserData(final WizardStep cStep) {
@@ -278,7 +280,14 @@
             if (displayConfirmation(ude.getLocalizedMessage(),
                 getMsg("confirmation-title")))
             {
+              try
+              {
               setCurrentStep(application.getNextWizardStep(cStep));
+              }
+              catch (Throwable t)
+              {
+                t.printStackTrace();
+              }
             }
           }
           else
@@ -553,6 +562,29 @@
   }
 
   /**
+   * Displays a dialog asking the user to accept a certificate.
+   *
+   * @param ce
+   *          the certificate exception that occurred.
+   * @param title
+   *          the title of the dialog.
+   * @return <CODE>true</CODE> if the user confirms the message, or
+   * <CODE>false</CODE> if not.
+   */
+  private boolean askToAcceptCertificate(UserDataCertificateException ce)
+  {
+    boolean accept = false;
+    CertificateDialog dlg = new CertificateDialog(getDialog().getFrame(), ce);
+    dlg.pack();
+    dlg.setVisible(true);
+    if (dlg.isAccepted())
+    {
+      accept = true;
+    }
+    return accept;
+  }
+
+  /**
    * Gets the string value for a given field name.
    *
    * @param fieldName
@@ -650,4 +682,78 @@
   {
     return Utils.isWebStart();
   }
+
+  /**
+   * This is a class used when the user clicks on next and that extends
+   * BackgroundTask.
+   */
+  private class NextClickedBackgroundTask extends BackgroundTask
+  {
+    private WizardStep cStep;
+    public NextClickedBackgroundTask(WizardStep cStep)
+    {
+      this.cStep = cStep;
+    }
+
+    public Object processBackgroundTask() throws UserDataException {
+      try {
+        application.updateUserData(cStep, QuickSetup.this);
+      }
+      catch (UserDataException uide) {
+        throw uide;
+      }
+      catch (Throwable t) {
+        throw new UserDataException(cStep,
+                getThrowableMsg("bug-msg", t));
+      }
+      return null;
+    }
+
+    public void backgroundTaskCompleted(Object returnValue,
+                                        Throwable throwable) {
+      getDialog().workerFinished();
+
+      if (throwable != null)
+      {
+        if (!(throwable instanceof UserDataException))
+        {
+          LOG.log(Level.WARNING, "Unhandled exception.", throwable);
+        }
+        else
+        {
+          UserDataException ude = (UserDataException) throwable;
+          if (ude instanceof UserDataConfirmationException)
+          {
+            if (displayConfirmation(ude.getLocalizedMessage(),
+                getMsg("confirmation-title")))
+            {
+              setCurrentStep(application.getNextWizardStep(cStep));
+            }
+          }
+          else if (ude instanceof UserDataCertificateException)
+          {
+            final UserDataCertificateException ce =
+              (UserDataCertificateException)ude;
+            if (askToAcceptCertificate(ce))
+            {
+              /*
+               * Retry the click but now with the certificate accepted.
+               */
+              application.acceptCertificateForException(ce);
+              application.nextClicked(cStep, QuickSetup.this);
+              BackgroundTask worker = new NextClickedBackgroundTask(cStep);
+              getDialog().workerStarted();
+              worker.startBackgroundTask();
+            }
+          }
+          else
+          {
+            displayError(ude.getLocalizedMessage(), getMsg("error-title"));
+          }
+        }
+      } else {
+        setCurrentStep(application.getNextWizardStep(cStep));
+      }
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
index 6f40872..77cd309 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/QuickSetupDialog.java
@@ -302,7 +302,7 @@
     {
       public void run()
       {
-        // TODO: here we could have an animated gif.
+        displayWorkingProgressImage(true);
         setButtonEnabled(ButtonName.NEXT, false);
         setButtonEnabled(ButtonName.PREVIOUS, false);
         setButtonEnabled(ButtonName.FINISH, false);
@@ -325,7 +325,7 @@
     {
       public void run()
       {
-        // TO COMPLETE: here we could have an animated gif.
+        displayWorkingProgressImage(false);
         setButtonEnabled(ButtonName.NEXT, true);
         setButtonEnabled(ButtonName.PREVIOUS, true);
         setButtonEnabled(ButtonName.FINISH, true);
@@ -543,4 +543,13 @@
       li.buttonActionPerformed(be);
     }
   }
+
+  private void displayWorkingProgressImage(boolean display)
+  {
+    if (getFramePanel() instanceof FramePanel)
+    {
+      ((FramePanel)getFramePanel()).setProgressIcon(display ?
+          UIFactory.IconType.WAIT : UIFactory.IconType.NO_ICON);
+    }
+  }
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
index 3482c67..ae414cc 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/ReviewPanel.java
@@ -68,7 +68,7 @@
 
     addVerticalGlue(panel);
 
-    JCheckBox chk = getCheckBox();
+    JComponent chk = getBottomComponent();
     if (chk != null) {
       gbc.insets.top = UIFactory.TOP_INSET_PRIMARY_FIELD;
       gbc.weighty = 0.0;
@@ -80,9 +80,11 @@
   }
 
   /**
-   * Returns the start server check box.
-   * If it does not exist creates the start server check box.
-   * @return the start server check box.
+   * Returns the component that will placed at the bottom of the panel.
+   * In the case of the installer and the uninstaller this is basically the
+   * start server check box.
+   * If it does not exist creates the component.
+   * @return the component that will placed at the bottom of the panel.
    */
-  protected abstract JCheckBox getCheckBox();
+  protected abstract JComponent getBottomComponent();
 }
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
index be5e00d..9152b8c 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/ui/UIFactory.java
@@ -1497,6 +1497,10 @@
       key = "wait-tiny";
       break;
 
+    case WAIT:
+      key = "wait";
+      break;
+
     default:
       throw new IllegalArgumentException("Unknown iconName: " + iconType);
     }
@@ -1577,6 +1581,10 @@
       description = getMsg("help-wait-description");
       break;
 
+    case WAIT:
+      description = getMsg("help-wait-description");
+      break;
+
     case NO_ICON:
       description = null;
       break;
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java
index 4b2077c..cfdc148 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/upgrader/ui/UpgraderReviewPanel.java
@@ -88,7 +88,7 @@
   public Object getFieldValue(FieldName fieldName) {
     Object value = null;
     if (fieldName == FieldName.SERVER_START) {
-      value = getCheckBox().isSelected();
+      value = getBottomComponent().isSelected();
     }
     return value;
   }
@@ -230,7 +230,7 @@
   /**
    * {@inheritDoc}
    */
-  protected JCheckBox getCheckBox()
+  protected JCheckBox getBottomComponent()
   {
     if (checkBox == null)
     {
diff --git a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index ab56bdf..fc78b0e 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -38,20 +38,22 @@
 import java.io.InputStream;
 import java.io.PrintWriter;
 import java.io.RandomAccessFile;
-import java.net.ConnectException;
+import java.security.GeneralSecurityException;
 import java.util.*;
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.naming.CommunicationException;
-import javax.naming.Context;
 import javax.naming.NamingException;
-import javax.naming.directory.SearchControls;
+import javax.naming.directory.SearchResult;
 import javax.naming.ldap.InitialLdapContext;
 import javax.naming.ldap.LdapName;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLHandshakeException;
+import javax.net.ssl.TrustManager;
 import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 
+import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.quicksetup.*;
 import org.opends.quicksetup.webstart.JnlpProperties;
 import org.opends.quicksetup.i18n.ResourceProvider;
@@ -67,8 +69,6 @@
   private static final Logger LOG =
           Logger.getLogger(Utils.class.getName());
 
-  private static final int DEFAULT_LDAP_CONNECT_TIMEOUT = 3000;
-
   private static final int BUFFER_SIZE = 1024;
 
   private static final int MAX_LINE_WIDTH = 80;
@@ -757,6 +757,20 @@
     return p.waitFor();
   }
 
+  /**
+   * Returns the String that can be used to represent a given host name in a
+   * LDAP URL.
+   * This method must be used when we have IPv6 addresses (the address in the
+   * LDAP URL must be enclosed with brackets).
+   * @param host the host name.
+   * @return the String that can be used to represent a given host name in a
+   * LDAP URL.
+   */
+  public static String getHostNameForLdapUrl(String host)
+  {
+    return ConnectionUtils.getHostNameForLdapUrl(host);
+  }
+
   // Very limited for the moment: apply only permissions to the current user and
   // does not work in non-English environments... to work in non English we
   // should use xcalcs but it does not come in the windows default install...
@@ -847,56 +861,83 @@
       String pwd, int timeout, Hashtable<String, String> env)
       throws NamingException
   {
-    if (env != null)
-    { // We clone 'env' so that we can modify it freely
-      env = new Hashtable<String, String>(env);
-    } else
-    {
-      env = new Hashtable<String, String>();
-    }
-    env
-        .put(Context.INITIAL_CONTEXT_FACTORY,
-            "com.sun.jndi.ldap.LdapCtxFactory");
-    env.put(Context.PROVIDER_URL, ldapURL);
-    if (timeout >= 1)
-    {
-      env.put("com.sun.jndi.ldap.connect.timeout", String.valueOf(timeout));
-    }
-    if (dn != null)
-    {
-      env.put(Context.SECURITY_PRINCIPAL, dn);
-    }
-    if (pwd != null)
-    {
-      env.put(Context.SECURITY_CREDENTIALS, pwd);
-    }
-
-    /* Contains the DirContext and the Exception if any */
-    final Object[] pair = new Object[]
-      { null, null };
-    final Hashtable fEnv = env;
-    Thread t = new Thread(new Runnable()
-    {
-      public void run()
-      {
-        try
-        {
-          pair[0] = new InitialLdapContext(fEnv, null);
-
-        } catch (NamingException ne)
-        {
-          pair[1] = ne;
-
-        } catch (Throwable t)
-        {
-          pair[1] = t;
-        }
-      }
-    });
-    return getInitialLdapContext(t, pair, timeout);
+    return ConnectionUtils.createLdapContext(ldapURL, dn, pwd, timeout, env);
   }
 
   /**
+   * Creates an LDAPS connection and returns the corresponding LdapContext.
+   * This method uses the TrusteSocketFactory class so that the specified
+   * trust manager gets called during the SSL handshake. If trust manager is
+   * null, certificates are not verified during SSL handshake.
+   *
+   * @param ldapsURL      the target *LDAPS* URL.
+   * @param dn            passed as Context.SECURITY_PRINCIPAL if not null.
+   * @param pwd           passed as Context.SECURITY_CREDENTIALS if not null.
+   * @param timeout       passed as com.sun.jndi.ldap.connect.timeout if > 0.
+   * @param env           null or additional environment properties.
+   * @param trustManager  null or the trust manager to be invoked during SSL
+   * negociation.
+   *
+   * @return the established connection with the given parameters.
+   *
+   * @throws NamingException the exception thrown when instantiating
+   * InitialLdapContext.
+   *
+   * @see javax.naming.Context
+   * @see javax.naming.ldap.InitialLdapContext
+   * @see TrustedSocketFactory
+   */
+  public static InitialLdapContext createLdapsContext(String ldapsURL,
+      String dn, String pwd, int timeout, Hashtable<String, String> env,
+      TrustManager trustManager) throws NamingException {
+    return ConnectionUtils.createLdapsContext(ldapsURL, dn, pwd, timeout, env,
+        trustManager);
+  }
+
+  /**
+   * Creates an LDAP+StartTLS connection and returns the corresponding
+   * LdapContext.
+   * This method first creates an LdapContext with anonymous bind. Then it
+   * requests a StartTlsRequest extended operation. The StartTlsResponse is
+   * setup with the specified hostname verifier. Negotiation is done using a
+   * TrustSocketFactory so that the specified TrustManager gets called during
+   * the SSL handshake.
+   * If trust manager is null, certificates are not checked during SSL
+   * handshake.
+   *
+   * @param ldapsURL      the target *LDAPS* URL.
+   * @param dn            passed as Context.SECURITY_PRINCIPAL if not null.
+   * @param pwd           passed as Context.SECURITY_CREDENTIALS if not null.
+   * @param timeout       passed as com.sun.jndi.ldap.connect.timeout if > 0.
+   * @param env           null or additional environment properties.
+   * @param trustManager  null or the trust manager to be invoked during SSL.
+   * negociation.
+   * @param verifier      null or the hostname verifier to be setup in the
+   * StartTlsResponse.
+   *
+   * @return the established connection with the given parameters.
+   *
+   * @throws NamingException the exception thrown when instantiating
+   * InitialLdapContext.
+   *
+   * @see javax.naming.Context
+   * @see javax.naming.ldap.InitialLdapContext
+   * @see javax.naming.ldap.StartTlsRequest
+   * @see javax.naming.ldap.StartTlsResponse
+   * @see TrustedSocketFactory
+   */
+
+  public static InitialLdapContext createStartTLSContext(String ldapsURL,
+      String dn, String pwd, int timeout, Hashtable<String, String> env,
+      TrustManager trustManager, HostnameVerifier verifier)
+  throws NamingException
+  {
+    return ConnectionUtils.createStartTLSContext(ldapsURL, dn, pwd, timeout,
+        env, trustManager, verifier);
+  }
+
+
+  /**
    * Method used to know if we can connect as administrator in a server with a
    * given password and dn.
    * @param ldapUrl the ldap URL of the server.
@@ -908,33 +949,40 @@
   public static boolean canConnectAsAdministrativeUser(String ldapUrl,
       String dn, String pwd)
   {
-    boolean canConnectAsAdministrativeUser = false;
-    try
-    {
-      InitialLdapContext ctx =
-        Utils.createLdapContext(ldapUrl, dn, pwd,
-            Utils.getDefaultLDAPTimeout(), null);
+    return ConnectionUtils.canConnectAsAdministrativeUser(ldapUrl, dn, pwd);
+  }
 
-      /*
-       * Search for the config to check that it is the directory manager.
-       */
-      SearchControls searchControls = new SearchControls();
-      searchControls.setCountLimit(1);
-      searchControls.setSearchScope(
-      SearchControls. OBJECT_SCOPE);
-      searchControls.setReturningAttributes(
-      new String[] {"dn"});
-      ctx.search("cn=config", "objectclass=*", searchControls);
+/**
+ * Tells whether the provided Throwable was caused because of a problem with
+ * a certificate while trying to establish a connection.
+ * @param t the Throwable to analyze.
+ * @return <CODE>true</CODE> if the provided Throwable was caused because of a
+ * problem with a certificate while trying to establish a connection and
+ * <CODE>false</CODE> otherwise.
+ */
+  public static boolean isCertificateException(Throwable t)
+  {
+    boolean returnValue = false;
 
-      canConnectAsAdministrativeUser = true;
-    } catch (NamingException ne)
+    while (!returnValue && (t != null))
     {
-      // Nothing to do.
-    } catch (Throwable t)
-    {
-      throw new IllegalStateException("Unexpected throwable.", t);
+      returnValue = (t instanceof SSLHandshakeException) ||
+      (t instanceof GeneralSecurityException);
+      t = t.getCause();
     }
-    return canConnectAsAdministrativeUser;
+
+    return returnValue;
+  }
+
+  /**
+   * Returns the default LDAP timeout in milliseconds when we try to connect to
+   * a server.
+   * @return the default LDAP timeout in milliseconds when we try to connect to
+   * a server.
+   */
+  public static int getDefaultLDAPTimeout()
+  {
+    return ConnectionUtils.getDefaultLDAPTimeout();
   }
 
   /**
@@ -999,7 +1047,7 @@
      String title)
  {
    return JOptionPane.YES_OPTION == JOptionPane.showOptionDialog(
-       parent, msg, title, JOptionPane.YES_NO_OPTION,
+       parent, wrapMsg(msg, 100), title, JOptionPane.YES_NO_OPTION,
        JOptionPane.QUESTION_MESSAGE, null, // don't use a custom
        // Icon
        null, // the titles of buttons
@@ -1018,7 +1066,7 @@
    */
   public static void displayError(Component parent, String msg, String title)
   {
-    JOptionPane.showMessageDialog(parent, msg, title,
+    JOptionPane.showMessageDialog(parent, wrapMsg(msg, 100), title,
         JOptionPane.ERROR_MESSAGE);
   }
 
@@ -1035,7 +1083,7 @@
   public static void displayInformationMessage(JFrame parent, String msg,
       String title)
   {
-    JOptionPane.showMessageDialog(parent, msg, title,
+    JOptionPane.showMessageDialog(parent, wrapMsg(msg, 100), title,
         JOptionPane.INFORMATION_MESSAGE);
   }
 
@@ -1087,95 +1135,6 @@
     return outsideLogs;
   }
 
-  /**
-   * This is just a commodity method used to try to get an InitialLdapContext.
-   * @param t the Thread to be used to create the InitialLdapContext.
-   * @param pair an Object[] array that contains the InitialLdapContext and the
-   * Throwable if any occurred.
-   * @param timeout the timeout.  If we do not get to create the connection
-   * before the timeout a CommunicationException will be thrown.
-   * @return the created InitialLdapContext
-   * @throws NamingException if something goes wrong during the creation.
-   */
-  private static InitialLdapContext getInitialLdapContext(Thread t,
-      Object[] pair, int timeout) throws NamingException
-  {
-    try
-    {
-      if (timeout > 0)
-      {
-        t.start();
-        t.join(timeout);
-      } else
-      {
-        t.run();
-      }
-
-    } catch (InterruptedException x)
-    {
-      // This might happen for problems in sockets
-      // so it does not necessarily imply a bug
-    }
-
-    boolean throwException = false;
-
-    if ((timeout > 0) && t.isAlive())
-    {
-      t.interrupt();
-      try
-      {
-        t.join(2000);
-      } catch (InterruptedException x)
-      {
-        // This might happen for problems in sockets
-        // so it does not necessarily imply a bug
-      }
-      throwException = true;
-    }
-
-    if ((pair[0] == null) && (pair[1] == null))
-    {
-      throwException = true;
-    }
-
-    if (throwException)
-    {
-      NamingException xx;
-      ConnectException x = new ConnectException("Connection timed out");
-      xx = new CommunicationException("Connection timed out");
-      xx.initCause(x);
-      throw xx;
-    }
-
-    if (pair[1] != null)
-    {
-      if (pair[1] instanceof NamingException)
-      {
-        throw (NamingException) pair[1];
-
-      } else if (pair[1] instanceof RuntimeException)
-      {
-        throw (RuntimeException) pair[1];
-
-      } else if (pair[1] instanceof Throwable)
-      {
-        throw new IllegalStateException("Unexpected throwable occurred",
-            (Throwable) pair[1]);
-      }
-    }
-    return (InitialLdapContext) pair[0];
-  }
-
-  /**
-   * Returns the default LDAP timeout in milliseconds when we try to connect to
-   * a server.
-   * @return the default LDAP timeout in milliseconds when we try to connect to
-   * a server.
-   */
-  public static int getDefaultLDAPTimeout()
-  {
-    return DEFAULT_LDAP_CONNECT_TIMEOUT;
-  }
 
   /**
 
@@ -1392,6 +1351,133 @@
   }
 
   /**
+   * Returns the String representation of the first value of an attribute in a
+   * LDAP entry.
+   * @param entry the entry.
+   * @param attrName the attribute name.
+   * @return the String representation of the first value of an attribute in a
+   * LDAP entry.
+   * @throws NamingException if there is an error processing the entry.
+   */
+  static public String getFirstValue(SearchResult entry, String attrName)
+  throws NamingException
+  {
+    return ConnectionUtils.getFirstValue(entry, attrName);
+  }
+
+  /**
+   * Private method used to wrap the messages that are displayed in dialogs
+   * of type JOptionPane.
+   * @param msg the message.
+   * @param width the maximum width of the column.
+   * @return the wrapped message.
+   */
+  private static String wrapMsg(String msg, int width)
+  {
+    StringBuilder   buffer        = new StringBuilder();
+    StringTokenizer lineTokenizer = new StringTokenizer(msg, "\n", true);
+    while (lineTokenizer.hasMoreTokens())
+    {
+      String line = lineTokenizer.nextToken();
+      if (line.equals("\n"))
+      {
+        // It's an end-of-line character, so append it as-is.
+        buffer.append(line);
+      }
+      else if (line.length() < width)
+      {
+        // The line fits in the specified width, so append it as-is.
+        buffer.append(line);
+      }
+      else
+      {
+        // The line doesn't fit in the specified width, so it needs to be
+        // wrapped.  Do so at space boundaries.
+        StringBuilder   lineBuffer    = new StringBuilder();
+        StringBuilder   delimBuffer   = new StringBuilder();
+        StringTokenizer wordTokenizer = new StringTokenizer(line, " ", true);
+        while (wordTokenizer.hasMoreTokens())
+        {
+          String word = wordTokenizer.nextToken();
+          if (word.equals(" "))
+          {
+            // It's a space, so add it to the delim buffer only if the line
+            // buffer is not empty.
+            if (lineBuffer.length() > 0)
+            {
+              delimBuffer.append(word);
+            }
+          }
+          else if (word.length() > width)
+          {
+            // This is a long word that can't be wrapped, so we'll just have to
+            // make do.
+            if (lineBuffer.length() > 0)
+            {
+              buffer.append(lineBuffer);
+              buffer.append("\n");
+              lineBuffer = new StringBuilder();
+            }
+            buffer.append(word);
+
+            if (wordTokenizer.hasMoreTokens())
+            {
+              // The next token must be a space, so remove it.  If there are
+              // still more tokens after that, then append an EOL.
+              wordTokenizer.nextToken();
+              if (wordTokenizer.hasMoreTokens())
+              {
+                buffer.append("\n");
+              }
+            }
+
+            if (delimBuffer.length() > 0)
+            {
+              delimBuffer = new StringBuilder();
+            }
+          }
+          else
+          {
+            // It's not a space, so see if we can fit it on the current line.
+            int newLineLength = lineBuffer.length() + delimBuffer.length() +
+            word.length();
+            if (newLineLength < width)
+            {
+              // It does fit on the line, so add it.
+              lineBuffer.append(delimBuffer).append(word);
+
+              if (delimBuffer.length() > 0)
+              {
+                delimBuffer = new StringBuilder();
+              }
+            }
+            else
+            {
+              // It doesn't fit on the line, so end the current line and start
+              // a new one.
+              buffer.append(lineBuffer);
+              buffer.append("\n");
+
+              lineBuffer = new StringBuilder();
+              lineBuffer.append(word);
+
+              if (delimBuffer.length() > 0)
+              {
+                delimBuffer = new StringBuilder();
+              }
+            }
+          }
+        }
+
+        // If there's anything left in the line buffer, then add it to the
+        // final buffer.
+        buffer.append(lineBuffer);
+      }
+    }
+    return buffer.toString();
+  }
+
+  /**
    * Inserts HTML break tags into <code>d</code> breaking it up
    * so that no line is longer than <code>maxll</code>.
    * @param d String to break
diff --git a/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java b/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java
index 22c9722..d7b366b 100644
--- a/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java
+++ b/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/ConfigFromLDAP.java
@@ -835,17 +835,7 @@
   private String getFirstValue(SearchResult entry, String attrName)
   throws NamingException
   {
-    String v = null;
-    Attributes attrs = entry.getAttributes();
-    if (attrs != null)
-    {
-      Attribute attr = attrs.get(attrName);
-      if ((attr != null) && (attr.size() > 0))
-      {
-        v = (String)attr.get();
-      }
-    }
-    return v;
+    return Utils.getFirstValue(entry, attrName);
   }
 
   private Set<String> getValues(SearchResult entry, String attrName)
diff --git a/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties b/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties
index ccdd7b6..0588ec8 100644
--- a/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties
+++ b/opendj-sdk/opends/src/statuspanel/org/opends/statuspanel/resources/Resources.properties
@@ -49,7 +49,6 @@
 quit-status-panel-button-tooltip=Quit Status Panel
 server-status-title=Server Status
 server-status-label=Server Run Status:
-not-available-label=<not available>
 not-available-server-down-tooltip=<html>Information is only available if \
 server is running and you are authenticated<br>as an administrative user.
 not-available-authentication-required-tooltip=<html>Information is only \

--
Gitblit v1.10.0