From 59b4905a66a5db370e6d0de5f7cb6dcd314ef443 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Sun, 26 Aug 2007 03:16:07 +0000
Subject: [PATCH] This commit includes all the code for the first version of the replication tools.  As they require further testing the command line associated with them has not been committed.

---
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java       |   63 
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java            | 3780 +++++++++++++++++++++++++++++++
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java          | 1462 ++++++++++++
 opends/src/ads/org/opends/admin/ads/ServerDescriptor.java                                 |  101 
 opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java                      |  109 
 opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java                |   15 
 opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java                     |  105 
 opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java       |    2 
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java           |   98 
 opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java       |   20 
 opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java                        |    2 
 opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java        |    2 
 opends/src/ads/org/opends/admin/ads/TopologyCacheException.java                           |   13 
 opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java |  203 +
 opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java    |  117 
 opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java     |  325 ++
 opends/src/guitools/org/opends/guitools/replicationcli/package-info.java                  |   40 
 opends/src/ads/org/opends/admin/ads/TopologyCache.java                                    |   29 
 opends/src/ads/org/opends/admin/ads/ADSContext.java                                       |   14 
 opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java                             |  233 +
 opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java               |   53 
 opends/src/quicksetup/org/opends/quicksetup/util/Utils.java                               |   17 
 opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java      |  188 +
 opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java                      |   15 
 opends/src/messages/messages/admin_tool.properties                                        |  149 +
 opends/src/quicksetup/org/opends/quicksetup/Application.java                              |    4 
 26 files changed, 6,933 insertions(+), 226 deletions(-)

diff --git a/opends/src/ads/org/opends/admin/ads/ADSContext.java b/opends/src/ads/org/opends/admin/ads/ADSContext.java
index 629dbad..8c21966 100644
--- a/opends/src/ads/org/opends/admin/ads/ADSContext.java
+++ b/opends/src/ads/org/opends/admin/ads/ADSContext.java
@@ -338,7 +338,7 @@
   }
 
   private static HashMap<String, AdministratorProperty>
-    nameToAdminUSerProperty = null;
+    nameToAdminUserProperty = null;
 
   /**
    * Get a AdministratorProperty associated to a name.
@@ -347,17 +347,17 @@
    * @return The corresponding AdministratorProperty or null if name
    * doesn't match with an existing property.
    */
-  public static AdministratorProperty getAdminUSerPropFromName(String name)
+  public static AdministratorProperty getAdminUserPropFromName(String name)
   {
-    if (nameToAdminUSerProperty == null)
+    if (nameToAdminUserProperty == null)
     {
-      nameToAdminUSerProperty = new HashMap<String, AdministratorProperty>();
+      nameToAdminUserProperty = new HashMap<String, AdministratorProperty>();
       for (AdministratorProperty u : AdministratorProperty.values())
       {
-        nameToAdminUSerProperty.put(u.getAttributeName(), u);
+        nameToAdminUserProperty.put(u.getAttributeName(), u);
       }
     }
-    return nameToAdminUSerProperty.get(name);
+    return nameToAdminUserProperty.get(name);
   }
 
   // The context used to retrieve information
@@ -898,6 +898,8 @@
    * So this should not be called by the Java Web Start before being sure that
    * this jar is loaded.
    * @param backendName the backend name which will handle admin information.
+   * <CODE>null</CODE> to use the default backend name for the admin
+   * information.
    * @throws ADSContextException if something goes wrong.
    */
   public void createAdminData(String backendName) throws ADSContextException
diff --git a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index 2034463..49d63ee 100644
--- a/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -27,17 +27,14 @@
 
 package org.opends.admin.ads;
 
-import java.net.URI;
-import java.net.URISyntaxException;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.naming.Context;
 import javax.naming.NameNotFoundException;
 import javax.naming.NamingEnumeration;
 import javax.naming.NamingException;
@@ -181,6 +178,69 @@
   }
 
   /**
+   * Tells whether this server is a replication server or not.
+   * @return <CODE>true</CODE> if the server is a replication server and
+   * <CODE>false</CODE> otherwise.
+   */
+  public boolean isReplicationServer()
+  {
+    return Boolean.TRUE.equals(
+        serverProperties.get(ServerProperty.IS_REPLICATION_SERVER));
+  }
+
+  /**
+   * Returns the String representation of this replication server based
+   * on the information we have ("hostname":"replication port") and
+   * <CODE>null</CODE> if this is not a replication server.
+   * @return the String representation of this replication server based
+   * on the information we have ("hostname":"replication port") and
+   * <CODE>null</CODE> if this is not a replication server.
+   */
+  public String getReplicationServerHostPort()
+  {
+    String hostPort = null;
+    if (isReplicationServer())
+    {
+      hostPort = getHostName().toLowerCase()+ ":" + getReplicationServerPort();
+    }
+    return hostPort;
+  }
+
+  /**
+   * Returns the replication server ID of this server and -1 if this is not a
+   * replications server.
+   * @return the replication server ID of this server and -1 if this is not a
+   * replications server.
+   */
+  public int getReplicationServerId()
+  {
+    int port = -1;
+    if (isReplicationServer())
+    {
+      port = (Integer)serverProperties.get(
+          ServerProperty.REPLICATION_SERVER_ID);
+    }
+    return port;
+  }
+
+  /**
+   * Returns the replication port of this server and -1 if this is not a
+   * replications server.
+   * @return the replication port of this server and -1 if this is not a
+   * replications server.
+   */
+  public int getReplicationServerPort()
+  {
+    int port = -1;
+    if (isReplicationServer())
+    {
+      port = (Integer)serverProperties.get(
+          ServerProperty.REPLICATION_SERVER_PORT);
+    }
+    return port;
+  }
+
+  /**
    * Sets the ADS properties of the server.
    * @param adsProperties a Map containing the ADS properties of the server.
    */
@@ -405,6 +465,7 @@
         adsProperties.put(adsProps[i][1], String.valueOf(port));
       }
     }
+    adsProperties.put(ADSContext.ServerProperty.ID, getHostPort(true));
   }
 
   /**
@@ -442,17 +503,9 @@
     updateReplicas(desc, ctx);
     updateReplication(desc, ctx);
 
-    String s = (String)ctx.getEnvironment().get(Context.PROVIDER_URL);
-    try
-    {
-      URI ldapURL = new URI(s);
-      desc.serverProperties.put(ServerProperty.HOST_NAME, ldapURL.getHost());
-    }
-    catch (URISyntaxException use)
-    {
-      // This is really strange.  Seems like a bug somewhere.
-      LOG.log(Level.WARNING, "Error parsing ldap URL "+s, use);
-    }
+    desc.serverProperties.put(ServerProperty.HOST_NAME,
+        ConnectionUtils.getHostName(ctx));
+
     return desc;
   }
 
@@ -683,7 +736,14 @@
             if (areDnsEqual(replica.getSuffix().getDN(), dn))
             {
               replica.setReplicationId(id);
-              replica.setReplicationServers(replicationServers);
+              // Keep the values of the replication servers in lower case
+              // to make use of Sets as String simpler.
+              LinkedHashSet<String> repServers = new LinkedHashSet<String>();
+              for (String s: replicationServers)
+              {
+                repServers.add(s.toLowerCase());
+              }
+              replica.setReplicationServers(repServers);
             }
           }
         }
@@ -724,8 +784,15 @@
         desc.serverProperties.put(ServerProperty.REPLICATION_SERVER_ID,
             Integer.parseInt(v));
         Set<String> values = getValues(sr, "ds-cfg-replication-server");
+        // Keep the values of the replication servers in lower case
+        // to make use of Sets as String simpler.
+        LinkedHashSet<String> repServers = new LinkedHashSet<String>();
+        for (String s: values)
+        {
+          repServers.add(s.toLowerCase());
+        }
         desc.serverProperties.put(ServerProperty.EXTERNAL_REPLICATION_SERVERS,
-            values);
+            repServers);
       }
     }
     catch (NameNotFoundException nse)
diff --git a/opends/src/ads/org/opends/admin/ads/TopologyCache.java b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
index 666f59a..4b0cff2 100644
--- a/opends/src/ads/org/opends/admin/ads/TopologyCache.java
+++ b/opends/src/ads/org/opends/admin/ads/TopologyCache.java
@@ -36,12 +36,11 @@
 import java.util.logging.Level;
 import java.util.logging.Logger;
 
-import javax.naming.Context;
-import javax.naming.NamingException;
 import javax.naming.ldap.LdapName;
 
 import org.opends.admin.ads.ADSContext.ServerProperty;
 import org.opends.admin.ads.util.ApplicationTrustManager;
+import org.opends.admin.ads.util.ConnectionUtils;
 import org.opends.admin.ads.util.ServerLoader;
 
 /**
@@ -72,27 +71,14 @@
    * @param trustManager the ApplicationTrustManager that must be used to trust
    * certificates when we create connections to the registered servers to read
    * their configuration.
-   * @throws TopologyCacheException if an error occurred reading the
-   * authentication data in the DirContext associated with the provided
-   * ADSContext.
    */
   public TopologyCache(ADSContext adsContext,
       ApplicationTrustManager trustManager)
-  throws TopologyCacheException
   {
     this.adsContext = adsContext;
     this.trustManager = trustManager;
-    try
-    {
-      dn = (String)adsContext.getDirContext().getEnvironment().get(
-          Context.SECURITY_PRINCIPAL);
-      pwd = (String)adsContext.getDirContext().getEnvironment().get(
-          Context.SECURITY_CREDENTIALS);
-    }
-    catch (NamingException ne)
-    {
-      throw new TopologyCacheException(TopologyCacheException.Type.BUG, ne);
-    }
+    dn = ConnectionUtils.getBindDN(adsContext.getDirContext());
+    pwd = ConnectionUtils.getBindPassword(adsContext.getDirContext());
   }
 
   /**
@@ -256,4 +242,13 @@
     return new ServerLoader(serverProperties, dn, pwd,
         trustManager.createCopy());
   }
+
+  /**
+   * Returns the adsContext used by this TopologyCache.
+   * @return the adsContext used by this TopologyCache.
+   */
+  public ADSContext getAdsContext()
+  {
+    return adsContext;
+  }
 }
diff --git a/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java b/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java
index 759bd9d..3fa64dd 100644
--- a/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java
+++ b/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java
@@ -141,6 +141,19 @@
   }
 
   /**
+   * Returns the host port representation of the server we where connected to
+   * (or trying to connect) when this exception was generated.
+   * @return the host port representation of the server we where connected to
+   * (or trying to connect) when this exception was generated.
+   */
+  public String getHostPort()
+  {
+    int index = ldapUrl.indexOf("//");
+    String hostPort = ldapUrl.substring(index + 2);
+    return hostPort;
+  }
+
+  /**
    * Returns the ApplicationTrustManager that we were using when this exception
    * was generated.
    * @return the ApplicationTrustManager that we were using when this exception
diff --git a/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java b/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
index 0d117c0..57dd0e7 100644
--- a/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
+++ b/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
@@ -29,10 +29,13 @@
 
 import java.io.IOException;
 import java.net.ConnectException;
+import java.net.URI;
 import java.security.GeneralSecurityException;
 import java.util.HashSet;
 import java.util.Hashtable;
 import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import javax.naming.CommunicationException;
 import javax.naming.Context;
@@ -58,6 +61,12 @@
 {
   private static final int DEFAULT_LDAP_CONNECT_TIMEOUT = 10000;
 
+  private static final String STARTTLS_PROPERTY =
+    "org.opends.connectionutils.isstarttls";
+
+  static private final Logger LOG =
+    Logger.getLogger(ConnectionUtils.class.getName());
+
   /**
    * Private constructor: this class cannot be instantiated.
    */
@@ -313,8 +322,10 @@
             throw xx;
           }
 
+          result.addToEnvironment(STARTTLS_PROPERTY, "true");
           if (fDn != null)
           {
+
             result.addToEnvironment(Context.SECURITY_AUTHENTICATION , "simple");
             result.addToEnvironment(Context.SECURITY_PRINCIPAL, fDn);
             if (fPwd != null)
@@ -338,6 +349,168 @@
     return getInitialLdapContext(t, pair, timeout);
   }
 
+  /**
+   * Returns the LDAP URL used in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return the LDAP URL used in the provided InitialLdapContext.
+   */
+  public static String getLdapUrl(InitialLdapContext ctx)
+  {
+    String s = null;
+    try
+    {
+      s = (String)ctx.getEnvironment().get(Context.PROVIDER_URL);
+    }
+    catch (NamingException ne)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Naming exception getting environment of "+ctx,
+          ne);
+    }
+    return s;
+  }
+
+  /**
+   * Returns the host name used in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return the host name used in the provided InitialLdapContext.
+   */
+  public static String getHostName(InitialLdapContext ctx)
+  {
+    String s = null;
+    try
+    {
+      URI ldapURL = new URI(getLdapUrl(ctx));
+      s = ldapURL.getHost();
+    }
+    catch (Throwable t)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Error getting host: "+t, t);
+    }
+    return s;
+  }
+
+  /**
+   * Returns the port number used in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return the port number used in the provided InitialLdapContext.
+   */
+  public static int getPort(InitialLdapContext ctx)
+  {
+    int port = -1;
+    try
+    {
+      URI ldapURL = new URI(getLdapUrl(ctx));
+      port = ldapURL.getPort();
+    }
+    catch (Throwable t)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Error getting port: "+t, t);
+    }
+    return port;
+  }
+
+  /**
+   * Returns the host port representation of the server to which this
+   * context is connected.
+   * @param ctx the context to analyze.
+   * @return the host port representation of the server to which this
+   * context is connected.
+   */
+  public static String getHostPort(InitialLdapContext ctx)
+  {
+    return getHostName(ctx)+":"+getPort(ctx);
+  }
+
+  /**
+   * Returns the bind DN used in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return the bind DN used in the provided InitialLdapContext.
+   */
+  public static String getBindDN(InitialLdapContext ctx)
+  {
+    String bindDN = null;
+    try
+    {
+      bindDN = (String)ctx.getEnvironment().get(Context.SECURITY_PRINCIPAL);
+    }
+    catch (NamingException ne)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Naming exception getting environment of "+ctx,
+          ne);
+    }
+    return bindDN;
+  }
+
+  /**
+   * Returns the password used in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return the password used in the provided InitialLdapContext.
+   */
+  public static String getBindPassword(InitialLdapContext ctx)
+  {
+    String bindPwd = null;
+    try
+    {
+      bindPwd = (String)ctx.getEnvironment().get(Context.SECURITY_CREDENTIALS);
+    }
+    catch (NamingException ne)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Naming exception getting environment of "+ctx,
+          ne);
+    }
+    return bindPwd;
+  }
+
+  /**
+   * Tells whether we are using SSL in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return <CODE>true</CODE> if we are using SSL and <CODE>false</CODE>
+   * otherwise.
+   */
+  public static boolean isSSL(InitialLdapContext ctx)
+  {
+    boolean isSSL = false;
+    String s = null;
+    try
+    {
+      s = getLdapUrl(ctx);
+      isSSL = s.toLowerCase().startsWith("ldaps");
+    }
+    catch (Throwable t)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Error getting if is SSL "+t, t);
+    }
+    return isSSL;
+  }
+
+  /**
+   * Tells whether we are using StartTLS in the provided InitialLdapContext.
+   * @param ctx the context to analyze.
+   * @return <CODE>true</CODE> if we are using StartTLS and <CODE>false</CODE>
+   * otherwise.
+   */
+  public static boolean isStartTLS(InitialLdapContext ctx)
+  {
+    boolean isStartTLS = false;
+    try
+    {
+      isStartTLS = "true".equalsIgnoreCase((String)ctx.getEnvironment().get(
+            STARTTLS_PROPERTY));
+    }
+    catch (NamingException ne)
+    {
+      // This is really strange.  Seems like a bug somewhere.
+      LOG.log(Level.WARNING, "Naming exception getting environment of "+ctx,
+          ne);
+    }
+    return isStartTLS;
+  }
 
   /**
    * Method used to know if we can connect as administrator in a server with a
@@ -354,21 +527,19 @@
     boolean canConnectAsAdministrativeUser = false;
     try
     {
-      InitialLdapContext ctx =
-        createLdapContext(ldapUrl, dn, pwd, getDefaultLDAPTimeout(), null);
+      InitialLdapContext ctx;
+      if (ldapUrl.toLowerCase().startsWith("ldap:"))
+      {
+        ctx = createLdapContext(ldapUrl, dn, pwd, getDefaultLDAPTimeout(),
+            null);
+      }
+      else
+      {
+        ctx = createLdapsContext(ldapUrl, dn, pwd, getDefaultLDAPTimeout(),
+            null, null, null);
+      }
 
-      /*
-       * 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);
-
-      canConnectAsAdministrativeUser = true;
+      canConnectAsAdministrativeUser = connectedAsAdministrativeUser(ctx);
     } catch (NamingException ne)
     {
       // Nothing to do.
@@ -380,6 +551,40 @@
   }
 
   /**
+   * Method used to know if we are connected as administrator in a server with a
+   * given InitialLdapContext.
+   * @param ctx the context.
+   * @return <CODE>true</CODE> if we are connected and read the configuration
+   * and <CODE>false</CODE> otherwise.
+   */
+  public static boolean connectedAsAdministrativeUser(InitialLdapContext ctx)
+  {
+    boolean connectedAsAdministrativeUser = false;
+    try
+    {
+      /*
+       * 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);
+
+      connectedAsAdministrativeUser = true;
+    } catch (NamingException ne)
+    {
+      // Nothing to do.
+    } catch (Throwable t)
+    {
+      throw new IllegalStateException("Unexpected throwable.", t);
+    }
+    return connectedAsAdministrativeUser;
+  }
+
+  /**
    * 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
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java b/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java
new file mode 100644
index 0000000..99219ea
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java
@@ -0,0 +1,117 @@
+/*
+ * 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.guitools.replicationcli;
+
+/**
+ * This class is used to store the information provided by the user to
+ * disable replication.  It is required because when we are in interactive
+ * mode the ReplicationCliArgumentParser is not enough.
+ *
+ */
+class DisableReplicationUserData extends ReplicationUserData
+{
+  private String hostName;
+  private int port;
+  private boolean useStartTLS;
+  private boolean useSSL;
+
+  /**
+   * Returns the host name of the server.
+   * @return the host name of the server.
+   */
+  String getHostName()
+  {
+    return hostName;
+  }
+
+  /**
+   * Sets the host name of the server.
+   * @param hostName the host name of the server.
+   */
+  void setHostName(String hostName)
+  {
+    this.hostName = hostName;
+  }
+
+  /**
+   * Returns the port of the server.
+   * @return the port of the server.
+   */
+  int getPort()
+  {
+    return port;
+  }
+
+  /**
+   * Sets the port of the server.
+   * @param port the port of the server.
+   */
+  void setPort(int port)
+  {
+    this.port = port;
+  }
+  /**
+   * Returns <CODE>true</CODE> if we must use SSL to connect to the server and
+   * <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use SSL to connect to the server and
+   * <CODE>false</CODE> otherwise.
+   */
+  boolean useSSL()
+  {
+    return useSSL;
+  }
+
+  /**
+   * Sets whether we must use SSL to connect to the server or not.
+   * @param useSSL whether we must use SSL to connect to the server or not.
+   */
+  void setUseSSL(boolean useSSL)
+  {
+    this.useSSL = useSSL;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use StartTLS to connect to the server
+   * and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use StartTLS to connect to the server
+   * and <CODE>false</CODE> otherwise.
+   */
+  boolean useStartTLS()
+  {
+    return useStartTLS;
+  }
+
+  /**
+   * Sets whether we must use StartTLS to connect to the server or not.
+   * @param useStartTLS whether we must use SSL to connect to the server or not.
+   */
+  void setUseStartTLS(boolean useStartTLS)
+  {
+    this.useStartTLS = useStartTLS;
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java b/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java
new file mode 100644
index 0000000..e17ca87
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java
@@ -0,0 +1,325 @@
+/*
+ * 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.guitools.replicationcli;
+
+/**
+ * This class is used to store the information provided by the user to enable
+ * replication.  It is required because when we are in interactive mode the
+ * ReplicationCliArgumentParser is not enough.
+ *
+ */
+class EnableReplicationUserData extends ReplicationUserData
+{
+  private String hostName1;
+  private int port1;
+  private String bindDn1;
+  private String pwd1;
+  private boolean useStartTLS1;
+  private boolean useSSL1;
+  private int replicationPort1;
+  private String hostName2;
+  private int port2;
+  private String pwd2;
+  private String bindDn2;
+  private boolean useStartTLS2;
+  private boolean useSSL2;
+  private int replicationPort2;
+
+  /**
+   * Returns the host name of the first server.
+   * @return the host name of the first server.
+   */
+  String getHostName1()
+  {
+    return hostName1;
+  }
+
+  /**
+   * Sets the host name of the first server.
+   * @param hostName1 the host name of the first server.
+   */
+  void setHostName1(String hostName1)
+  {
+    this.hostName1 = hostName1;
+  }
+
+  /**
+   * Returns the port of the first server.
+   * @return the port of the first server.
+   */
+  int getPort1()
+  {
+    return port1;
+  }
+
+  /**
+   * Sets the port of the first server.
+   * @param port1 the port of the first server.
+   */
+  void setPort1(int port1)
+  {
+    this.port1 = port1;
+  }
+
+  /**
+   * Returns the password for the first server.
+   * @return the password for the first server.
+   */
+  String getPwd1()
+  {
+    return pwd1;
+  }
+
+  /**
+   * Sets the password for the first server.
+   * @param pwd1 the password for the first server.
+   */
+  void setPwd1(String pwd1)
+  {
+    this.pwd1 = pwd1;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use SSL to connect to the first
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use SSL to connect to the first
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useSSL1()
+  {
+    return useSSL1;
+  }
+
+  /**
+   * Sets whether we must use SSL to connect to the first server or not.
+   * @param useSSL1 whether we must use SSL to connect to the first server or
+   * not.
+   */
+  void setUseSSL1(boolean useSSL1)
+  {
+    this.useSSL1 = useSSL1;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use StartTLS to connect to the first
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use StartTLS to connect to the first
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useStartTLS1()
+  {
+    return useStartTLS1;
+  }
+
+  /**
+   * Sets whether we must use StartTLS to connect to the first server or not.
+   * @param useStartTLS1 whether we must use SSL to connect to the first server
+   * or not.
+   */
+  void setUseStartTLS1(boolean useStartTLS1)
+  {
+    this.useStartTLS1 = useStartTLS1;
+  }
+
+
+  /**
+   * Returns the host name of the second server.
+   * @return the host name of the second server.
+   */
+  String getHostName2()
+  {
+    return hostName2;
+  }
+
+  /**
+   * Sets the host name of the second server.
+   * @param host2Name the host name of the second server.
+   */
+  void setHostName2(String host2Name)
+  {
+    this.hostName2 = host2Name;
+  }
+
+  /**
+   * Returns the port of the second server.
+   * @return the port of the second server.
+   */
+  int getPort2()
+  {
+    return port2;
+  }
+
+  /**
+   * Sets the port of the second server.
+   * @param port2 the port of the second server.
+   */
+  void setPort2(int port2)
+  {
+    this.port2 = port2;
+  }
+
+  /**
+   * Returns the password for the second server.
+   * @return the password for the second server.
+   */
+  String getPwd2()
+  {
+    return pwd2;
+  }
+
+  /**
+   * Sets the password for the second server.
+   * @param pwd2 the password for the second server.
+   */
+  void setPwd2(String pwd2)
+  {
+    this.pwd2 = pwd2;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use SSL to connect to the second
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use SSL to connect to the second
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useSSL2()
+  {
+    return useSSL2;
+  }
+
+  /**
+   * Sets whether we must use SSL to connect to the second server or not.
+   * @param useSSL2 whether we must use SSL to connect to the second server or
+   * not.
+   */
+  void setUseSSL2(boolean useSSL2)
+  {
+    this.useSSL2 = useSSL2;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use StartTLS to connect to the second
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use StartTLS to connect to the second
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useStartTLS2()
+  {
+    return useStartTLS2;
+  }
+
+  /**
+   * Sets whether we must use StartTLS to connect to the second server or not.
+   * @param useStartTLS2 whether we must use SSL to connect to the second server
+   * or not.
+   */
+  void setUseStartTLS2(boolean useStartTLS2)
+  {
+    this.useStartTLS2 = useStartTLS2;
+  }
+
+  /**
+   * Returns the dn to be used to bind to the first server.
+   * @return the dn to be used to bind to the first server.
+   */
+  String getBindDn1()
+  {
+    return bindDn1;
+  }
+
+  /**
+   * Sets the dn to be used to bind to the first server.
+   * @param bindDn1 the dn to be used to bind to the first server.
+   */
+  void setBindDn1(String bindDn1)
+  {
+    this.bindDn1 = bindDn1;
+  }
+
+  /**
+   * Returns the dn to be used to bind to the second server.
+   * @return the dn to be used to bind to the second server.
+   */
+  String getBindDn2()
+  {
+    return bindDn2;
+  }
+
+  /**
+   * Sets the dn to be used to bind to the second server.
+   * @param bindDn2 the dn to be used to bind to the second server.
+   */
+  void setBindDn2(String bindDn2)
+  {
+    this.bindDn2 = bindDn2;
+  }
+
+  /**
+   * Returns the replication port to be used on the first server if it is not
+   * defined yet.
+   * @return the replication port to be used on the first server if it is not
+   * defined yet.
+   */
+  int getReplicationPort1()
+  {
+    return replicationPort1;
+  }
+
+  /**
+   * Sets the replication port to be used on the first server if it is not
+   * defined yet.
+   * @param replicationPort1 the replication port to be used on the first server
+   * if it is not defined yet.
+   */
+  void setReplicationPort1(int replicationPort1)
+  {
+    this.replicationPort1 = replicationPort1;
+  }
+
+  /**
+   * Returns the replication port to be used on the second server if it is not
+   * defined yet.
+   * @return the replication port to be used on the second server if it is not
+   * defined yet.
+   */
+  int getReplicationPort2()
+  {
+    return replicationPort2;
+  }
+
+  /**
+   * Sets the replication port to be used on the second server if it is not
+   * defined yet.
+   * @param replicationPort2 the replication port to be used on the second
+   * server if it is not defined yet.
+   */
+  void setReplicationPort2(int replicationPort2)
+  {
+    this.replicationPort2 = replicationPort2;
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java b/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java
new file mode 100644
index 0000000..4f68e23
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java
@@ -0,0 +1,203 @@
+/*
+ * 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.guitools.replicationcli;
+
+/**
+ * This class is used to store the information provided by the user to
+ * initialize replication.  It is required because when we are in interactive
+ * mode the ReplicationCliArgumentParser is not enough.
+ *
+ */
+class InitializeReplicationUserData extends ReplicationUserData
+{
+  private String hostNameSource;
+  private int portSource;
+  private boolean useStartTLSSource;
+  private boolean useSSLSource;
+  private String hostNameDestination;
+  private int portDestination;
+  private boolean useStartTLSDestination;
+  private boolean useSSLDestination;
+
+  /**
+   * Returns the host name of the source server.
+   * @return the host name of the source server.
+   */
+  String getHostNameSource()
+  {
+    return hostNameSource;
+  }
+
+  /**
+   * Sets the host name of the source server.
+   * @param hostNameSource the host name of the source server.
+   */
+  void setHostNameSource(String hostNameSource)
+  {
+    this.hostNameSource = hostNameSource;
+  }
+
+  /**
+   * Returns the port of the source server.
+   * @return the port of the source server.
+   */
+  int getPortSource()
+  {
+    return portSource;
+  }
+
+  /**
+   * Sets the port of the source server.
+   * @param portSource the port of the source server.
+   */
+  void setPortSource(int portSource)
+  {
+    this.portSource = portSource;
+  }
+  /**
+   * Returns <CODE>true</CODE> if we must use SSL to connect to the source
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use SSL to connect to the source
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useSSLSource()
+  {
+    return useSSLSource;
+  }
+
+  /**
+   * Sets whether we must use SSL to connect to the source server or not.
+   * @param useSSLSource whether we must use SSL to connect to the source server
+   * or not.
+   */
+  void setUseSSLSource(boolean useSSLSource)
+  {
+    this.useSSLSource = useSSLSource;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use StartTLS to connect to the source
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use StartTLS to connect to the source
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useStartTLSSource()
+  {
+    return useStartTLSSource;
+  }
+
+  /**
+   * Sets whether we must use StartTLS to connect to the source server or not.
+   * @param useStartTLSSource whether we must use SSL to connect to the source
+   * server or not.
+   */
+  void setUseStartTLSSource(boolean useStartTLSSource)
+  {
+    this.useStartTLSSource = useStartTLSSource;
+  }
+
+
+  /**
+   * Returns the host name of the destination server.
+   * @return the host name of the destination server.
+   */
+  String getHostNameDestination()
+  {
+    return hostNameDestination;
+  }
+
+  /**
+   * Sets the host name of the destination server.
+   * @param hostNameDestination the host name of the destination server.
+   */
+  void setHostNameDestination(String hostNameDestination)
+  {
+    this.hostNameDestination = hostNameDestination;
+  }
+
+  /**
+   * Returns the port of the destination server.
+   * @return the port of the destination server.
+   */
+  int getPortDestination()
+  {
+    return portDestination;
+  }
+
+  /**
+   * Sets the port of the destination server.
+   * @param portDestination the port of the destination server.
+   */
+  void setPortDestination(int portDestination)
+  {
+    this.portDestination = portDestination;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use SSL to connect to the destination
+   * server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use SSL to connect to the destination
+   * server and <CODE>false</CODE> otherwise.
+   */
+  boolean useSSLDestination()
+  {
+    return useSSLDestination;
+  }
+
+  /**
+   * Sets whether we must use SSL to connect to the destination server or not.
+   * @param useSSLDestination whether we must use SSL to connect to the
+   * destination server or not.
+   */
+  void setUseSSLDestination(boolean useSSLDestination)
+  {
+    this.useSSLDestination = useSSLDestination;
+  }
+
+  /**
+   * Returns <CODE>true</CODE> if we must use StartTLS to connect to the
+   * destination server and <CODE>false</CODE> otherwise.
+   * @return <CODE>true</CODE> if we must use StartTLS to connect to the
+   * destination server and <CODE>false</CODE> otherwise.
+   */
+  boolean useStartTLSDestination()
+  {
+    return useStartTLSDestination;
+  }
+
+  /**
+   * Sets whether we must use StartTLS to connect to the destination server or
+   * not.
+   * @param useStartTLSDestination whether we must use SSL to connect to the
+   * destination server or not.
+   */
+  void setUseStartTLSDestination(boolean useStartTLSDestination)
+  {
+    this.useStartTLSDestination = useStartTLSDestination;
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java
new file mode 100644
index 0000000..baa9d01
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java
@@ -0,0 +1,63 @@
+/*
+ * 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.guitools.replicationcli;
+
+import org.opends.messages.Message;
+import org.opends.server.types.OpenDsException;
+
+/**
+ * The exception that is thrown during the replication command-line execution.
+ *
+ */
+public class ReplicationCliException extends OpenDsException {
+  private static final long serialVersionUID = -8085682356609610678L;
+  private ReplicationCliReturnCode errorCode;
+
+  /**
+   * The constructor for the exception.
+   * @param message the localized message.
+   * @param errorCode the error code associated with this exception.
+   * @param cause the cause that generated this exception.
+   */
+  ReplicationCliException(Message message, ReplicationCliReturnCode errorCode,
+      Throwable cause)
+  {
+    super(message, cause);
+    this.errorCode = errorCode;
+  }
+
+  /**
+   * Returns the error code associated with this exception.
+   * @return the error code associated with this exception.
+   */
+  public ReplicationCliReturnCode getErrorCode()
+  {
+    return errorCode;
+  }
+}
+
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
new file mode 100644
index 0000000..d9ed908
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
@@ -0,0 +1,3780 @@
+/*
+ * 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.guitools.replicationcli;
+
+import static org.opends.guitools.replicationcli.ReplicationCliReturnCode.*;
+import static org.opends.messages.AdminToolMessages.*;
+import static org.opends.messages.QuickSetupMessages.*;
+import static org.opends.messages.ToolMessages.*;
+import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
+import static org.opends.server.util.StaticUtils.wrapText;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.naming.NamingException;
+import javax.naming.NoPermissionException;
+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.ConnectionUtils;
+import org.opends.admin.ads.util.ServerLoader;
+import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
+import org.opends.quicksetup.ApplicationException;
+import org.opends.quicksetup.CliApplicationHelper;
+import org.opends.quicksetup.Constants;
+import org.opends.quicksetup.event.ProgressUpdateEvent;
+import org.opends.quicksetup.event.ProgressUpdateListener;
+import org.opends.quicksetup.installer.InstallerHelper;
+import org.opends.quicksetup.installer.PeerNotFoundException;
+import org.opends.quicksetup.installer.offline.OfflineInstaller;
+import org.opends.quicksetup.util.PlainTextProgressMessageFormatter;
+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.JNDIDirContextAdaptor;
+import org.opends.server.admin.client.ldap.LDAPManagementContext;
+import org.opends.server.admin.std.client.*;
+import org.opends.server.admin.std.meta.*;
+import org.opends.server.types.DN;
+import org.opends.server.types.NullOutputStream;
+import org.opends.server.types.OpenDsException;
+import org.opends.server.util.args.ArgumentException;
+
+/**
+ * This class provides a tool that can be used to enable and disable replication
+ * and also to initialize the contents of a replicated suffix with the contents
+ * of another suffix.
+ */
+public class ReplicationCliMain extends CliApplicationHelper
+{
+  /**
+   * The fully-qualified name of this class.
+   */
+  private static final String CLASS_NAME = ReplicationCliMain.class.getName();
+
+  private static final Logger LOG =
+    Logger.getLogger(CliApplicationHelper.class.getName());
+
+  // The print stream to use for standard error.
+  private PrintStream err;
+
+  // The print stream to use for standard output.
+  private PrintStream out;
+
+  // The argument parser to be used.
+  private ReplicationCliParser argParser;
+
+  // The message formatter
+  PlainTextProgressMessageFormatter formatter =
+      new PlainTextProgressMessageFormatter();
+
+  /**
+   * Constructor for the ReplicationCliMain object.
+   *
+   * @param  out the print stream to use for standard output.
+   * @param  err the print stream to use for standard error.
+   */
+  public ReplicationCliMain(PrintStream out, PrintStream err)
+  {
+    this.out = out;
+    this.err = err;
+  }
+
+  /**
+   * The main method for the replication tool.
+   *
+   * @param args the command-line arguments provided to this program.
+   */
+
+  public static void main(String[] args)
+  {
+    int retCode = mainCLI(args, true, System.out, System.err);
+
+    if(retCode != 0)
+    {
+      System.exit(retCode);
+    }
+  }
+
+  /**
+   * Parses the provided command-line arguments and uses that information to
+   * run the replication tool.
+   *
+   * @param args the command-line arguments provided to this program.
+   *
+   * @return The error code.
+   */
+
+  public static int mainCLI(String[] args)
+  {
+    return mainCLI(args, true, System.out, System.err);
+  }
+
+  /**
+   * Parses the provided command-line arguments and uses that information to
+   * run the replication tool.
+   *
+   * @param  args              The command-line arguments provided to this
+   *                           program.
+   * @param initializeServer   Indicates whether to initialize the server.
+   * @param  outStream         The output stream to use for standard output, or
+   *                           <CODE>null</CODE> if standard output is not
+   *                           needed.
+   * @param  errStream         The output stream to use for standard error, or
+   *                           <CODE>null</CODE> if standard error is not
+   *                           needed.
+   * @return The error code.
+   */
+
+  public static int mainCLI(String[] args, boolean initializeServer,
+      OutputStream outStream, OutputStream errStream)
+  {
+    PrintStream out;
+    if (outStream == null)
+    {
+      out = NullOutputStream.printStream();
+    }
+    else
+    {
+      out = new PrintStream(outStream);
+    }
+
+    PrintStream err;
+    if (errStream == null)
+    {
+      err = NullOutputStream.printStream();
+    }
+    else
+    {
+      err = new PrintStream(errStream);
+    }
+
+    ReplicationCliMain replicationCli = new ReplicationCliMain(out, err);
+    return replicationCli.execute(args, initializeServer);
+  }
+
+  /**
+   * Parses the provided command-line arguments and uses that information to
+   * run the replication tool.
+   *
+   * @param args the command-line arguments provided to this program.
+   * @param  initializeServer  Indicates whether to initialize the server.
+   *
+   * @return The error code.
+   */
+  public int execute(String[] args, boolean initializeServer)
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    // Create the command-line argument parser for use with this
+    // program.
+    try
+    {
+      argParser = new ReplicationCliParser(CLASS_NAME);
+      argParser.initializeParser(out);
+    }
+    catch (ArgumentException ae)
+    {
+      Message message = ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
+
+      printErrorMessage(message);
+      LOG.log(Level.SEVERE, "Complete error stack:", ae);
+      returnValue = CANNOT_INITIALIZE_ARGS;
+    }
+
+    if (returnValue == SUCCESSFUL_NOP)
+    {
+      //  Parse the command-line arguments provided to this program.
+      try
+      {
+        argParser.parseArguments(args);
+      }
+      catch (ArgumentException ae)
+      {
+        Message message = ERR_ERROR_PARSING_ARGS.get(ae.getMessage());
+
+        printErrorMessage(message);
+        err.println(argParser.getUsage());
+        LOG.log(Level.SEVERE, "Complete error stack:", ae);
+        returnValue = ERROR_PARSING_ARGS;
+      }
+    }
+
+    if (returnValue == SUCCESSFUL_NOP)
+    {
+      /* Check that the provided parameters are compatible.
+       */
+      MessageBuilder buf = new MessageBuilder();
+      argParser.validateOptions(buf);
+      if (buf.length() > 0)
+      {
+        err.println(wrapText(buf.toMessage(), MAX_LINE_WIDTH));
+        err.println(argParser.getUsage());
+        returnValue = ERROR_PARSING_ARGS;
+      }
+    }
+
+    if (returnValue == SUCCESSFUL_NOP)
+    {
+      if (argParser.isEnableReplicationSubcommand())
+      {
+        returnValue = enableReplication();
+      }
+      else if (argParser.isDisableReplicationSubcommand())
+      {
+        returnValue = disableReplication();
+      }
+      else if (argParser.isInitializeReplicationSubcommand())
+      {
+        returnValue = initializeReplication();
+      }
+      else
+      {
+        err.println(wrapText(ERR_REPLICATION_VALID_SUBCOMMAND_NOT_FOUND.get(),
+            MAX_LINE_WIDTH));
+        err.println(argParser.getUsage());
+        returnValue = ERROR_PARSING_ARGS;
+      }
+    }
+    return returnValue.getReturnCode();
+  }
+
+  /**
+   * Displays an error message in the error output (wrapping it if necessary).
+   * @param msg the error message to be displayed.
+   */
+  protected void printErrorMessage(Message msg)
+  {
+    err.println(org.opends.server.util.StaticUtils.wrapText(msg,
+        Utils.getCommandLineMaxLineWidth()));
+    LOG.log(Level.SEVERE, msg.toString());
+  }
+
+  /**
+   * Displays a progress message in the error output (wrapping it if necessary).
+   * @param msg the error message to be displayed.
+   */
+  protected void printProgressMessage(Message msg)
+  {
+    if (!argParser.isQuiet())
+    {
+      out.print(org.opends.server.util.StaticUtils.wrapText(msg,
+          Utils.getCommandLineMaxLineWidth()));
+      out.flush();
+    }
+    LOG.log(Level.INFO, msg.toString());
+  }
+
+  /**
+   * Prints a line break in the standard output if we are not in quite mode.
+   */
+  protected void printProgressLineBreak()
+  {
+    if (!argParser.isQuiet())
+    {
+      out.println();
+    }
+  }
+
+  /**
+   * Displays a warning message in the error output (wrapping it if necessary).
+   * @param msg the warning message to be displayed.
+   */
+  protected void printWarningMessage(Message msg)
+  {
+    if (!argParser.isQuiet())
+    {
+      // TODO: decide if even in quiet mode we must display this message or not.
+      out.print(org.opends.server.util.StaticUtils.wrapText(msg,
+          Utils.getCommandLineMaxLineWidth()));
+      out.flush();
+    }
+    LOG.log(Level.WARNING, msg.toString());
+  }
+
+  /**
+   * Prints a line break in the standard output.
+   */
+  protected void printLineBreak()
+  {
+    out.println();
+  }
+
+  /**
+   * Based on the data provided in the command-line it enables replication
+   * between two servers.
+   * @return the error code if the operation failed and 0 if it was successful.
+   */
+  private ReplicationCliReturnCode enableReplication()
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    EnableReplicationUserData uData = new EnableReplicationUserData();
+    if (argParser.isInteractive())
+    {
+      if (promptIfRequired(uData))
+      {
+        returnValue = enableReplication(uData);
+      }
+      else
+      {
+        returnValue = USER_CANCELLED;
+      }
+    }
+    else
+    {
+      initializeWithArgParser(uData);
+      returnValue = enableReplication(uData);
+    }
+    return returnValue;
+  }
+
+  /**
+   * Based on the data provided in the command-line it disables replication
+   * in the server.
+   * @return the error code if the operation failed and SUCCESSFUL if it was
+   * successful.
+   */
+  private ReplicationCliReturnCode disableReplication()
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    DisableReplicationUserData uData = new DisableReplicationUserData();
+    if (argParser.isInteractive())
+    {
+      if (promptIfRequired(uData))
+      {
+        returnValue = disableReplication(uData);
+      }
+      else
+      {
+        returnValue = USER_CANCELLED;
+      }
+    }
+    else
+    {
+      initializeWithArgParser(uData);
+      returnValue = disableReplication(uData);
+    }
+    return returnValue;
+  }
+
+  /**
+   * Based on the data provided in the command-line it initializes replication
+   * between two servers.
+   * @return the error code if the operation failed and SUCCESSFUL if it was
+   * successful.
+   */
+  private ReplicationCliReturnCode initializeReplication()
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    InitializeReplicationUserData uData = new InitializeReplicationUserData();
+    if (argParser.isInteractive())
+    {
+      if (promptIfRequired(uData))
+      {
+        returnValue = initializeReplication(uData);
+      }
+      else
+      {
+        returnValue = USER_CANCELLED;
+      }
+    }
+    else
+    {
+      initializeWithArgParser(uData);
+      returnValue = initializeReplication(uData);
+    }
+    return returnValue;
+  }
+
+  /**
+   * Updates the contents of the provided EnableReplicationUserData object
+   * with the information provided in the command-line.  If some information
+   * is missing, ask the user to provide valid data.
+   * We assume that if this method is called we are in interactive mode.
+   * @param uData the object to be updated.
+   * @return <CODE>true</CODE> if the object was successfully updated and
+   * <CODE>false</CODE> if the user cancelled the operation.
+   */
+  private boolean promptIfRequired(EnableReplicationUserData uData)
+  {
+    boolean cancelled = false;
+
+    String adminPwd = argParser.getBindPasswordAdmin();
+    String adminUid = argParser.getAdministratorUID();
+
+    /*
+     * Try to connect to the first server.
+     */
+    String host1 = getValue(argParser.getHostName1(),
+        argParser.getDefaultHostName1());
+    int port1 = getValue(argParser.getPort1(),
+        argParser.getDefaultPort1());
+    String bindDn1 = getValue(argParser.getBindDn1(),
+        argParser.getDefaultBindDn1());
+    String pwd1 = argParser.getBindPassword1();
+    if ((pwd1 == null) && (adminPwd != null) && (adminUid != null))
+    {
+      // No information provided to connect to the first server.  Try
+      // to use global administrator.
+      bindDn1 = ADSContext.getAdministratorDN(adminUid);
+      pwd1 = adminPwd;
+    }
+    boolean useSSL1 = argParser.useSSL1();
+    boolean useStartTLS1 = argParser.useStartTLS1();
+    InitialLdapContext ctx1 = null;
+    // Boolean used to only ask for the information that was not explicitly
+    // provided the first time we ask.  After we ask for all the information.
+    boolean firstTimeAsked =
+      (argParser.getHostName1() == null) ||
+      (argParser.getPort1() == -1) ||
+      (argParser.getBindDn1() == null) ||
+      (argParser.getBindPassword1() == null);
+
+    while ((ctx1 == null) && !cancelled)
+    {
+      try
+      {
+        ctx1 = createContext(host1, port1, useSSL1, useStartTLS1, bindDn1,
+            pwd1, getTrustManager());
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.WARNING, "Error connecting to "+host1+":"+port1, ne);
+        if (Utils.isCertificateException(ne))
+        {
+          String usedUrl = getLDAPUrl(host1, port1, useSSL1);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          if (pwd1 != null)
+          {
+            printLineBreak();
+            printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+                host1+":"+port1));
+          }
+          printLineBreak();
+          if (!firstTimeAsked || (argParser.getHostName1() == null))
+          {
+            host1 = promptForString(
+              INFO_REPLICATION_ENABLE_HOSTNAME1_PROMPT.get(),
+              getValue(host1, argParser.getDefaultHostName1()));
+          }
+          if (!firstTimeAsked || (argParser.getPort1() == -1))
+          {
+            port1 = promptForPort(INFO_REPLICATION_ENABLE_PORT1_PROMPT.get(),
+              getValue(port1, argParser.getDefaultPort1()));
+          }
+          if (!firstTimeAsked || (argParser.getBindDn1() == null))
+          {
+            bindDn1 = promptForString(
+              INFO_REPLICATION_BINDDN_PROMPT.get(),
+              getValue(bindDn1, argParser.getDefaultBindDn1()));
+          }
+          if (!firstTimeAsked || (argParser.getBindPassword1() == null))
+          {
+            pwd1 = promptForPassword(INFO_REPLICATION_PASSWORD_PROMPT.get());
+          }
+          if (!firstTimeAsked || (!useSSL1 && !useStartTLS1))
+          {
+            useSSL1 = confirm(INFO_REPLICATION_USESSL_PROMPT.get(),
+                useSSL1);
+            if (!useSSL1)
+            {
+              useStartTLS1 = confirm(INFO_REPLICATION_USESTARTTLS_PROMPT.get(),
+                  useStartTLS1);
+            }
+          }
+          firstTimeAsked = false;
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostName1(host1);
+      uData.setPort1(port1);
+      uData.setBindDn1(bindDn1);
+      uData.setPwd1(pwd1);
+      uData.setUseSSL1(useSSL1);
+      uData.setUseStartTLS1(useStartTLS1);
+    }
+    if (ctx1 != null)
+    {
+      // Try to get the replication port for server 1 only if the user did
+      // not explicitly provide it and if it is required.
+      int replicationPort1 = argParser.getReplicationPort1();
+      if (replicationPort1 == -1)
+      {
+        if (!hasReplicationPort(ctx1))
+        {
+          while (replicationPort1 == -1)
+          {
+            replicationPort1 = promptForPort(
+                INFO_REPLICATION_ENABLE_REPLICATIONPORT1_PROMPT.get(),
+                argParser.getDefaultReplicationPort1());
+            if (replicationPort1 == port1)
+            {
+              replicationPort1 = -1;
+              printLineBreak();
+              printErrorMessage(
+                  ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
+                      String.valueOf(port1)));
+            }
+          }
+          uData.setReplicationPort1(replicationPort1);
+        }
+      }
+      else
+      {
+        uData.setReplicationPort1(replicationPort1);
+      }
+      // If the server contains an ADS. Try to load it and only load it: if
+      // there are issues with the ADS they will be encountered in the
+      // enableReplication(EnableReplicationUserData) method.  Here we have
+      // to load the ADS to ask the user to accept the certificates and
+      // eventually admin authentication data.
+      cancelled = loadADSAndAcceptCertificates(ctx1, uData, true);
+    }
+
+    /*
+     * Try to connect to the second server.
+     */
+    String host2 = getValue(argParser.getHostName2(),
+        argParser.getDefaultHostName2());
+    int port2 = getValue(argParser.getPort2(),
+        argParser.getDefaultPort2());
+    String bindDn2 = getValue(argParser.getBindDn2(),
+        argParser.getDefaultBindDn2());
+    String pwd2 = argParser.getBindPassword2();
+    if ((pwd2 == null) && (adminPwd != null) && (adminUid != null))
+    {
+      // No information provided to connect to the second server.  Try
+      // to use global administrator.
+      bindDn2 = ADSContext.getAdministratorDN(adminUid);
+      pwd2 = adminPwd;
+    }
+    boolean useSSL2 = argParser.useSSL2();
+    boolean useStartTLS2 = argParser.useStartTLS2();
+    InitialLdapContext ctx2 = null;
+    firstTimeAsked =
+      (argParser.getHostName2() == null) ||
+      (argParser.getPort2() == -1) ||
+      (argParser.getBindDn2() == null) ||
+      (argParser.getBindPassword2() == null);
+    while ((ctx2 == null) && !cancelled)
+    {
+      try
+      {
+        ctx2 = createContext(host2, port2, useSSL2, useStartTLS2, bindDn2,
+            pwd2, getTrustManager());
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.WARNING, "Error connecting to "+host2+":"+port2, ne);
+        if (Utils.isCertificateException(ne))
+        {
+          String usedUrl = getLDAPUrl(host2, port2, useSSL2);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          if (pwd2 != null)
+          {
+            printLineBreak();
+            printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+                host2+":"+port2));
+          }
+          printLineBreak();
+          if (!firstTimeAsked || (argParser.getHostName2() == null))
+          {
+            host2 = promptForString(
+              INFO_REPLICATION_ENABLE_HOSTNAME2_PROMPT.get(),
+              getValue(host2, argParser.getDefaultHostName2()));
+          }
+          if (!firstTimeAsked || (argParser.getPort2() == -1))
+          {
+            port2 = promptForPort(INFO_REPLICATION_ENABLE_PORT2_PROMPT.get(),
+              getValue(port2, argParser.getDefaultPort2()));
+          }
+          if (!firstTimeAsked || (argParser.getBindDn2() == null))
+          {
+            bindDn2 = promptForString(
+              INFO_REPLICATION_BINDDN_PROMPT.get(),
+              getValue(bindDn2, argParser.getDefaultBindDn2()));
+          }
+          if (!firstTimeAsked || (argParser.getBindPassword2() == null))
+          {
+            pwd2 = promptForPassword(INFO_REPLICATION_PASSWORD_PROMPT.get());
+          }
+          if (!firstTimeAsked || !useSSL2 || !useStartTLS2)
+          {
+            useSSL2 = confirm(INFO_REPLICATION_USESSL_PROMPT.get(),
+                useSSL2);
+            if (!useSSL2)
+            {
+              useStartTLS2 = confirm(INFO_REPLICATION_USESTARTTLS_PROMPT.get(),
+                  useStartTLS2);
+            }
+          }
+          firstTimeAsked = false;
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostName2(host2);
+      uData.setPort2(port2);
+      uData.setBindDn2(bindDn2);
+      uData.setPwd2(pwd2);
+      uData.setUseSSL2(useSSL2);
+      uData.setUseStartTLS2(useStartTLS2);
+    }
+    if (ctx2 != null)
+    {
+      int replicationPort2 = argParser.getReplicationPort2();
+      if (replicationPort2 == -1)
+      {
+        if (!hasReplicationPort(ctx2))
+        {
+          while (replicationPort2 == -1)
+          {
+            replicationPort2 = promptForPort(
+                INFO_REPLICATION_ENABLE_REPLICATIONPORT2_PROMPT.get(),
+                argParser.getDefaultReplicationPort2());
+            if (replicationPort2 == port2)
+            {
+              replicationPort2 = -1;
+              printLineBreak();
+              printErrorMessage(
+                  ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
+                      String.valueOf(port2)));
+            }
+          }
+          uData.setReplicationPort2(replicationPort2);
+        }
+      }
+      else
+      {
+        uData.setReplicationPort2(replicationPort2);
+      }
+      // If the server contains an ADS. Try to load it and only load it: if
+      // there are issues with the ADS they will be encountered in the
+      // enableReplication(EnableReplicationUserData) method.  Here we have
+      // to load the ADS to ask the user to accept the certificates.
+      cancelled = loadADSAndAcceptCertificates(ctx2, uData, false);
+    }
+
+    // If the adminUid and adminPwd are not set in the EnableReplicationUserData
+    // object, that means that there are no administrators and that they
+    // must be created. The adminUId and adminPwd are updated inside
+    // loadADSAndAcceptCertificates.
+    if (!cancelled && (uData.getAdminUid() == null))
+    {
+      if (adminUid == null)
+      {
+        adminUid= askForAdministratorUID(
+            argParser.getDefaultAdministratorUID());
+      }
+      uData.setAdminUid(adminUid);
+    }
+
+    if (!cancelled && (uData.getAdminPwd() == null))
+    {
+      boolean adminDefined = hasAdministrator(ctx1) || hasAdministrator(ctx2);
+      while ((adminPwd == null) && !adminDefined)
+      {
+        adminPwd = askForAdministratorPwd();
+        String adminPwdConfirm =
+          promptForPassword(INFO_ADMINISTRATOR_PWD_CONFIRM_PROMPT.get());
+        if (!adminPwd.equals(adminPwdConfirm))
+        {
+          printErrorMessage(ERR_ADMINISTRATOR_PWD_DO_NOT_MATCH.get());
+          printLineBreak();
+          adminPwd = null;
+        }
+      }
+      uData.setAdminPwd(adminPwd);
+    }
+
+    if (!cancelled)
+    {
+      LinkedList<String> suffixes = argParser.getBaseDNs();
+      checkSuffixesForEnableReplication(suffixes, ctx1, ctx2, true);
+      cancelled = suffixes.isEmpty();
+
+      uData.setBaseDNs(suffixes);
+    }
+
+    if (ctx1 != null)
+    {
+      try
+      {
+        ctx1.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+
+    if (ctx2 != null)
+    {
+      try
+      {
+        ctx2.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    return cancelled;
+  }
+
+  /**
+   * Updates the contents of the provided DisableReplicationUserData object
+   * with the information provided in the command-line.  If some information
+   * is missing, ask the user to provide valid data.
+   * We assume that if this method is called we are in interactive mode.
+   * @param uData the object to be updated.
+   * @return <CODE>true</CODE> if the object was successfully updated and
+   * <CODE>false</CODE> if the user cancelled the operation.
+   */
+  private boolean promptIfRequired(DisableReplicationUserData uData)
+  {
+    boolean cancelled = false;
+
+    String adminPwd = argParser.getBindPasswordAdmin();
+    String adminUid = argParser.getAdministratorUID();
+
+    if (adminPwd == null)
+    {
+      adminPwd = askForAdministratorPwd();
+    }
+
+    /*
+     * Try to connect to the server.
+     */
+    String host = getValue(argParser.getHostNameToDisable(),
+        argParser.getDefaultHostNameToDisable());
+    int port = getValue(argParser.getPortToDisable(),
+        argParser.getDefaultPortToDisable());
+    boolean useSSL = argParser.useSSLToDisable();
+    boolean useStartTLS = argParser.useStartTLSToDisable();
+    InitialLdapContext ctx = null;
+    boolean firstTimeAsked =
+      (argParser.getHostNameToDisable() == null) ||
+      (argParser.getPortToDisable() == -1) ||
+      (argParser.getAdministratorUID() == null) ||
+      (argParser.getBindPasswordAdmin() == null);
+
+    while ((ctx == null) && !cancelled)
+    {
+      try
+      {
+        ctx = createContext(host, port, useSSL, useStartTLS,
+            ADSContext.getAdministratorDN(adminUid), adminPwd,
+            getTrustManager());
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.WARNING, "Error connecting to "+host+":"+port, ne);
+        if (Utils.isCertificateException(ne))
+        {
+          String usedUrl = getLDAPUrl(host, port, useSSL);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          printLineBreak();
+          printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+              host+":"+port));
+          printLineBreak();
+          if (!firstTimeAsked || (argParser.getHostNameToDisable() == null))
+          {
+            host = promptForString(
+                INFO_REPLICATION_DISABLE_HOSTNAME_PROMPT.get(),
+                getValue(host, argParser.getDefaultHostNameToDisable()));
+          }
+          if (!firstTimeAsked || (argParser.getPortToDisable() == -1))
+          {
+            port = promptForPort(
+                INFO_REPLICATION_DISABLE_PORT_PROMPT.get(),
+              getValue(port, argParser.getDefaultPortToDisable()));
+          }
+          if (!firstTimeAsked || (argParser.getAdministratorUID() == null))
+          {
+            adminUid = askForAdministratorUID(adminUid);
+          }
+          if (!firstTimeAsked || (argParser.getBindPasswordAdmin() == null))
+          {
+            adminPwd = askForAdministratorPwd();
+          }
+          if (!firstTimeAsked || useSSL)
+          {
+            useSSL = confirm(INFO_REPLICATION_USESSL_PROMPT.get(), useSSL);
+            if (!useSSL)
+            {
+              useStartTLS =
+                confirm(INFO_REPLICATION_USESTARTTLS_PROMPT.get(), useStartTLS);
+            }
+          }
+          firstTimeAsked = false;
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostName(host);
+      uData.setPort(port);
+      uData.setUseSSL(useSSL);
+      uData.setUseStartTLS(useStartTLS);
+      uData.setAdminUid(adminUid);
+      uData.setAdminPwd(adminPwd);
+    }
+    if (ctx != null)
+    {
+      // If the server contains an ADS, try to load it and only load it: if
+      // there are issues with the ADS they will be encountered in the
+      // disableReplication(DisableReplicationUserData) method.  Here we have
+      // to load the ADS to ask the user to accept the certificates and
+      // eventually admin authentication data.
+      cancelled = loadADSAndAcceptCertificates(ctx, uData, false);
+    }
+
+    if (!cancelled)
+    {
+      LinkedList<String> suffixes = argParser.getBaseDNs();
+      checkSuffixesForDisableReplication(suffixes, ctx, true);
+      cancelled = suffixes.isEmpty();
+
+      uData.setBaseDNs(suffixes);
+    }
+
+    if (!cancelled)
+    {
+      // Ask for confirmation to disable.
+      boolean disableADS = false;
+      for (String dn : uData.getBaseDNs())
+      {
+        if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
+        {
+          disableADS = true;
+          break;
+        }
+      }
+      if (disableADS)
+      {
+        cancelled = !confirm(INFO_REPLICATION_CONFIRM_DISABLE_ADS.get(
+            ADSContext.getAdministrationSuffixDN()));
+      }
+      else
+      {
+        cancelled = !confirm(INFO_REPLICATION_CONFIRM_DISABLE_GENERIC.get());
+      }
+    }
+
+    if (ctx != null)
+    {
+      try
+      {
+        ctx.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+
+    return cancelled;
+  }
+
+  /**
+   * Updates the contents of the provided InitializeReplicationUserData object
+   * with the information provided in the command-line.  If some information
+   * is missing, ask the user to provide valid data.
+   * We assume that if this method is called we are in interactive mode.
+   * @param uData the object to be updated.
+   * @return <CODE>true</CODE> if the object was successfully updated and
+   * <CODE>false</CODE> if the user cancelled the operation.
+   */
+  private boolean promptIfRequired(InitializeReplicationUserData uData)
+  {
+    boolean cancelled = false;
+
+    String adminPwd = argParser.getBindPasswordAdmin();
+    String adminUid = argParser.getAdministratorUID();
+
+    if (adminPwd == null)
+    {
+      adminPwd = askForAdministratorPwd();
+    }
+
+    /*
+     * Try to connect to the source server.
+     */
+    String hostSource = getValue(argParser.getHostNameSource(),
+        argParser.getDefaultHostNameSource());
+    int portSource = getValue(argParser.getPortSource(),
+        argParser.getDefaultPortSource());
+    boolean useSSLSource = argParser.useSSLSource();
+    boolean useStartTLSSource = argParser.useStartTLSSource();
+    InitialLdapContext ctxSource = null;
+    boolean firstTimeAsked =
+      (argParser.getHostNameSource() == null) ||
+      (argParser.getPortSource() == -1) ||
+      (argParser.getAdministratorUID() == null) ||
+      (argParser.getBindPasswordAdmin() == null);
+
+    while ((ctxSource == null) && !cancelled)
+    {
+      try
+      {
+        ctxSource = createContext(hostSource, portSource, useSSLSource,
+              useStartTLSSource, ADSContext.getAdministratorDN(adminUid),
+              adminPwd, getTrustManager());
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.WARNING, "Error connecting to "+hostSource+":"+portSource,
+            ne);
+        if (Utils.isCertificateException(ne))
+        {
+          String usedUrl = getLDAPUrl(hostSource, portSource, useSSLSource);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          printLineBreak();
+          printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+              hostSource+":"+portSource));
+          printLineBreak();
+          if (!firstTimeAsked || (argParser.getHostNameSource() == null))
+          {
+            hostSource = promptForString(
+                INFO_REPLICATION_INITIALIZE_HOSTNAMESOURCE_PROMPT.get(),
+                getValue(hostSource, argParser.getDefaultHostNameSource()));
+          }
+          if (!firstTimeAsked || (argParser.getPortSource() == -1))
+          {
+            portSource = promptForPort(
+              INFO_REPLICATION_INITIALIZE_PORTSOURCE_PROMPT.get(),
+              getValue(portSource, argParser.getDefaultPortSource()));
+          }
+          if (!firstTimeAsked || (argParser.getAdministratorUID() == null))
+          {
+            adminUid = askForAdministratorUID(adminUid);
+          }
+          if (!firstTimeAsked || (argParser.getBindPasswordAdmin() == null))
+          {
+            adminPwd = askForAdministratorPwd();
+          }
+          if (!firstTimeAsked || useSSLSource)
+          {
+            useSSLSource = confirm(INFO_REPLICATION_USESSL_PROMPT.get(),
+                useSSLSource);
+            if (!useSSLSource)
+            {
+              useStartTLSSource =
+                confirm(INFO_REPLICATION_USESTARTTLS_PROMPT.get(),
+                    useStartTLSSource);
+            }
+          }
+          firstTimeAsked = false;
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostNameSource(hostSource);
+      uData.setPortSource(portSource);
+      uData.setUseSSLSource(useSSLSource);
+      uData.setUseStartTLSSource(useStartTLSSource);
+      uData.setAdminUid(adminUid);
+      uData.setAdminPwd(adminPwd);
+    }
+
+    /*
+     * Try to connect to the destination server.
+     */
+    String hostDestination = getValue(argParser.getHostNameDestination(),
+        argParser.getDefaultHostNameDestination());
+    int portDestination = getValue(argParser.getPortDestination(),
+        argParser.getDefaultPortDestination());
+    boolean useSSLDestination = argParser.useSSLDestination();
+    boolean useStartTLSDestination = argParser.useStartTLSDestination();
+    InitialLdapContext ctxDestination = null;
+    firstTimeAsked =
+      (argParser.getHostNameDestination() == null) ||
+      (argParser.getPortDestination() == -1);
+    while ((ctxDestination == null) && !cancelled)
+    {
+      try
+      {
+        ctxDestination = createContext(hostDestination, portDestination,
+            useSSLDestination, useStartTLSDestination,
+            ADSContext.getAdministratorDN(adminUid),
+            adminPwd, getTrustManager());
+      }
+      catch (NamingException ne)
+      {
+        LOG.log(Level.WARNING, "Error connecting to "+hostDestination+":"+
+            portDestination, ne);
+
+        if (Utils.isCertificateException(ne))
+        {
+          String usedUrl = getLDAPUrl(hostDestination, portDestination,
+              useSSLDestination);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          printLineBreak();
+          printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+              hostDestination+":"+portDestination));
+          printLineBreak();
+          if (!firstTimeAsked || (argParser.getHostNameDestination() == null))
+          {
+            hostDestination = promptForString(
+                INFO_REPLICATION_INITIALIZE_HOSTNAMEDESTINATION_PROMPT.get(),
+                getValue(hostDestination,
+                    argParser.getDefaultHostNameDestination()));
+          }
+          if (!firstTimeAsked || (argParser.getPortDestination() == -1))
+          {
+            portDestination = promptForPort(
+                INFO_REPLICATION_INITIALIZE_PORTDESTINATION_PROMPT.get(),
+                getValue(portDestination,
+                    argParser.getDefaultPortDestination()));
+          }
+          if (!firstTimeAsked || useSSLDestination)
+          {
+            useSSLDestination = confirm(INFO_REPLICATION_USESSL_PROMPT.get(),
+                useSSLDestination);
+            if (!useSSLDestination)
+            {
+              useStartTLSDestination =
+                confirm(INFO_REPLICATION_USESTARTTLS_PROMPT.get(),
+                    useStartTLSDestination);
+            }
+          }
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostNameDestination(hostDestination);
+      uData.setPortDestination(portDestination);
+      uData.setUseSSLDestination(useSSLDestination);
+      uData.setUseStartTLSDestination(useStartTLSDestination);
+    }
+
+    if (!cancelled)
+    {
+      LinkedList<String> suffixes = argParser.getBaseDNs();
+      checkSuffixesForInitializeReplication(suffixes, ctxSource, ctxDestination,
+          true);
+      cancelled = suffixes.isEmpty();
+
+      uData.setBaseDNs(suffixes);
+    }
+
+    if (!cancelled)
+    {
+      // Ask for confirmation to disable.
+      boolean initializeADS = false;
+      for (String dn : uData.getBaseDNs())
+      {
+        if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
+        {
+          initializeADS = true;
+          break;
+        }
+      }
+      String hostPortSource = ConnectionUtils.getHostPort(ctxSource);
+      String hostPortDestination = ConnectionUtils.getHostPort(ctxDestination);
+      if (initializeADS)
+      {
+        cancelled = !confirm(INFO_REPLICATION_CONFIRM_INITIALIZE_ADS.get(
+            ADSContext.getAdministrationSuffixDN(), hostPortDestination,
+            hostPortSource));
+      }
+      else
+      {
+        cancelled = !confirm(INFO_REPLICATION_CONFIRM_INITIALIZE_GENERIC.get(
+            hostPortDestination, hostPortSource));
+      }
+    }
+
+    if (ctxSource != null)
+    {
+      try
+      {
+        ctxSource.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+
+    if (ctxDestination != null)
+    {
+      try
+      {
+        ctxDestination.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    return cancelled;
+  }
+
+  /**
+   * Commodity method that simply checks if a provided value is null or not,
+   * if it is not <CODE>null</CODE> returns it and if it is <CODE>null</CODE>
+   * returns the provided default value.
+   * @param v the value to analyze.
+   * @param defaultValue the default value.
+   * @return if the provided value is not <CODE>null</CODE> returns it and if it
+   * is <CODE>null</CODE> returns the provided default value.
+   */
+  private String getValue(String v, String defaultValue)
+  {
+    if (v != null)
+    {
+      return v;
+    }
+    else
+    {
+      return defaultValue;
+    }
+  }
+
+  /**
+   * Commodity method that simply checks if a provided value is -1 or not,
+   * if it is not -1 returns it and if it is -1 returns the provided default
+   * value.
+   * @param v the value to analyze.
+   * @param defaultValue the default value.
+   * @return if the provided value is not -1 returns it and if it is -1 returns
+   * the provided default value.
+   */
+  private int getValue(int v, int defaultValue)
+  {
+    if (v != -1)
+    {
+      return v;
+    }
+    else
+    {
+      return defaultValue;
+    }
+  }
+
+  /**
+   * Returns the trust manager to be used by this application.
+   * @return the trust manager to be used by this application.
+   */
+  private ApplicationTrustManager getTrustManager()
+  {
+    return argParser.getTrustManager();
+  }
+
+  /**
+   * Initializes the contents of the provided enable replication user data
+   * object with what was provided in the command-line without prompting to the
+   * user.
+   * @param uData the enable replication user data object to be initialized.
+   */
+  private void initializeWithArgParser(EnableReplicationUserData uData)
+  {
+    uData.setBaseDNs(new LinkedList<String>(argParser.getBaseDNs()));
+    String adminUid = getValue(argParser.getAdministratorUID(),
+        argParser.getDefaultAdministratorUID());
+    uData.setAdminUid(adminUid);
+    String adminPwd = argParser.getBindPasswordAdmin();
+    uData.setAdminPwd(adminPwd);
+
+    String host1Name = getValue(argParser.getHostName1(),
+        argParser.getDefaultHostName1());
+    uData.setHostName1(host1Name);
+    int port1 = getValue(argParser.getPort1(),
+        argParser.getDefaultPort1());
+    uData.setPort1(port1);
+    uData.setUseSSL1(argParser.useSSL1());
+    uData.setUseStartTLS1(argParser.useStartTLS1());
+    String pwd1 = argParser.getBindPassword1();
+    if (pwd1 == null)
+    {
+      uData.setBindDn1(ADSContext.getAdministratorDN(adminUid));
+      uData.setPwd1(adminPwd);
+    }
+    else
+    {
+      String bindDn = getValue(argParser.getBindDn1(),
+          argParser.getDefaultBindDn1());
+      uData.setBindDn1(bindDn);
+      uData.setPwd1(pwd1);
+    }
+    int replicationPort1 = getValue(argParser.getReplicationPort1(),
+        argParser.getDefaultReplicationPort1());
+    uData.setReplicationPort1(replicationPort1);
+
+    String host2Name = getValue(argParser.getHostName2(),
+        argParser.getDefaultHostName2());
+    uData.setHostName2(host2Name);
+    int port2 = getValue(argParser.getPort2(),
+        argParser.getDefaultPort2());
+    uData.setPort2(port2);
+    uData.setUseSSL2(argParser.useSSL2());
+    uData.setUseStartTLS2(argParser.useStartTLS2());
+    String pwd2 = argParser.getBindPassword2();
+    if (pwd2 == null)
+    {
+      uData.setBindDn2(ADSContext.getAdministratorDN(adminUid));
+      uData.setPwd2(adminPwd);
+    }
+    else
+    {
+      String bindDn = getValue(argParser.getBindDn2(),
+          argParser.getDefaultBindDn2());
+      uData.setBindDn2(bindDn);
+      uData.setPwd2(pwd2);
+    }
+    uData.setReplicationPort1(replicationPort1);
+  }
+
+  /**
+   * Initializes the contents of the provided initialize replication user data
+   * object with what was provided in the command-line without prompting to the
+   * user.
+   * @param uData the initialize replication user data object to be initialized.
+   */
+  private void initializeWithArgParser(InitializeReplicationUserData uData)
+  {
+    uData.setBaseDNs(new LinkedList<String>(argParser.getBaseDNs()));
+    String adminUid = getValue(argParser.getAdministratorUID(),
+        argParser.getDefaultAdministratorUID());
+    uData.setAdminUid(adminUid);
+    String adminPwd = argParser.getBindPasswordAdmin();
+    uData.setAdminPwd(adminPwd);
+
+    String hostNameSource = getValue(argParser.getHostNameSource(),
+        argParser.getDefaultHostNameSource());
+    uData.setHostNameSource(hostNameSource);
+    int portSource = getValue(argParser.getPortSource(),
+        argParser.getDefaultPortSource());
+    uData.setPortSource(portSource);
+    uData.setUseSSLSource(argParser.useSSLSource());
+    uData.setUseStartTLSSource(argParser.useStartTLSSource());
+
+    String hostNameDestination = getValue(
+        argParser.getHostNameDestination(),
+        argParser.getDefaultHostNameDestination());
+    uData.setHostNameDestination(hostNameDestination);
+    int portDestination = getValue(argParser.getPortSource(),
+        argParser.getDefaultPortDestination());
+    uData.setPortDestination(portDestination);
+    uData.setUseSSLDestination(argParser.useSSLDestination());
+    uData.setUseStartTLSDestination(argParser.useStartTLSDestination());
+  }
+
+  /**
+   * Initializes the contents of the provided disable replication user data
+   * object with what was provided in the command-line without prompting to the
+   * user.
+   * @param uData the disable replication user data object to be initialized.
+   */
+  private void initializeWithArgParser(DisableReplicationUserData uData)
+  {
+    uData.setBaseDNs(new LinkedList<String>(argParser.getBaseDNs()));
+    String adminUid = getValue(argParser.getAdministratorUID(),
+        argParser.getDefaultAdministratorUID());
+    uData.setAdminUid(adminUid);
+    String adminPwd = argParser.getBindPasswordAdmin();
+    uData.setAdminPwd(adminPwd);
+
+    String hostName = getValue(argParser.getHostNameToDisable(),
+        argParser.getDefaultHostNameToDisable());
+    uData.setHostName(hostName);
+    int port = getValue(argParser.getPortToDisable(),
+        argParser.getDefaultPortToDisable());
+    uData.setPort(port);
+    uData.setUseSSL(argParser.useSSLToDisable());
+    uData.setUseStartTLS(argParser.useStartTLSToDisable());
+  }
+
+  /**
+   * Returns an InitialLdapContext using the provided parameters.  We try
+   * to guarantee that the connection is able to read the configuration.
+   * @param host the host name.
+   * @param port the port to connect.
+   * @param useSSL whether to use SSL or not.
+   * @param useStartTLS whether to use StartTLS or not.
+   * @param bindDn the bind dn to be used.
+   * @param pwd the password.
+   * @param trustManager the trust manager.
+   * @return an InitialLdapContext connected.
+   * @throws NamingException if there was an error establishing the connection.
+   */
+  private InitialLdapContext createContext(String host, int port,
+      boolean useSSL, boolean useStartTLS, String bindDn, String pwd,
+      ApplicationTrustManager trustManager)
+  throws NamingException
+  {
+    InitialLdapContext ctx;
+    String ldapUrl = getLDAPUrl(host, port, useSSL);
+    if (useSSL)
+    {
+      ctx = Utils.createLdapsContext(ldapUrl, bindDn, pwd,
+          Utils.getDefaultLDAPTimeout(), null, trustManager);
+    }
+    else if (useStartTLS)
+    {
+      ctx = Utils.createStartTLSContext(ldapUrl, bindDn, pwd,
+          Utils.getDefaultLDAPTimeout(), null, trustManager,
+          null);
+    }
+    else
+    {
+      ctx = Utils.createLdapContext(ldapUrl, bindDn, pwd,
+          Utils.getDefaultLDAPTimeout(), null);
+    }
+    if (!ConnectionUtils.connectedAsAdministrativeUser(ctx))
+    {
+      throw new NoPermissionException(
+          ERR_NOT_ADMINISTRATIVE_USER.get().toString());
+    }
+    return ctx;
+  }
+
+  /**
+   * Returns the LDAP URL for the provided parameters.
+   * @param host the host name.
+   * @param port the LDAP port.
+   * @param useSSL whether to use SSL or not.
+   * @return the LDAP URL for the provided parameters.
+   */
+  private String getLDAPUrl(String host, int port, boolean useSSL)
+  {
+    String ldapUrl;
+    host = Utils.getHostNameForLdapUrl(host);
+    if (useSSL)
+    {
+      ldapUrl = "ldaps://"+host+":"+port;
+    }
+    else
+    {
+      ldapUrl = "ldap://"+host+":"+port;
+    }
+    return ldapUrl;
+  }
+
+  /**
+   * Tells whether the server to which the LdapContext is connected has a
+   * replication port or not.
+   * @param ctx the InitialLdapContext to be used.
+   * @return <CODE>true</CODE> if the replication port for the server could
+   * be found and <CODE>false</CODE> otherwise.
+   */
+  private boolean hasReplicationPort(InitialLdapContext ctx)
+  {
+    return getReplicationPort(ctx) != -1;
+  }
+
+  /**
+   * Returns the replication port of server to which the LdapContext is
+   * connected and -1 if the replication port could not be found.
+   * @param ctx the InitialLdapContext to be used.
+   * @return the replication port of server to which the LdapContext is
+   * connected and -1 if the replication port could not be found.
+   */
+  private int getReplicationPort(InitialLdapContext ctx)
+  {
+    int replicationPort = -1;
+    try
+    {
+      ManagementContext mCtx = LDAPManagementContext.createFromContext(
+          JNDIDirContextAdaptor.adapt(ctx));
+      RootCfgClient root = mCtx.getRootConfiguration();
+
+      MultimasterSynchronizationProviderCfgClient sync = null;
+      sync = (MultimasterSynchronizationProviderCfgClient)
+      root.getSynchronizationProvider("Multimaster Synchronization");
+      /*
+       * Configure the replication server.
+       */
+      if (sync.hasReplicationServer())
+      {
+        ReplicationServerCfgClient replicationServer =
+          sync.getReplicationServer();
+        replicationPort = replicationServer.getReplicationPort();
+      }
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.WARNING,
+          "Unexpected error retrieving the replication port: "+t, t);
+    }
+    return replicationPort;
+  }
+
+  /**
+   * Loads the ADS with the provided context.  If there are certificates to
+   * be accepted we prompt them to the user.  If there are errors loading the
+   * servers we display them to the user and we ask for confirmation.  If the
+   * provided ctx is not using Global Administrator credentials, we prompt the
+   * user to provide them and update the provide ReplicationUserData
+   * accordingly.
+   * @param ctx the Ldap context to be used.
+   * @param uData the ReplicationUserData to be udpated.
+   * @param isFirstOrSourceServer whether this is the first server in the
+   * enable replication subcommand or the source server in the initialize server
+   * subcommand.
+   * @return <CODE>true</CODE> if everything went fine and the user accepted
+   * all the certificates and confirmed everything.  Returns <CODE>false</CODE>
+   * if a critical error occurred or the user did not accept a certificate or
+   * any of the confirmation messages.
+   */
+  private boolean loadADSAndAcceptCertificates(InitialLdapContext ctx,
+      ReplicationUserData uData, boolean isFirstOrSourceServer)
+  {
+    boolean cancelled = false;
+    boolean triedWithUserProvidedAdmin = false;
+    String host = ConnectionUtils.getHostName(ctx);
+    int port = ConnectionUtils.getPort(ctx);
+    boolean isSSL = ConnectionUtils.isSSL(ctx);
+    boolean isStartTLS = ConnectionUtils.isStartTLS(ctx);
+    try
+    {
+      ADSContext adsContext = new ADSContext(ctx);
+      if (adsContext.hasAdminData())
+      {
+        TopologyCache cache = new TopologyCache(adsContext, getTrustManager());
+        boolean reloadTopology = true;
+        LinkedList<Message> exceptionMsgs = new LinkedList<Message>();
+        while (reloadTopology && !cancelled)
+        {
+          cache.reloadTopology();
+
+          reloadTopology = false;
+          exceptionMsgs.clear();
+
+          /* 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<TopologyCacheException> exceptions =
+            new HashSet<TopologyCacheException>();
+          Set<ServerDescriptor> servers = cache.getServers();
+          for (ServerDescriptor server : servers)
+          {
+            TopologyCacheException e = server.getLastException();
+            if (e != null)
+            {
+              exceptions.add(e);
+            }
+          }
+          /* Check the exceptions and see if we throw them or not. */
+          for (TopologyCacheException e : exceptions)
+          {
+            switch (e.getType())
+            {
+              case NOT_GLOBAL_ADMINISTRATOR:
+                printLineBreak();
+                printErrorMessage(INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get());
+                boolean connected = false;
+
+                String adminUid = uData.getAdminUid();
+                String adminPwd = uData.getAdminPwd();
+                while (!connected)
+                {
+                  if ((!triedWithUserProvidedAdmin) && (adminPwd == null))
+                  {
+                    adminUid = getValue(argParser.getAdministratorUID(),
+                        argParser.getDefaultAdministratorUID());
+                    adminPwd = argParser.getBindPasswordAdmin();
+                    triedWithUserProvidedAdmin = true;
+                  }
+                  if (adminPwd == null)
+                  {
+                    adminUid = askForAdministratorUID(
+                        argParser.getDefaultAdministratorUID());
+                    adminPwd = askForAdministratorPwd();
+                  }
+                  try
+                  {
+                    ctx.close();
+                  }
+                  catch (Throwable t)
+                  {
+                  }
+                  try
+                  {
+                    ctx = createContext(host, port, isSSL, isStartTLS,
+                        ADSContext.getAdministratorDN(adminUid), adminPwd,
+                        getTrustManager());
+                    adsContext = new ADSContext(ctx);
+                    cache = new TopologyCache(adsContext, getTrustManager());
+                  }
+                  catch (Throwable t)
+                  {
+                    printLineBreak();
+                    printErrorMessage(
+                        ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+                        host+":"+port));
+                    LOG.log(Level.WARNING, "Complete error stack:", t);
+                    printLineBreak();
+                  }
+                }
+                uData.setAdminUid(adminUid);
+                uData.setAdminPwd(adminPwd);
+                if (uData instanceof EnableReplicationUserData)
+                {
+                  EnableReplicationUserData enableData =
+                    (EnableReplicationUserData)uData;
+                  if (isFirstOrSourceServer)
+                  {
+                    enableData.setBindDn1(
+                        ADSContext.getAdministratorDN(adminUid));
+                    enableData.setPwd1(adminPwd);
+                  }
+                  else
+                  {
+                    enableData.setBindDn2(
+                        ADSContext.getAdministratorDN(adminUid));
+                    enableData.setPwd2(adminPwd);
+                  }
+                }
+                reloadTopology = true;
+              break;
+            case GENERIC_CREATING_CONNECTION:
+              if ((e.getCause() != null) &&
+                  Utils.isCertificateException(e.getCause()))
+              {
+                reloadTopology = true;
+                cancelled = !promptForCertificateConfirmation(e.getCause(),
+                      getTrustManager(), e.getLdapUrl());
+              }
+              else
+              {
+                exceptionMsgs.add(Utils.getMessage(e));
+              }
+              break;
+            default:
+              exceptionMsgs.add(Utils.getMessage(e));
+            }
+          }
+        }
+        if ((exceptionMsgs.size() > 0) && !cancelled)
+        {
+          cancelled = !confirm(
+              ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.
+              get(Utils.getMessageFromCollection(exceptionMsgs,
+                    Constants.LINE_SEPARATOR).toString()));
+        }
+      }
+    }
+    catch (ADSContextException ace)
+    {
+      printLineBreak();
+      printErrorMessage(Utils.getThrowableMsg(INFO_BUG_MSG.get(), ace));
+
+      LOG.log(Level.SEVERE, "Complete error stack:", ace);
+      cancelled = true;
+    }
+    catch (TopologyCacheException tce)
+    {
+      printLineBreak();
+      printErrorMessage(Utils.getMessage(tce));
+
+      LOG.log(Level.SEVERE, "Complete error stack:", tce);
+      cancelled = true;
+    }
+    return !cancelled;
+  }
+
+  /**
+   * Tells whether there is a Global Administrator defined in the server
+   * to which the InitialLdapContext is connected.
+   * @param ctx the InitialLdapContext.
+   * @return <CODE>true</CODE> if we could find an administrator and
+   * <CODE>false</CODE> otherwise.
+   */
+  private boolean hasAdministrator(InitialLdapContext ctx)
+  {
+    boolean isAdminDefined = false;
+    try
+    {
+      ADSContext adsContext = new ADSContext(ctx);
+      if (adsContext.hasAdminData())
+      {
+        Set administrators = adsContext.readAdministratorRegistry();
+        isAdminDefined = administrators.size() > 0;
+      }
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.WARNING,
+          "Unexpected error retrieving the ADS data: "+t, t);
+    }
+    return isAdminDefined;
+  }
+
+  /**
+   * Returns a Collection containing a list of suffixes that are defined in
+   * two servers at the same time (depending on the value of the argument
+   * replicated this list contains only the suffixes that are replicated
+   * between the servers or the list of suffixes that are not replicated
+   * between the servers).
+   * @param ctx1 the connection to the first server.
+   * @param ctx2 the connection to the second server.
+   * @param type whether to return a list with the suffixes that are
+   * replicated, fully replicated (replicas have exactly the same list of
+   * replication servers), not replicated or all the common suffixes.
+   * @return a Collection containing a list of suffixes that are replicated
+   * (or those that can be replicated) in two servers.
+   */
+  private enum SuffixRelationType
+  {
+    NOT_REPLICATED, FULLY_REPLICATED, REPLICATED, NOT_FULLY_REPLICATED, ALL
+  };
+  private Collection<String> getCommonSuffixes(
+      InitialLdapContext ctx1, InitialLdapContext ctx2, SuffixRelationType type)
+  {
+    LinkedList<String> suffixes = new LinkedList<String>();
+    try
+    {
+      ServerDescriptor server1 = ServerDescriptor.createStandalone(ctx1);
+      ServerDescriptor server2 = ServerDescriptor.createStandalone(ctx2);
+      Set<ReplicaDescriptor> replicas1 = server1.getReplicas();
+      Set<ReplicaDescriptor> replicas2 = server2.getReplicas();
+
+      for (ReplicaDescriptor rep1 : replicas1)
+      {
+        for (ReplicaDescriptor rep2 : replicas2)
+        {
+          switch (type)
+          {
+          case NOT_REPLICATED:
+            if (!areReplicated(rep1, rep2))
+            {
+              suffixes.add(rep1.getSuffix().getDN());
+            }
+            break;
+          case FULLY_REPLICATED:
+            if (areFullyReplicated(rep1, rep2))
+            {
+              suffixes.add(rep1.getSuffix().getDN());
+            }
+            break;
+          case REPLICATED:
+            if (areReplicated(rep1, rep2))
+            {
+              suffixes.add(rep1.getSuffix().getDN());
+            }
+            break;
+          case NOT_FULLY_REPLICATED:
+            if (!areFullyReplicated(rep1, rep2))
+            {
+              suffixes.add(rep1.getSuffix().getDN());
+            }
+            break;
+          case ALL:
+            if (Utils.areDnsEqual(rep1.getSuffix().getDN(),
+                rep2.getSuffix().getDN()))
+            {
+              suffixes.add(rep1.getSuffix().getDN());
+            }
+            break;
+            default:
+              throw new IllegalStateException("Unknown type: "+type);
+          }
+        }
+      }
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.WARNING,
+          "Unexpected error retrieving the server configuration: "+t, t);
+    }
+    return suffixes;
+  }
+
+  /**
+   * Tells whether the two provided replicas are fully replicated or not.  The
+   * code in fact checks that both replicas have the same DN that they are
+   * replicated if both servers are replication servers and that both replicas
+   * make reference to the other replication server.
+   * @param rep1 the first replica.
+   * @param rep2 the second replica.
+   * @return <CODE>true</CODE> if we can assure that the two replicas are
+   * replicated using the replication server and replication port information
+   * and <CODE>false</CODE> otherwise.
+   */
+  private boolean areFullyReplicated(ReplicaDescriptor rep1,
+      ReplicaDescriptor rep2)
+  {
+    boolean areFullyReplicated = false;
+    if (Utils.areDnsEqual(rep1.getSuffix().getDN(), rep2.getSuffix().getDN()) &&
+        rep1.isReplicated() && rep2.isReplicated() &&
+        rep1.getServer().isReplicationServer() &&
+        rep2.getServer().isReplicationServer())
+    {
+     Set<String> servers1 = rep1.getReplicationServers();
+     Set<String> servers2 = rep2.getReplicationServers();
+     String server1 = rep1.getServer().getReplicationServerHostPort();
+     String server2 = rep2.getServer().getReplicationServerHostPort();
+     areFullyReplicated = servers1.contains(server2) &&
+     servers2.contains(server1);
+    }
+    return areFullyReplicated;
+  }
+
+  /**
+   * Tells whether the two provided replicas are replicated or not.  The
+   * code in fact checks that both replicas have the same DN and that they
+   * have at least one common replication server referenced.
+   * @param rep1 the first replica.
+   * @param rep2 the second replica.
+   * @return <CODE>true</CODE> if we can assure that the two replicas are
+   * replicated and <CODE>false</CODE> otherwise.
+   */
+  private boolean areReplicated(ReplicaDescriptor rep1, ReplicaDescriptor rep2)
+  {
+    boolean areReplicated = false;
+    if (Utils.areDnsEqual(rep1.getSuffix().getDN(), rep2.getSuffix().getDN()) &&
+        rep1.isReplicated() && rep2.isReplicated())
+    {
+      Set<String> servers1 = rep1.getReplicationServers();
+      Set<String> servers2 = rep2.getReplicationServers();
+      servers1.retainAll(servers2);
+      areReplicated = !servers1.isEmpty();
+    }
+    return areReplicated;
+  }
+
+  /**
+   * Returns a Collection containing a list of replicas in a server.
+   * @param ctx the connection to the server.
+   * @return a Collection containing a list of replicas in a server.
+   */
+  private Collection<ReplicaDescriptor> getReplicas(InitialLdapContext ctx)
+  {
+    LinkedList<ReplicaDescriptor> suffixes =
+      new LinkedList<ReplicaDescriptor>();
+    try
+    {
+      ServerDescriptor server = ServerDescriptor.createStandalone(ctx);
+      suffixes.addAll(server.getReplicas());
+    }
+    catch (Throwable t)
+    {
+      LOG.log(Level.WARNING,
+          "Unexpected error retrieving the server configuration: "+t, t);
+    }
+    return suffixes;
+  }
+
+  /**
+   * Enables the replication between two servers using the parameters in the
+   * provided EnableReplicationUserData.  This method does not prompt to the
+   * user for information if something is missing.
+   * @param uData the EnableReplicationUserData object.
+   * @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
+   * successful.
+   * and the replication could be enabled and an error code otherwise.
+   */
+  private ReplicationCliReturnCode enableReplication(
+      EnableReplicationUserData uData)
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    InitialLdapContext ctx1 = null;
+    InitialLdapContext ctx2 = null;
+    printProgressMessage(
+        formatter.getFormattedWithPoints(INFO_REPLICATION_CONNECTING.get()));
+    try
+    {
+      ctx1 = createContext(uData.getHostName1(), uData.getPort1(),
+          uData.useSSL1(), uData.useStartTLS1(), uData.getBindDn1(),
+          uData.getPwd1(), getTrustManager());
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = uData.getHostName1()+":"+uData.getPort1();
+      printLineBreak();
+      printErrorMessage(getMessageForException(ne, hostPort));
+
+      LOG.log(Level.SEVERE, "Complete error stack:", ne);
+    }
+    try
+    {
+      ctx2 = createContext(uData.getHostName2(), uData.getPort2(),
+          uData.useSSL2(), uData.useStartTLS2(), uData.getBindDn2(),
+          uData.getPwd2(), getTrustManager());
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = uData.getHostName2()+":"+uData.getPort2();
+      printLineBreak();
+      printErrorMessage(getMessageForException(ne, hostPort));
+
+      LOG.log(Level.SEVERE, "Complete error stack:", ne);
+    }
+    if ((ctx1 != null) && (ctx2 != null))
+    {
+      // This done is for the message informing that we are connecting.
+      printProgressMessage(formatter.getFormattedDone());
+      printProgressMessage(formatter.getLineBreak());
+      LinkedList<String> suffixes = uData.getBaseDNs();
+      checkSuffixesForEnableReplication(suffixes, ctx1, ctx2, false);
+      if (!suffixes.isEmpty())
+      {
+        uData.setBaseDNs(suffixes);
+        try
+        {
+          updateConfiguration(ctx1, ctx2, uData);
+          returnValue = SUCCESSFUL;
+        }
+        catch (ReplicationCliException rce)
+        {
+          returnValue = rce.getErrorCode();
+          printLineBreak();
+          printErrorMessage(rce.getMessageObject());
+          LOG.log(Level.SEVERE, "Complete error stack:", rce);
+        }
+      }
+      else
+      {
+        // The error messages are already displayed in the method
+        // checkSuffixesForEnableReplication.
+        returnValue = REPLICATION_CANNOT_BE_ENABLED_ON_BASEDN;
+      }
+    }
+    else
+    {
+      returnValue = ERROR_CONNECTING;
+    }
+
+    if (ctx1 != null)
+    {
+      try
+      {
+        ctx1.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+
+    if (ctx2 != null)
+    {
+      try
+      {
+        ctx2.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Disbles the replication in the server for the provided suffixes using the
+   * data in the DisableReplicationUserData object.  This method does not prompt
+   * to the user for information if something is missing.
+   * @param uData the DisableReplicationUserData object.
+   * @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
+   * successful.
+   * and the replication could be enabled and an error code otherwise.
+   */
+  private ReplicationCliReturnCode disableReplication(
+      DisableReplicationUserData uData)
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    InitialLdapContext ctx = null;
+    printProgressMessage(
+        formatter.getFormattedWithPoints(INFO_REPLICATION_CONNECTING.get()));
+    try
+    {
+      ctx = createContext(uData.getHostName(), uData.getPort(),
+          uData.useSSL(), uData.useStartTLS(),
+          ADSContext.getAdministratorDN(uData.getAdminUid()),
+          uData.getAdminPwd(), getTrustManager());
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = uData.getHostName()+":"+uData.getPort();
+      printLineBreak();
+      printErrorMessage(getMessageForException(ne, hostPort));
+      LOG.log(Level.SEVERE, "Complete error stack:", ne);
+    }
+
+    if (ctx != null)
+    {
+      // This done is for the message informing that we are connecting.
+      printProgressMessage(formatter.getFormattedDone());
+      printProgressMessage(formatter.getLineBreak());
+      LinkedList<String> suffixes = uData.getBaseDNs();
+      checkSuffixesForDisableReplication(suffixes, ctx, false);
+      if (!suffixes.isEmpty())
+      {
+        uData.setBaseDNs(suffixes);
+        try
+        {
+          updateConfiguration(ctx, uData);
+          returnValue = SUCCESSFUL;
+        }
+        catch (ReplicationCliException rce)
+        {
+          returnValue = rce.getErrorCode();
+          printLineBreak();
+          printErrorMessage(rce.getMessageObject());
+          LOG.log(Level.SEVERE, "Complete error stack:", rce);
+        }
+      }
+      else
+      {
+        returnValue = REPLICATION_CANNOT_BE_DISABLED_ON_BASEDN;
+      }
+    }
+    else
+    {
+      returnValue = ERROR_CONNECTING;
+    }
+
+    if (ctx != null)
+    {
+      try
+      {
+        ctx.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Initializes the contents of one server with the contents of the other
+   * using the parameters in the provided InitializeReplicationUserData.
+   * This method does not prompt to the user for information if something is
+   * missing.
+   * @param uData the InitializeReplicationUserData object.
+   * @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
+   * successful.
+   * and the replication could be enabled and an error code otherwise.
+   */
+  private ReplicationCliReturnCode initializeReplication(
+      InitializeReplicationUserData uData)
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    InitialLdapContext ctxSource = null;
+    InitialLdapContext ctxDestination = null;
+    try
+    {
+      ctxSource = createContext(uData.getHostNameSource(),
+          uData.getPortSource(), uData.useSSLSource(),
+          uData.useStartTLSSource(),
+          ADSContext.getAdministratorDN(uData.getAdminUid()),
+          uData.getAdminPwd(), getTrustManager());
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = uData.getHostNameSource()+":"+uData.getPortSource();
+      printLineBreak();
+      printErrorMessage(getMessageForException(ne, hostPort));
+      LOG.log(Level.SEVERE, "Complete error stack:", ne);
+    }
+    try
+    {
+      ctxDestination = createContext(uData.getHostNameDestination(),
+          uData.getPortDestination(), uData.useSSLDestination(),
+          uData.useStartTLSDestination(),
+          ADSContext.getAdministratorDN(uData.getAdminUid()),
+          uData.getAdminPwd(), getTrustManager());
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = uData.getHostNameDestination()+":"+
+      uData.getPortDestination();
+      printLineBreak();
+      printErrorMessage(getMessageForException(ne, hostPort));
+      LOG.log(Level.SEVERE, "Complete error stack:", ne);
+    }
+    if ((ctxSource != null) && (ctxDestination != null))
+    {
+      LinkedList<String> baseDNs = uData.getBaseDNs();
+      checkSuffixesForInitializeReplication(baseDNs, ctxSource, ctxDestination,
+          false);
+      if (!baseDNs.isEmpty())
+      {
+        for (String baseDN : baseDNs)
+        {
+          try
+          {
+            Message msg = formatter.getFormattedProgress(
+                INFO_PROGRESS_INITIALIZING_SUFFIX.get(baseDN,
+                    ConnectionUtils.getHostPort(ctxDestination)));
+            printProgressMessage(msg);
+            printProgressLineBreak();
+            initializeSuffix(baseDN, ctxSource, ctxDestination, true);
+          }
+          catch (ReplicationCliException rce)
+          {
+            printLineBreak();
+            printErrorMessage(rce.getMessageObject());
+            returnValue = rce.getErrorCode();
+            LOG.log(Level.SEVERE, "Complete error stack:", rce);
+          }
+        }
+      }
+      else
+      {
+        returnValue = REPLICATION_CANNOT_BE_INITIALIZED_ON_BASEDN;
+      }
+    }
+    else
+    {
+      returnValue = ERROR_CONNECTING;
+    }
+
+    if (ctxSource != null)
+    {
+      try
+      {
+        ctxSource.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+
+    if (ctxDestination != null)
+    {
+      try
+      {
+        ctxDestination.close();
+      }
+      catch (Throwable t)
+      {
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Checks that replication can actually be enabled in the provided baseDNs
+   * for the two servers.
+   * @param suffixes the suffixes provided by the user.  This Collection is
+   * updated by removing the base DNs that cannot be enabled and with the
+   * base DNs that the user provided interactively.
+   * @param ctx1 connection to the first server.
+   * @param ctx2 connection to the second server.
+   * @param interactive whether to ask the user to provide interactively
+   * base DNs if none of the provided base DNs can be enabled.
+   */
+  private void checkSuffixesForEnableReplication(Collection<String> suffixes,
+      InitialLdapContext ctx1, InitialLdapContext ctx2,
+      boolean interactive)
+  {
+    boolean cancelled = false;
+
+    TreeSet<String> availableSuffixes =
+      new TreeSet<String>(getCommonSuffixes(ctx1, ctx2,
+          SuffixRelationType.NOT_FULLY_REPLICATED));
+    TreeSet<String> alreadyReplicatedSuffixes =
+      new TreeSet<String>(getCommonSuffixes(ctx1, ctx2,
+          SuffixRelationType.FULLY_REPLICATED));
+
+    if (availableSuffixes.size() == 0)
+    {
+      printLineBreak();
+      printErrorMessage(
+          ERR_NO_SUFFIXES_AVAILABLE_TO_ENABLE_REPLICATION.get());
+
+      LinkedList<String> userProvidedSuffixes = argParser.getBaseDNs();
+      TreeSet<String> userProvidedReplicatedSuffixes = new TreeSet<String>();
+
+      for (String s1 : userProvidedSuffixes)
+      {
+        for (String s2 : alreadyReplicatedSuffixes)
+        {
+          if (Utils.areDnsEqual(s1, s2))
+          {
+            userProvidedReplicatedSuffixes.add(s1);
+          }
+        }
+      }
+      if (userProvidedReplicatedSuffixes.size() > 0)
+      {
+        printErrorMessage(
+            INFO_ALREADY_REPLICATED_SUFFIXES.get(
+                Utils.getStringFromCollection(userProvidedReplicatedSuffixes,
+                    Constants.LINE_SEPARATOR)));
+      }
+      cancelled = true;
+    }
+
+    //  Verify that the provided suffixes are configured in the servers.
+    if (!cancelled)
+    {
+      TreeSet<String> notFound = new TreeSet<String>();
+      TreeSet<String> alreadyReplicated = new TreeSet<String>();
+      for (String dn : suffixes)
+      {
+        boolean found = false;
+        for (String dn1 : availableSuffixes)
+        {
+          if (Utils.areDnsEqual(dn, dn1))
+          {
+            found = true;
+            break;
+          }
+        }
+        if (!found)
+        {
+          boolean isReplicated = false;
+          for (String s : alreadyReplicatedSuffixes)
+          {
+            if (Utils.areDnsEqual(s, dn))
+            {
+              isReplicated = true;
+              break;
+            }
+          }
+          if (isReplicated)
+          {
+            alreadyReplicated.add(dn);
+          }
+          else
+          {
+            notFound.add(dn);
+          }
+        }
+      }
+      suffixes.removeAll(notFound);
+      suffixes.removeAll(alreadyReplicated);
+      if (notFound.size() > 0)
+      {
+        printLineBreak();
+        printErrorMessage(ERR_REPLICATION_ENABLE_SUFFIXES_NOT_FOUND.get(
+              Utils.getStringFromCollection(notFound,
+                  Constants.LINE_SEPARATOR)));
+      }
+      if (alreadyReplicated.size() > 0)
+      {
+        printLineBreak();
+        printErrorMessage(INFO_ALREADY_REPLICATED_SUFFIXES.get(
+            Utils.getStringFromCollection(alreadyReplicated,
+                Constants.LINE_SEPARATOR)));
+      }
+      if (interactive)
+      {
+        while (suffixes.isEmpty())
+        {
+          printLineBreak();
+          printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_REPLICATE.get());
+          for (String dn : availableSuffixes)
+          {
+            if (confirm(INFO_REPLICATION_ENABLE_SUFFIX_PROMPT.get(dn)))
+            {
+              suffixes.add(dn);
+            }
+          }
+        }
+      }
+      else if (suffixes.isEmpty())
+      {
+        cancelled = true;
+      }
+    }
+  }
+
+  /**
+   * Checks that replication can actually be disabled in the provided baseDNs
+   * for the server.
+   * @param suffixes the suffixes provided by the user.  This Collection is
+   * updated by removing the base DNs that cannot be enabled and with the
+   * base DNs that the user provided interactively.
+   * @param ctx connection to the server.
+   * @param interactive whether to ask the user to provide interactively
+   * base DNs if none of the provided base DNs can be disabled.
+   */
+  private void checkSuffixesForDisableReplication(Collection<String> suffixes,
+      InitialLdapContext ctx, boolean interactive)
+  {
+    boolean cancelled = false;
+
+    TreeSet<String> availableSuffixes = new TreeSet<String>();
+    TreeSet<String> notReplicatedSuffixes = new TreeSet<String>();
+
+    Collection<ReplicaDescriptor> replicas = getReplicas(ctx);
+    for (ReplicaDescriptor rep : replicas)
+    {
+      String dn = rep.getSuffix().getDN();
+      if (rep.isReplicated())
+      {
+        availableSuffixes.add(dn);
+      }
+      else
+      {
+        notReplicatedSuffixes.add(dn);
+      }
+    }
+    if (availableSuffixes.size() == 0)
+    {
+      printLineBreak();
+      printErrorMessage(
+          ERR_NO_SUFFIXES_AVAILABLE_TO_DISABLE_REPLICATION.get());
+      LinkedList<String> userProvidedSuffixes = argParser.getBaseDNs();
+      TreeSet<String> userProvidedNotReplicatedSuffixes =
+        new TreeSet<String>();
+      for (String s1 : userProvidedSuffixes)
+      {
+        for (String s2 : notReplicatedSuffixes)
+        {
+          if (Utils.areDnsEqual(s1, s2))
+          {
+            userProvidedNotReplicatedSuffixes.add(s1);
+          }
+        }
+      }
+      if (userProvidedNotReplicatedSuffixes.size() > 0)
+      {
+        printErrorMessage(
+            INFO_ALREADY_NOT_REPLICATED_SUFFIXES.get(
+                Utils.getStringFromCollection(
+                    userProvidedNotReplicatedSuffixes,
+                    Constants.LINE_SEPARATOR)));
+      }
+      cancelled = true;
+    }
+
+    if (!cancelled)
+    {
+      // Verify that the provided suffixes are configured in the servers.
+      TreeSet<String> notFound = new TreeSet<String>();
+      TreeSet<String> alreadyNotReplicated = new TreeSet<String>();
+      for (String dn : suffixes)
+      {
+        boolean found = false;
+        for (String dn1 : availableSuffixes)
+        {
+          if (Utils.areDnsEqual(dn, dn1))
+          {
+            found = true;
+            break;
+          }
+        }
+        if (!found)
+        {
+          boolean notReplicated = false;
+          for (String s : notReplicatedSuffixes)
+          {
+            if (Utils.areDnsEqual(s, dn))
+            {
+              notReplicated = true;
+              break;
+            }
+          }
+          if (notReplicated)
+          {
+            alreadyNotReplicated.add(dn);
+          }
+          else
+          {
+            notFound.add(dn);
+          }
+        }
+      }
+      suffixes.removeAll(notFound);
+      suffixes.removeAll(alreadyNotReplicated);
+      if (notFound.size() > 0)
+      {
+        printLineBreak();
+        printErrorMessage(ERR_REPLICATION_DISABLE_SUFFIXES_NOT_FOUND.get(
+                Utils.getStringFromCollection(notFound,
+                    Constants.LINE_SEPARATOR)));
+      }
+      if (alreadyNotReplicated.size() > 0)
+      {
+        printLineBreak();
+        printErrorMessage(INFO_ALREADY_NOT_REPLICATED_SUFFIXES.get(
+                Utils.getStringFromCollection(alreadyNotReplicated,
+                    Constants.LINE_SEPARATOR)));
+      }
+      if (interactive)
+      {
+        while (suffixes.isEmpty())
+        {
+          printLineBreak();
+          printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_DISABLE.get());
+          for (String dn : availableSuffixes)
+          {
+            if (confirm(INFO_REPLICATION_DISABLE_SUFFIX_PROMPT.get(dn)))
+            {
+              suffixes.add(dn);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Checks that we can initialize the provided baseDNs between the two servers.
+   * @param suffixes the suffixes provided by the user.  This Collection is
+   * updated by removing the base DNs that cannot be enabled and with the
+   * base DNs that the user provided interactively.
+   * @param ctxSource connection to the source server.
+   * @param ctxDestination connection to the destination server.
+   * @param interactive whether to ask the user to provide interactively
+   * base DNs if none of the provided base DNs can be initialized.
+   */
+  private void checkSuffixesForInitializeReplication(
+      Collection<String> suffixes, InitialLdapContext ctxSource,
+      InitialLdapContext ctxDestination, boolean interactive)
+  {
+    boolean cancelled = false;
+    TreeSet<String> availableSuffixes = new TreeSet<String>(
+        getCommonSuffixes(ctxSource, ctxDestination,
+            SuffixRelationType.REPLICATED));
+    if (availableSuffixes.size() == 0)
+    {
+      printLineBreak();
+      printErrorMessage(
+          ERR_NO_SUFFIXES_AVAILABLE_TO_INITIALIZE_REPLICATION.get());
+      cancelled = true;
+    }
+
+    if (!cancelled)
+    {
+      // Verify that the provided suffixes are configured in the servers.
+      LinkedList<String> notFound = new LinkedList<String>();
+      for (String dn : suffixes)
+      {
+        boolean found = false;
+        for (String dn1 : availableSuffixes)
+        {
+          if (Utils.areDnsEqual(dn, dn1))
+          {
+            found = true;
+            break;
+          }
+        }
+        if (!found)
+        {
+          notFound.add(dn);
+        }
+      }
+      suffixes.removeAll(notFound);
+      if (notFound.size() > 0)
+      {
+        printLineBreak();
+        printErrorMessage(ERR_SUFFIXES_CANNOT_BE_INITIALIZED.get(
+                Utils.getStringFromCollection(notFound,
+                    Constants.LINE_SEPARATOR)));
+      }
+      if (interactive)
+      {
+        while (suffixes.isEmpty())
+        {
+          printLineBreak();
+          printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_INITIALIZE.get());
+          for (String dn : availableSuffixes)
+          {
+            if (confirm(INFO_REPLICATION_INITIALIZE_SUFFIX_PROMPT.get(dn)))
+            {
+              suffixes.add(dn);
+            }
+          }
+        }
+      }
+    }
+  }
+
+  /**
+   * Updates the configuration in the two servers (and in other servers if
+   * they are referenced) to enable replication.
+   * @param ctx1 the connection to the first server.
+   * @param ctx2 the connection to the second server.
+   * @param uData the EnableReplicationUserData object containing the required
+   * parameters to update the confgiuration.
+   * @throws ReplicationCliException if there is an error.
+   */
+  private void updateConfiguration(InitialLdapContext ctx1,
+      InitialLdapContext ctx2, EnableReplicationUserData uData)
+  throws ReplicationCliException
+  {
+    LinkedHashSet<String> twoReplServers = new LinkedHashSet<String>();
+    LinkedHashSet<String> allRepServers = new LinkedHashSet<String>();
+    HashMap<String, LinkedHashSet<String>> hmRepServers =
+      new HashMap<String, LinkedHashSet<String>>();
+    Set<Integer> usedReplicationServerIds = new HashSet<Integer>();
+    HashMap<String, HashSet<Integer>> hmUsedReplicationDomainIds =
+      new HashMap<String, HashSet<Integer>>();
+
+    ServerDescriptor server1;
+    try
+    {
+      server1 = ServerDescriptor.createStandalone(ctx1);
+    }
+    catch (NamingException ne)
+    {
+      throw new ReplicationCliException(
+          getMessageForException(ne, ConnectionUtils.getHostPort(ctx1)),
+          ERROR_READING_CONFIGURATION, ne);
+    }
+    ServerDescriptor server2;
+    try
+    {
+      server2 = ServerDescriptor.createStandalone(ctx2);
+    }
+    catch (NamingException ne)
+    {
+      throw new ReplicationCliException(
+          getMessageForException(ne, ConnectionUtils.getHostPort(ctx2)),
+          ERROR_READING_CONFIGURATION, ne);
+    }
+
+    ADSContext adsCtx1 = new ADSContext(ctx1);
+    ADSContext adsCtx2 = new ADSContext(ctx2);
+
+    // These are used to identify which server we use to initialize
+    // the contents of the other server (if any).
+    InitialLdapContext ctxAdsSource = null;
+    InitialLdapContext ctxAdsDestination = null;
+
+    printProgressMessage(formatter.getFormattedWithPoints(
+        INFO_REPLICATION_ENABLE_UPDATING_ADS_CONTENTS.get()));
+    try
+    {
+      if (adsCtx1.hasAdminData() && adsCtx2.hasAdminData())
+      {
+        Set<Map<ADSContext.ServerProperty, Object>> registry1 =
+          adsCtx1.readServerRegistry();
+        Set<Map<ADSContext.ServerProperty, Object>> registry2 =
+          adsCtx2.readServerRegistry();
+        if (registry2.size() <= 1)
+        {
+          // Only the server itself registered.
+          if (!hasAdministrator(adsCtx1.getDirContext()))
+          {
+            adsCtx1.createAdministrator(getAdministratorProperties(uData));
+          }
+          if (registry2.size() == 0)
+          {
+            server2.updateAdsPropertiesWithServerProperties();
+            adsCtx1.registerServer(server2.getAdsProperties());
+          }
+          else
+          {
+            adsCtx1.registerServer(registry2.iterator().next());
+          }
+
+          ctxAdsSource = ctx1;
+          ctxAdsDestination = ctx2;
+        }
+        else if (registry1.size() <= 1)
+        {
+          // Only the server itself registered.
+          if (!hasAdministrator(adsCtx2.getDirContext()))
+          {
+            adsCtx2.createAdministrator(getAdministratorProperties(uData));
+          }
+          if (registry1.size() == 0)
+          {
+            server1.updateAdsPropertiesWithServerProperties();
+            adsCtx2.registerServer(server1.getAdsProperties());
+          }
+          else
+          {
+            adsCtx2.registerServer(registry1.iterator().next());
+          }
+
+          ctxAdsSource = ctx2;
+          ctxAdsDestination = ctx1;
+        }
+        else if (!registry1.equals(registry2))
+        {
+          // TO COMPLETE: we may want to merge the ADS but for the moment
+          // just say this is not supported.
+          throw new ReplicationCliException(
+              ERR_REPLICATION_ADS_MERGE_NOT_SUPPORTED.get(
+                  ConnectionUtils.getHostPort(ctx1),
+                  ConnectionUtils.getHostPort(ctx2)),
+                  REPLICATION_ADS_MERGE_NOT_SUPPORTED, null);
+        }
+        else
+        {
+          // They are already replicated: nothing to do in terms of ADS
+          // initialization or ADS update data
+        }
+      }
+      else if (!adsCtx1.hasAdminData() && adsCtx2.hasAdminData())
+      {
+        adsCtx1.createAdministrationSuffix(null);
+        if (!hasAdministrator(adsCtx2.getDirContext()))
+        {
+          adsCtx2.createAdministrator(getAdministratorProperties(uData));
+        }
+        server1.updateAdsPropertiesWithServerProperties();
+        adsCtx2.registerServer(server1.getAdsProperties());
+
+        ctxAdsSource = ctx2;
+        ctxAdsDestination = ctx1;
+      }
+      else if (adsCtx1.hasAdminData() && !adsCtx2.hasAdminData())
+      {
+        adsCtx2.createAdministrationSuffix(null);
+        if (!hasAdministrator(adsCtx1.getDirContext()))
+        {
+          adsCtx1.createAdministrator(getAdministratorProperties(uData));
+        }
+        server2.updateAdsPropertiesWithServerProperties();
+        adsCtx1.registerServer(server2.getAdsProperties());
+
+        ctxAdsSource = ctx1;
+        ctxAdsDestination = ctx2;
+      }
+      else
+      {
+        adsCtx1.createAdminData(null);
+        adsCtx1.createAdministrator(getAdministratorProperties(uData));
+        server1.updateAdsPropertiesWithServerProperties();
+        adsCtx1.registerServer(server1.getAdsProperties());
+        server2.updateAdsPropertiesWithServerProperties();
+        adsCtx1.registerServer(server2.getAdsProperties());
+        adsCtx2.createAdministrationSuffix(null);
+
+        ctxAdsSource = ctx1;
+        ctxAdsDestination = ctx2;
+      }
+    }
+    catch (ADSContextException adce)
+    {
+      throw new ReplicationCliException(
+          ERR_REPLICATION_UPDATING_ADS.get(adce.getMessage()),
+          ERROR_UPDATING_ADS, adce);
+    }
+    printProgressMessage(formatter.getFormattedDone());
+    printProgressMessage(formatter.getLineBreak());
+
+    LinkedList<String> baseDNs = uData.getBaseDNs();
+    boolean found = false;
+    for (String dn : baseDNs)
+    {
+      if (Utils.areDnsEqual(dn, ADSContext.getAdministrationSuffixDN()))
+      {
+        found = true;
+        break;
+      }
+    }
+    if (!found)
+    {
+      baseDNs.add(ADSContext.getAdministrationSuffixDN());
+      uData.setBaseDNs(baseDNs);
+    }
+
+    TopologyCache cache1 = null;
+    TopologyCache cache2 = null;
+    try
+    {
+      if (adsCtx1.hasAdminData())
+      {
+        cache1 = new TopologyCache(adsCtx1, getTrustManager());
+        cache1.reloadTopology();
+        usedReplicationServerIds.addAll(getReplicationServerIds(cache1));
+      }
+
+      if (adsCtx2.hasAdminData())
+      {
+        cache2 = new TopologyCache(adsCtx2, getTrustManager());
+        cache2.reloadTopology();
+        usedReplicationServerIds.addAll(getReplicationServerIds(cache2));
+      }
+    }
+    catch (ADSContextException adce)
+    {
+      throw new ReplicationCliException(
+          ERR_REPLICATION_READING_ADS.get(adce.getMessage()),
+          ERROR_READING_ADS, adce);
+    }
+    catch (TopologyCacheException tce)
+    {
+      throw new ReplicationCliException(
+          ERR_REPLICATION_READING_ADS.get(tce.getMessage()),
+          ERROR_READING_TOPOLOGY_CACHE, tce);
+    }
+
+    if (!argParser.isInteractive())
+    {
+      // Inform the user of the potential errors that we found.
+      LinkedHashSet<Message> messages = new LinkedHashSet<Message>();
+      if (cache1 != null)
+      {
+        messages.addAll(getErrorMessages(cache1));
+      }
+      if (cache2 != null)
+      {
+        messages.addAll(getErrorMessages(cache2));
+      }
+      if (!messages.isEmpty())
+      {
+        printWarningMessage(
+            ERR_REPLICATION_READING_REGISTERED_SERVERS_WARNING.get(
+                Utils.getMessageFromCollection(messages,
+                    Constants.LINE_SEPARATOR).toString()));
+      }
+    }
+
+    if (server1.isReplicationServer())
+    {
+      twoReplServers.add(server1.getReplicationServerHostPort());
+      usedReplicationServerIds.add(server1.getReplicationServerId());
+    }
+    else
+    {
+      twoReplServers.add(
+          ConnectionUtils.getHostName(ctx1)+":"+uData.getReplicationPort1());
+    }
+    if (server2.isReplicationServer())
+    {
+      twoReplServers.add(server2.getReplicationServerHostPort());
+      usedReplicationServerIds.add(server2.getReplicationServerId());
+    }
+    else
+    {
+      twoReplServers.add(
+          ConnectionUtils.getHostName(ctx2)+":"+uData.getReplicationPort2());
+    }
+
+    for (String baseDN : uData.getBaseDNs())
+    {
+      LinkedHashSet<String> repServersForBaseDN = new LinkedHashSet<String>();
+      repServersForBaseDN.addAll(getReplicationServers(baseDN, cache1,
+          server1));
+      repServersForBaseDN.addAll(getReplicationServers(baseDN, cache2,
+          server2));
+      repServersForBaseDN.addAll(twoReplServers);
+      hmRepServers.put(baseDN, repServersForBaseDN);
+
+      Set<Integer> ids = new HashSet<Integer>();
+      ids.addAll(getReplicationDomainIds(baseDN, server1));
+      ids.addAll(getReplicationDomainIds(baseDN, server2));
+      if (cache1 != null)
+      {
+        for (ServerDescriptor server : cache1.getServers())
+        {
+          ids.addAll(getReplicationDomainIds(baseDN, server));
+        }
+      }
+      if (cache2 != null)
+      {
+        for (ServerDescriptor server : cache2.getServers())
+        {
+          ids.addAll(getReplicationDomainIds(baseDN, server));
+        }
+      }
+    }
+    for (LinkedHashSet<String> v : hmRepServers.values())
+    {
+      allRepServers.addAll(v);
+    }
+
+    if (!server1.isReplicationServer())
+    {
+      try
+      {
+        configureAsReplicationServer(ctx1, uData.getReplicationPort1(),
+          allRepServers, usedReplicationServerIds);
+      }
+      catch (OpenDsException ode)
+      {
+        throw new ReplicationCliException(
+            getMessageForReplicationServerException(ode,
+            ConnectionUtils.getHostPort(ctx1)),
+            ERROR_CONFIGURING_REPLICATIONSERVER, ode);
+      }
+    }
+    if (!server2.isReplicationServer())
+    {
+      try
+      {
+        configureAsReplicationServer(ctx2, uData.getReplicationPort2(),
+            allRepServers, usedReplicationServerIds);
+      }
+      catch (OpenDsException ode)
+      {
+        throw new ReplicationCliException(
+            getMessageForReplicationServerException(ode,
+            ConnectionUtils.getHostPort(ctx1)),
+            ERROR_CONFIGURING_REPLICATIONSERVER, ode);
+      }
+    }
+
+    for (String baseDN : uData.getBaseDNs())
+    {
+      LinkedHashSet<String> repServers = hmRepServers.get(baseDN);
+      Set<Integer> usedIds = hmUsedReplicationDomainIds.get(baseDN);
+      Set<String> alreadyConfiguredServers = new HashSet<String>();
+
+      try
+      {
+        configureToReplicateBaseDN(ctx1, baseDN, repServers, usedIds);
+      }
+      catch (OpenDsException ode)
+      {
+        Message msg = getMessageForEnableException(ode,
+            ConnectionUtils.getHostPort(ctx1), baseDN);
+        throw new ReplicationCliException(msg,
+            ERROR_ENABLING_REPLICATION_ON_BASEDN, ode);
+      }
+      alreadyConfiguredServers.add(server1.getId());
+      try
+      {
+        configureToReplicateBaseDN(ctx2, baseDN, repServers, usedIds);
+      }
+      catch (OpenDsException ode)
+      {
+        Message msg = getMessageForEnableException(ode,
+            ConnectionUtils.getHostPort(ctx2), baseDN);
+        throw new ReplicationCliException(msg,
+            ERROR_ENABLING_REPLICATION_ON_BASEDN, ode);
+      }
+      alreadyConfiguredServers.add(server2.getId());
+
+      if (cache1 != null)
+      {
+        configureToReplicateBaseDN(baseDN, repServers, usedIds, cache1, server1,
+            alreadyConfiguredServers);
+      }
+      if (cache2 != null)
+      {
+        configureToReplicateBaseDN(baseDN, repServers, usedIds, cache2, server2,
+            alreadyConfiguredServers);
+      }
+    }
+
+    // Now that replication is configured in all servers, simply try to
+    // initialize the contents of one ADS with the other (in the case where
+    // already both servers were replicating the same ADS there is nothing to be
+    // done).
+    if ((ctxAdsSource != null) && (ctxAdsDestination != null))
+    {
+      printProgressMessage(formatter.getFormattedWithPoints(
+          INFO_ENABLE_REPLICATION_INITIALIZING_ADS.get(
+              ConnectionUtils.getHostPort(ctxAdsDestination),
+              ConnectionUtils.getHostPort(ctxAdsSource))));
+
+      initializeSuffix(ADSContext.getAdministrationSuffixDN(), ctxAdsSource,
+          ctxAdsDestination, false);
+      printProgressMessage(formatter.getFormattedDone());
+      printProgressMessage(formatter.getLineBreak());
+    }
+  }
+
+  /**
+   * Updates the configuration in the server (and in other servers if
+   * they are referenced) to disable replication.
+   * @param ctx the connection to the server.
+   * @param uData the DisableReplicationUserData object containing the required
+   * parameters to update the confgiuration.
+   * @throws ReplicationCliException if there is an error.
+   */
+  private void updateConfiguration(InitialLdapContext ctx,
+      DisableReplicationUserData uData) throws ReplicationCliException
+  {
+    ServerDescriptor server;
+    try
+    {
+      server = ServerDescriptor.createStandalone(ctx);
+    }
+    catch (NamingException ne)
+    {
+      throw new ReplicationCliException(
+          getMessageForException(ne, ConnectionUtils.getHostPort(ctx)),
+          ERROR_READING_CONFIGURATION, ne);
+    }
+
+    ADSContext adsCtx = new ADSContext(ctx);
+
+    TopologyCache cache = null;
+    try
+    {
+      if (adsCtx.hasAdminData())
+      {
+        cache = new TopologyCache(adsCtx, getTrustManager());
+        cache.reloadTopology();
+      }
+    }
+    catch (ADSContextException adce)
+    {
+      throw new ReplicationCliException(
+          ERR_REPLICATION_READING_ADS.get(adce.getMessage()),
+          ERROR_READING_ADS, adce);
+    }
+    catch (TopologyCacheException tce)
+    {
+      throw new ReplicationCliException(
+          ERR_REPLICATION_READING_ADS.get(tce.getMessage()),
+          ERROR_READING_TOPOLOGY_CACHE, tce);
+    }
+    if (!argParser.isInteractive())
+    {
+      // Inform the user of the potential errors that we found.
+      LinkedHashSet<Message> messages = new LinkedHashSet<Message>();
+      if (cache != null)
+      {
+        messages.addAll(getErrorMessages(cache));
+      }
+      if (!messages.isEmpty())
+      {
+        printWarningMessage(
+            ERR_REPLICATION_READING_REGISTERED_SERVERS_WARNING.get(
+                Utils.getMessageFromCollection(messages,
+                    Constants.LINE_SEPARATOR).toString()));
+      }
+    }
+
+    String replicationServerHostPort = server.getReplicationServerHostPort();
+    for (String baseDN : uData.getBaseDNs())
+    {
+      try
+      {
+        deleteReplicationDomain(ctx, baseDN);
+      }
+      catch (OpenDsException ode)
+      {
+        Message msg = getMessageForDisableException(ode,
+            ConnectionUtils.getHostPort(ctx), baseDN);
+        throw new ReplicationCliException(msg,
+            ERROR_DISABLING_REPLICATION_ON_BASEDN, ode);
+      }
+    }
+
+    if ((replicationServerHostPort != null) && (cache != null))
+    {
+      Set<ServerDescriptor> serversToUpdate =
+        new LinkedHashSet<ServerDescriptor>();
+      for (String baseDN : uData.getBaseDNs())
+      {
+        SuffixDescriptor suffix = getSuffix(baseDN, cache, server);
+        if (suffix != null)
+        {
+          for (ReplicaDescriptor replica : suffix.getReplicas())
+          {
+            serversToUpdate.add(replica.getServer());
+          }
+        }
+      }
+      String bindDn = ConnectionUtils.getBindDN(ctx);
+      String pwd = ConnectionUtils.getBindPassword(ctx);
+      for (ServerDescriptor s : serversToUpdate)
+      {
+        removeReferencesInServer(s, replicationServerHostPort, bindDn, pwd,
+            uData.getBaseDNs());
+      }
+    }
+  }
+
+  /**
+   * Retrieves all the replication servers for a given baseDN.  The
+   * ServerDescriptor is used to identify the server where the suffix is
+   * defined and it cannot be null.  The TopologyCache is used to retrieve
+   * replication servers defined in other replicas but not in the one we
+   * get in the ServerDescriptor.
+   * @param baseDN the base DN.
+   * @param cache the TopologyCache (might be null).
+   * @param server the ServerDescriptor.
+   * @return a Set containing the replication servers currently being used
+   * to replicate the baseDN defined in the server described by the
+   * ServerDescriptor.
+   */
+  private LinkedHashSet<String> getReplicationServers(String baseDN,
+      TopologyCache cache, ServerDescriptor server)
+  {
+    LinkedHashSet<String> servers = new LinkedHashSet<String>();
+    for (ReplicaDescriptor replica : server.getReplicas())
+    {
+      if (Utils.areDnsEqual(replica.getSuffix().getDN(), baseDN))
+      {
+        servers.addAll(replica.getReplicationServers());
+        break;
+      }
+    }
+    if (cache != null)
+    {
+      Set<SuffixDescriptor> suffixes = cache.getSuffixes();
+      for (SuffixDescriptor suffix : suffixes)
+      {
+        if (Utils.areDnsEqual(suffix.getDN(), baseDN))
+        {
+          Set<String> s = suffix.getReplicationServers();
+          // Test that at least we share one of the replication servers.
+          // If we do: we are dealing with the same replication topology
+          // (we must consider the case of disjoint replication topologies
+          // replicating the same base DN).
+          HashSet<String> copy = new HashSet<String>(s);
+          copy.retainAll(servers);
+          if (!copy.isEmpty())
+          {
+            servers.addAll(s);
+            break;
+          }
+        }
+      }
+    }
+    return servers;
+  }
+
+  /**
+   * Retrieves the suffix in the TopologyCache for a given baseDN.  The
+   * ServerDescriptor is used to identify the server where the suffix is
+   * defined.
+   * @param baseDN the base DN.
+   * @param cache the TopologyCache.
+   * @param server the ServerDescriptor.
+   * @return the suffix in the TopologyCache for a given baseDN.
+   */
+  private SuffixDescriptor getSuffix(String baseDN, TopologyCache cache,
+      ServerDescriptor server)
+  {
+    SuffixDescriptor returnValue = null;
+    Set<String> servers = new LinkedHashSet<String>();
+    for (ReplicaDescriptor replica : server.getReplicas())
+    {
+      if (Utils.areDnsEqual(replica.getSuffix().getDN(), baseDN))
+      {
+        servers.addAll(replica.getReplicationServers());
+        break;
+      }
+    }
+
+    Set<SuffixDescriptor> suffixes = cache.getSuffixes();
+    for (SuffixDescriptor suffix : suffixes)
+    {
+      if (Utils.areDnsEqual(suffix.getDN(), baseDN))
+      {
+        Set<String> s = suffix.getReplicationServers();
+        // Test that at least we share one of the replication servers.
+        // If we do: we are dealing with the same replication topology
+        // (we must consider the case of disjoint replication topologies
+        // replicating the same base DN).
+        HashSet<String> copy = new HashSet<String>(s);
+        copy.retainAll(servers);
+        if (!copy.isEmpty())
+        {
+          returnValue = suffix;
+          break;
+        }
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Retrieves all the replication domain IDs for a given baseDN in the
+   * ServerDescriptor.
+   * @param baseDN the base DN.
+   * @param server the ServerDescriptor.
+   * @return a Set containing the replication domain IDs for a given baseDN in
+   * the ServerDescriptor.
+   */
+  private Set<Integer> getReplicationDomainIds(String baseDN,
+      ServerDescriptor server)
+  {
+    Set<Integer> ids = new HashSet<Integer>();
+    for (ReplicaDescriptor replica : server.getReplicas())
+    {
+      if ((replica.isReplicated()) &&
+      Utils.areDnsEqual(replica.getSuffix().getDN(), baseDN))
+      {
+        ids.add(replica.getReplicationId());
+        break;
+      }
+    }
+    return ids;
+  }
+
+  /**
+   * Configures the server to which the provided InitialLdapContext is connected
+   * as a replication server.  The replication server listens in the provided
+   * port.
+   * @param ctx the context connected to the server that we want to configure.
+   * @param replicationPort the replication port of the replication server.
+   * @param replicationServers the list of replication servers to which the
+   * replication server will communicate with.
+   * @param usedReplicationServerIds the set of replication server IDs that
+   * are already in use.  The set will be updated with the replication ID
+   * that will be used by the newly configured replication server.
+   * @throws OpenDsException if there is an error updating the configuration.
+   */
+  private void configureAsReplicationServer(InitialLdapContext ctx,
+      int replicationPort, LinkedHashSet<String> replicationServers,
+      Set<Integer> usedReplicationServerIds) throws OpenDsException
+  {
+    printProgressMessage(formatter.getFormattedWithPoints(
+        INFO_REPLICATION_ENABLE_CONFIGURING_REPLICATION_SERVER.get(
+            ConnectionUtils.getHostPort(ctx))));
+
+    ManagementContext mCtx = LDAPManagementContext.createFromContext(
+        JNDIDirContextAdaptor.adapt(ctx));
+    RootCfgClient root = mCtx.getRootConfiguration();
+
+    /*
+     * Configure Synchronization plugin.
+     */
+    MultimasterSynchronizationProviderCfgClient sync = null;
+    try
+    {
+      sync = (MultimasterSynchronizationProviderCfgClient)
+      root.getSynchronizationProvider("Multimaster Synchronization");
+    }
+    catch (ManagedObjectNotFoundException monfe)
+    {
+      LOG.log(Level.INFO, "Synchronization server does not exist in "+
+          ConnectionUtils.getHostPort(ctx));
+    }
+    if (sync == null)
+    {
+      MultimasterSynchronizationProviderCfgDefn provider =
+        MultimasterSynchronizationProviderCfgDefn.getInstance();
+      sync = root.createSynchronizationProvider(provider,
+          "Multimaster Synchronization",
+          new ArrayList<DefaultBehaviorException>());
+      sync.setJavaImplementationClass(
+          org.opends.server.replication.plugin.MultimasterReplication.class.
+          getName());
+      sync.setEnabled(Boolean.TRUE);
+    }
+    else
+    {
+      if (!sync.isEnabled())
+      {
+        sync.setEnabled(Boolean.TRUE);
+      }
+    }
+    sync.commit();
+
+    /*
+     * Configure the replication server.
+     */
+    ReplicationServerCfgClient replicationServer = null;
+
+    boolean mustCommit = false;
+
+    if (!sync.hasReplicationServer())
+    {
+      int id = InstallerHelper.getReplicationId(usedReplicationServerIds);
+      usedReplicationServerIds.add(id);
+      replicationServer = sync.createReplicationServer(
+          ReplicationServerCfgDefn.getInstance(),
+          new ArrayList<DefaultBehaviorException>());
+      replicationServer.setReplicationServerId(id);
+      replicationServer.setReplicationPort(replicationPort);
+      replicationServer.setReplicationServer(replicationServers);
+      mustCommit = true;
+    }
+    else
+    {
+      replicationServer = sync.getReplicationServer();
+      usedReplicationServerIds.add(
+          replicationServer.getReplicationServerId());
+      Set<String> servers = replicationServer.getReplicationServer();
+      if (servers == null)
+      {
+        replicationServer.setReplicationServer(servers);
+        mustCommit = true;
+      }
+      else if (!servers.equals(replicationServers))
+      {
+        replicationServers.addAll(servers);
+        replicationServer.setReplicationServer(replicationServers);
+        mustCommit = true;
+      }
+    }
+    if (mustCommit)
+    {
+      replicationServer.commit();
+    }
+
+    printProgressMessage(formatter.getFormattedDone());
+    printProgressMessage(formatter.getLineBreak());
+  }
+
+  /**
+   * Returns a Set containing all the replication server ids found in the
+   * servers of a given TopologyCache object.
+   * @param cache the TopologyCache object to use.
+   * @return a Set containing all the replication server ids found in a given
+   * TopologyCache object.
+   */
+  private Set<Integer> getReplicationServerIds(TopologyCache cache)
+  {
+    Set<Integer> ids = new HashSet<Integer>();
+    for (ServerDescriptor server : cache.getServers())
+    {
+      if (server.isReplicationServer())
+      {
+        ids.add(server.getReplicationServerId());
+      }
+    }
+    return ids;
+  }
+
+  /**
+   * Configures a replication domain for a given base DN in the server to which
+   * the provided InitialLdapContext is connected.
+   * @param ctx the context connected to the server that we want to configure.
+   * @param baseDN the base DN of the replication domain to configure.
+   * @param replicationServers the list of replication servers to which the
+   * replication domain will communicate with.
+   * @param usedReplicationDomainIds the set of replication domain IDs that
+   * are already in use.  The set will be updated with the replication ID
+   * that will be used by the newly configured replication server.
+   * @throws OpenDsException if there is an error updating the configuration.
+   */
+  private void configureToReplicateBaseDN(InitialLdapContext ctx,
+      String baseDN,
+      LinkedHashSet<String> replicationServers,
+      Set<Integer> usedReplicationDomainIds) throws OpenDsException
+  {
+    printProgressMessage(formatter.getFormattedWithPoints(
+        INFO_REPLICATION_ENABLE_CONFIGURING_BASEDN.get(baseDN,
+            ConnectionUtils.getHostPort(ctx))));
+
+    ManagementContext mCtx = LDAPManagementContext.createFromContext(
+        JNDIDirContextAdaptor.adapt(ctx));
+    RootCfgClient root = mCtx.getRootConfiguration();
+
+    MultimasterSynchronizationProviderCfgClient sync =
+      (MultimasterSynchronizationProviderCfgClient)
+      root.getSynchronizationProvider("Multimaster Synchronization");
+
+    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]);
+    }
+    MultimasterDomainCfgClient domain = null;
+    String domainName = null;
+    for (int i=0; i<domains.length && (domain == null); i++)
+    {
+      if (Utils.areDnsEqual(baseDN, domains[i].getReplicationDN().toString()))
+      {
+        domain = domains[i];
+        domainName = domainNames[i];
+      }
+    }
+    boolean mustCommit = false;
+    if (domain == null)
+    {
+      int domainId = InstallerHelper.getReplicationId(usedReplicationDomainIds);
+      usedReplicationDomainIds.add(domainId);
+      domainName = InstallerHelper.getDomainName(domainNames, domainId);
+      domain = sync.createMultimasterDomain(
+          MultimasterDomainCfgDefn.getInstance(), domainName,
+          new ArrayList<DefaultBehaviorException>());
+      domain.setServerId(domainId);
+      domain.setReplicationDN(DN.decode(baseDN));
+      domain.setReplicationServer(replicationServers);
+      mustCommit = true;
+    }
+    else
+    {
+      Set<String> servers = domain.getReplicationServer();
+      if (servers == null)
+      {
+        domain.setReplicationServer(servers);
+        mustCommit = true;
+      }
+      else if (!servers.equals(replicationServers))
+      {
+        replicationServers.addAll(servers);
+        domain.setReplicationServer(replicationServers);
+        mustCommit = true;
+      }
+    }
+
+    if (mustCommit)
+    {
+      domain.commit();
+    }
+
+    printProgressMessage(formatter.getFormattedDone());
+    printProgressMessage(formatter.getLineBreak());
+  }
+
+  /**
+   * Configures the baseDN to replicate in all the Replicas found in a Topology
+   * Cache that are replicated with the Replica of the same base DN in the
+   * provided ServerDescriptor object.
+   * @param baseDN the base DN to replicate.
+   * @param repServers the replication servers to be defined in the domain.
+   * @param usedIds the replication domain Ids already used.  This Set is
+   * updated with the new domains that are used.
+   * @param cache the TopologyCache used to retrieve the different defined
+   * replicas.
+   * @param server the ServerDescriptor that is used to identify the
+   * replication topology that we are interested at (we only update the replicas
+   * that are already replicated with this server).
+   * @param alreadyConfiguredServers the list of already configured servers.  If
+   * a server is in this list no updates are performed.
+   * @throws ReplicationCliException if something goes wrong.
+   */
+  private void configureToReplicateBaseDN(String baseDN,
+      LinkedHashSet<String> repServers, Set<Integer> usedIds,
+      TopologyCache cache, ServerDescriptor server,
+      Set<String>alreadyConfiguredServers) throws ReplicationCliException
+  {
+    SuffixDescriptor suffix = getSuffix(baseDN, cache, server);
+    if (suffix != null)
+    {
+      for (ReplicaDescriptor replica: suffix.getReplicas())
+      {
+        ServerDescriptor s = replica.getServer();
+        if (!alreadyConfiguredServers.contains(s.getId()))
+        {
+          String dn = ConnectionUtils.getBindDN(
+              cache.getAdsContext().getDirContext());
+          String pwd = ConnectionUtils.getBindPassword(
+              cache.getAdsContext().getDirContext());
+
+          ServerLoader loader = new ServerLoader(server.getAdsProperties(),
+              dn, pwd, getTrustManager());
+          InitialLdapContext ctx = null;
+          try
+          {
+            ctx = loader.createContext();
+            configureToReplicateBaseDN(ctx, baseDN, repServers, usedIds);
+          }
+          catch (NamingException ne)
+          {
+            String hostPort = server.getHostPort(true);
+            Message msg = getMessageForException(ne, hostPort);
+            throw new ReplicationCliException(msg, ERROR_CONNECTING, ne);
+          }
+          catch (OpenDsException ode)
+          {
+            String hostPort = server.getHostPort(true);
+            Message msg = getMessageForEnableException(ode, hostPort, baseDN);
+            throw new ReplicationCliException(msg,
+                ERROR_ENABLING_REPLICATION_ON_BASEDN, ode);
+          }
+          finally
+          {
+            if (ctx != null)
+            {
+              try
+              {
+                ctx.close();
+              }
+              catch (Throwable t)
+              {
+              }
+            }
+          }
+          alreadyConfiguredServers.add(s.getId());
+        }
+      }
+    }
+  }
+
+  /**
+   * Returns the Map of properties to be used to update the ADS.
+   * This map uses the data provided by the user.
+   * @return the Map of properties to be used to update the ADS.
+   * This map uses the data provided by the user
+   */
+  private Map<ADSContext.AdministratorProperty, Object>
+  getAdministratorProperties(ReplicationUserData uData)
+  {
+    Map<ADSContext.AdministratorProperty, Object> adminProperties =
+      new HashMap<ADSContext.AdministratorProperty, Object>();
+    adminProperties.put(ADSContext.AdministratorProperty.UID,
+        uData.getAdminUid());
+    adminProperties.put(ADSContext.AdministratorProperty.PASSWORD,
+        uData.getAdminPwd());
+    adminProperties.put(ADSContext.AdministratorProperty.DESCRIPTION,
+        INFO_GLOBAL_ADMINISTRATOR_DESCRIPTION.get().toString());
+    return adminProperties;
+  }
+
+  private void initializeSuffix(String baseDN, InitialLdapContext ctxSource,
+      InitialLdapContext ctxDestination, boolean displayProgress)
+  throws ReplicationCliException
+  {
+    int replicationId = -1;
+    try
+    {
+      ServerDescriptor source = ServerDescriptor.createStandalone(
+          ctxSource);
+      for (ReplicaDescriptor replica : source.getReplicas())
+      {
+        if (Utils.areDnsEqual(replica.getSuffix().getDN(), baseDN))
+        {
+          replicationId = replica.getReplicationId();
+          break;
+        }
+      }
+    }
+    catch (NamingException ne)
+    {
+      String hostPort = ConnectionUtils.getHostPort(ctxSource);
+      Message msg = getMessageForException(ne, hostPort);
+      throw new ReplicationCliException(msg, ERROR_READING_CONFIGURATION, ne);
+    }
+
+    if (replicationId == -1)
+    {
+      throw new ReplicationCliException(
+          ERR_INITIALIZING_REPLICATIONID_NOT_FOUND.get(
+              ConnectionUtils.getHostPort(ctxSource), baseDN),
+          REPLICATIONID_NOT_FOUND, null);
+    }
+
+    OfflineInstaller installer = new OfflineInstaller();
+    installer.setProgressMessageFormatter(formatter);
+    installer.addProgressUpdateListener(new ProgressUpdateListener()
+    {
+      public void progressUpdate(ProgressUpdateEvent ev)
+      {
+        Message newLogDetails = ev.getNewLogs();
+        if (newLogDetails != null)
+        {
+          printProgressMessage(newLogDetails);
+          printProgressLineBreak();
+        }
+      }
+    });
+    int nTries = 5;
+    boolean initDone = false;
+    while (!initDone)
+    {
+      try
+      {
+        installer.initializeSuffix(ctxDestination, replicationId, baseDN,
+            displayProgress, ConnectionUtils.getHostPort(ctxSource));
+        initDone = true;
+      }
+      catch (PeerNotFoundException pnfe)
+      {
+        LOG.log(Level.INFO, "Peer could not be found");
+        if (nTries == 1)
+        {
+          throw new ReplicationCliException(
+              ERR_REPLICATION_INITIALIZING_TRIES_COMPLETED.get(
+                  pnfe.getMessageObject().toString()),
+              INITIALIZING_TRIES_COMPLETED, pnfe);
+        }
+        try
+        {
+          Thread.sleep((5 - nTries) * 3000);
+        }
+        catch (Throwable t)
+        {
+        }
+      }
+      catch (ApplicationException ae)
+      {
+        throw new ReplicationCliException(ae.getMessageObject(),
+            ERROR_INITIALIZING_BASEDN_GENERIC, ae);
+      }
+      nTries--;
+    }
+  }
+
+  /**
+   * Returns a set of error messages encountered in the provided TopologyCache.
+   * @param cache the topology cache.
+   * @return a set of error messages encountered in the provided TopologyCache.
+   */
+  private LinkedHashSet<Message> getErrorMessages(TopologyCache cache)
+  {
+    Set<TopologyCacheException> exceptions =
+      new HashSet<TopologyCacheException>();
+    Set<ServerDescriptor> servers = cache.getServers();
+    LinkedHashSet<Message> exceptionMsgs = new LinkedHashSet<Message>();
+    for (ServerDescriptor server : servers)
+    {
+      TopologyCacheException e = server.getLastException();
+      if (e != null)
+      {
+        exceptions.add(e);
+      }
+    }
+    /* Check the exceptions and see if we throw them or not. */
+    for (TopologyCacheException e : exceptions)
+    {
+      switch (e.getType())
+      {
+        case NOT_GLOBAL_ADMINISTRATOR:
+          exceptionMsgs.add(INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get());
+
+        break;
+      case GENERIC_CREATING_CONNECTION:
+        if ((e.getCause() != null) &&
+            Utils.isCertificateException(e.getCause()))
+        {
+          exceptionMsgs.add(
+              INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(
+              e.getHostPort(), e.getCause().getMessage()));
+        }
+        else
+        {
+          exceptionMsgs.add(Utils.getMessage(e));
+        }
+        break;
+      default:
+        exceptionMsgs.add(Utils.getMessage(e));
+      }
+    }
+    return exceptionMsgs;
+  }
+
+  /**
+   * Removes the references to a replication server in the base DNs of a
+   * given server.
+   * @param server the server that we want to update.
+   * @param replicationServer the replication server whose references we want
+   * to remove.
+   * @param bindDn the bindDn that must be used to log to the server.
+   * @param pwd the password that must be used to log to the server.
+   * @param baseDNs the list of base DNs where we want to remove the references
+   * to the provided replication server.
+   * @throws ReplicationCliException if there is an error updating the
+   * configuration.
+   */
+  private void removeReferencesInServer(ServerDescriptor server,
+      String replicationServer, String bindDn, String pwd,
+      Collection<String> baseDNs)
+  throws ReplicationCliException
+  {
+    ServerLoader loader = new ServerLoader(server.getAdsProperties(), bindDn,
+        pwd, getTrustManager());
+    InitialLdapContext ctx = null;
+    String lastBaseDN = null;
+    String hostPort = null;
+    try
+    {
+      ctx = loader.createContext();
+      hostPort = ConnectionUtils.getHostPort(ctx);
+      ManagementContext mCtx = LDAPManagementContext.createFromContext(
+          JNDIDirContextAdaptor.adapt(ctx));
+      RootCfgClient root = mCtx.getRootConfiguration();
+      MultimasterSynchronizationProviderCfgClient sync = null;
+      try
+      {
+        sync = (MultimasterSynchronizationProviderCfgClient)
+        root.getSynchronizationProvider("Multimaster Synchronization");
+      }
+      catch (ManagedObjectNotFoundException monfe)
+      {
+        // It does not exist.
+        LOG.log(Level.INFO, "No synchronization found on "+ hostPort +".",
+            monfe);
+      }
+      if (sync != null)
+      {
+        String[] domainNames = sync.listMultimasterDomains();
+        if (domainNames != null)
+        {
+          for (int i=0; i<domainNames.length; i++)
+          {
+            MultimasterDomainCfgClient domain =
+              sync.getMultimasterDomain(domainNames[i]);
+            for (String baseDN : baseDNs)
+            {
+              lastBaseDN = baseDN;
+              if (Utils.areDnsEqual(domain.getReplicationDN().toString(),
+                  baseDN))
+              {
+                printProgressMessage(formatter.getFormattedWithPoints(
+                    INFO_REPLICATION_REMOVING_REFERENCES_ON_REMOTE.get(baseDN,
+                        hostPort)));
+                Set<String> replServers = domain.getReplicationServer();
+                if (replServers != null)
+                {
+                  String replServer = null;
+                  for (String o : replServers)
+                  {
+                    if (replicationServer.equalsIgnoreCase(o))
+                    {
+                      replServer = o;
+                      break;
+                    }
+                  }
+                  if (replServer != null)
+                  {
+                    LOG.log(Level.INFO, "Updating references in domain " +
+                        domain.getReplicationDN()+" on " + hostPort + ".");
+                    replServers.remove(replServer);
+                    if (replServers.size() > 0)
+                    {
+                      domain.setReplicationServer(replServers);
+                      domain.commit();
+                    }
+                    else
+                    {
+                      sync.removeMultimasterDomain(domainNames[i]);
+                      sync.commit();
+                    }
+                  }
+                }
+                printProgressMessage(formatter.getFormattedDone());
+                printProgressMessage(formatter.getLineBreak());
+              }
+            }
+          }
+        }
+      }
+    }
+    catch (NamingException ne)
+    {
+      hostPort = server.getHostPort(true);
+      Message msg = getMessageForException(ne, hostPort);
+      throw new ReplicationCliException(msg, ERROR_CONNECTING, ne);
+    }
+    catch (OpenDsException ode)
+    {
+      if (lastBaseDN != null)
+      {
+        Message msg = getMessageForDisableException(ode, hostPort, lastBaseDN);
+        throw new ReplicationCliException(msg,
+          ERROR_DISABLING_REPLICATION_REMOVE_REFERENCE_ON_BASEDN, ode);
+      }
+      else
+      {
+        Message msg = ERR_REPLICATION_ERROR_READING_CONFIGURATION.get(hostPort,
+            ode.getMessage());
+        throw new ReplicationCliException(msg, ERROR_CONNECTING, ode);
+      }
+    }
+    finally
+    {
+      if (ctx != null)
+      {
+        try
+        {
+          ctx.close();
+        }
+        catch (Throwable t)
+        {
+        }
+      }
+    }
+  }
+
+  /**
+   * Deletes a replication domain in a server for a given base DN (disable
+   * replication of the base DN).
+   * @param ctx the connection to the server.
+   * @param baseDN the base DN of the replication domain that we want to
+   * delete.
+   * @throws ReplicationCliException if there is an error updating the
+   * configuration of the server.
+   */
+  private void deleteReplicationDomain(InitialLdapContext ctx,
+      String baseDN) throws ReplicationCliException
+  {
+    String hostPort = ConnectionUtils.getHostPort(ctx);
+    try
+    {
+      ManagementContext mCtx = LDAPManagementContext.createFromContext(
+          JNDIDirContextAdaptor.adapt(ctx));
+      RootCfgClient root = mCtx.getRootConfiguration();
+      MultimasterSynchronizationProviderCfgClient sync = null;
+      try
+      {
+        sync = (MultimasterSynchronizationProviderCfgClient)
+        root.getSynchronizationProvider("Multimaster Synchronization");
+      }
+      catch (ManagedObjectNotFoundException monfe)
+      {
+        // It does not exist.
+        LOG.log(Level.INFO, "No synchronization found on "+ hostPort +".",
+            monfe);
+      }
+      if (sync != null)
+      {
+        String[] domainNames = sync.listMultimasterDomains();
+        if (domainNames != null)
+        {
+          for (int i=0; i<domainNames.length; i++)
+          {
+            MultimasterDomainCfgClient domain =
+              sync.getMultimasterDomain(domainNames[i]);
+            if (Utils.areDnsEqual(domain.getReplicationDN().toString(), baseDN))
+            {
+              printProgressMessage(formatter.getFormattedWithPoints(
+                  INFO_REPLICATION_DISABLING_BASEDN.get(baseDN,
+                      hostPort)));
+              sync.removeMultimasterDomain(domainNames[i]);
+              sync.commit();
+
+              printProgressMessage(formatter.getFormattedDone());
+              printProgressMessage(formatter.getLineBreak());
+            }
+          }
+        }
+      }
+    }
+    catch (OpenDsException ode)
+    {
+      Message msg = getMessageForDisableException(ode, hostPort, baseDN);
+        throw new ReplicationCliException(msg,
+          ERROR_DISABLING_REPLICATION_REMOVE_REFERENCE_ON_BASEDN, ode);
+    }
+  }
+
+  /**
+   * Returns a message object for the given NamingException.
+   * @param ne the NamingException.
+   * @param hostPort the hostPort representation of the server we were
+   * contacting when the NamingException occurred.
+   * @return a message object for the given NamingException.
+   */
+  private Message getMessageForException(NamingException ne, String hostPort)
+  {
+    Message msg;
+    if (Utils.isCertificateException(ne))
+    {
+      msg = INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(
+              hostPort, ne.getMessage());
+    }
+    else
+    {
+       msg = INFO_CANNOT_CONNECT_TO_REMOTE_GENERIC.get(
+          hostPort, ne.getMessage());
+    }
+    return msg;
+  }
+
+  /**
+   * Returns a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring the replication server.
+   * @param ode the OpenDsException.
+   * @param hostPort the hostPort representation of the server we were
+   * contacting when the OpenDsException occurred.
+   * @return a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring the replication server.
+   */
+  private Message getMessageForReplicationServerException(OpenDsException ode,
+      String hostPort)
+  {
+    return ERR_REPLICATION_CONFIGURING_REPLICATIONSERVER.get(hostPort);
+  }
+
+  /**
+   * Returns a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring some replication domain (creating
+   * the replication domain or updating the list of replication servers of
+   * the replication domain).
+   * @param ode the OpenDsException.
+   * @param hostPort the hostPort representation of the server we were
+   * contacting when the OpenDsException occurred.
+   * @return a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring some replication domain (creating
+   * the replication domain or updating the list of replication servers of
+   * the replication domain).
+   */
+  private Message getMessageForEnableException(OpenDsException ode,
+      String hostPort, String baseDN)
+  {
+    return ERR_REPLICATION_CONFIGURING_BASEDN.get(baseDN, hostPort);
+  }
+
+  /**
+   * Returns a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring some replication domain (deleting
+   * the replication domain or updating the list of replication servers of
+   * the replication domain).
+   * @param ode the OpenDsException.
+   * @param hostPort the hostPort representation of the server we were
+   * contacting when the OpenDsException occurred.
+   * @return a message for a given OpenDsException (we assume that was an
+   * exception generated updating the configuration of the server) that
+   * occurred when we were configuring some replication domain (deleting
+   * the replication domain or updating the list of replication servers of
+   * the replication domain).
+   */
+  private Message getMessageForDisableException(OpenDsException ode,
+      String hostPort, String baseDN)
+  {
+    return ERR_REPLICATION_CONFIGURING_BASEDN.get(baseDN, hostPort);
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java
new file mode 100644
index 0000000..a00fd16
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java
@@ -0,0 +1,1462 @@
+/*
+ * 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.guitools.replicationcli;
+
+import static org.opends.messages.AdminToolMessages.*;
+import static org.opends.messages.ToolMessages.*;
+import static org.opends.server.tools.ToolConstants.*;
+
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.LinkedList;
+
+import org.opends.messages.Message;
+import org.opends.messages.MessageBuilder;
+import org.opends.quicksetup.Constants;
+import org.opends.quicksetup.util.Utils;
+import org.opends.server.admin.client.cli.SecureConnectionCliParser;
+import org.opends.server.util.args.Argument;
+import org.opends.server.util.args.ArgumentException;
+import org.opends.server.util.args.BooleanArgument;
+import org.opends.server.util.args.FileBasedArgument;
+import org.opends.server.util.args.IntegerArgument;
+import org.opends.server.util.args.StringArgument;
+import org.opends.server.util.args.SubCommand;
+
+/**
+ * This class is used to parse the arguments passed to the replication CLI.
+ * It also checks the compatibility between the values and that all the
+ * required information has been provided.  However it does not do any
+ * verification that require connection to any server.
+ */
+public class ReplicationCliParser extends SecureConnectionCliParser
+{
+  private SubCommand enableReplicationSubCmd;
+  private SubCommand disableReplicationSubCmd;
+  private SubCommand initializeReplicationSubCmd;
+
+  private BooleanArgument interactive;
+
+  /**
+   * The 'hostName' global argument for the first server.
+   */
+  private StringArgument hostName1Arg = null;
+
+  /**
+   * The 'port' global argument for the first server.
+   */
+  private IntegerArgument port1Arg = null;
+
+  /**
+   * The 'binDN' global argument for the first server.
+   */
+  private StringArgument bindDn1Arg = null;
+
+  /**
+   * The 'bindPasswordFile' global argument for the first server.
+   */
+  private FileBasedArgument bindPasswordFile1Arg = null;
+
+  /**
+   * The 'bindPassword' global argument for the first server.
+   */
+  private StringArgument bindPassword1Arg = null;
+
+  /**
+   * The 'useSSLArg' argument for the first server.
+   */
+  protected BooleanArgument useSSL1Arg = null;
+
+  /**
+   * The 'useStartTLS1Arg' argument for the first server.
+   */
+  protected BooleanArgument useStartTLS1Arg = null;
+
+  /**
+   * The 'replicationPort' global argument for the first server.
+   */
+  private IntegerArgument replicationPort1Arg = null;
+
+  /**
+   * The 'hostName' global argument for the second server.
+   */
+  private StringArgument hostName2Arg = null;
+
+  /**
+   * The 'port' global argument for the second server.
+   */
+  private IntegerArgument port2Arg = null;
+
+  /**
+   * The 'binDN' global argument for the second server.
+   */
+  private StringArgument bindDn2Arg = null;
+
+  /**
+   * The 'bindPasswordFile' global argument for the second server.
+   */
+  private FileBasedArgument bindPasswordFile2Arg = null;
+
+  /**
+   * The 'bindPassword' global argument for the second server.
+   */
+  private StringArgument bindPassword2Arg = null;
+
+  /**
+   * The 'useSSLArg' argument for the second server.
+   */
+  protected BooleanArgument useSSL2Arg = null;
+
+  /**
+   * The 'useStartTLS2Arg' argument for the second server.
+   */
+  protected BooleanArgument useStartTLS2Arg = null;
+
+  /**
+   * The 'replicationPort' global argument for the second server.
+   */
+  private IntegerArgument replicationPort2Arg = null;
+
+  /**
+   * The 'hostName' global argument for the source server.
+   */
+  private StringArgument hostNameSourceArg = null;
+
+  /**
+   * The 'port' global argument for the source server.
+   */
+  private IntegerArgument portSourceArg = null;
+
+  /**
+   * The 'useSSLArg' argument for the source server.
+   */
+  protected BooleanArgument useSSLSourceArg = null;
+
+  /**
+   * The 'useStartTLSSourceArg' argument for the source server.
+   */
+  protected BooleanArgument useStartTLSSourceArg = null;
+
+  /**
+   * The 'hostName' global argument for the destination server.
+   */
+  private StringArgument hostNameDestinationArg = null;
+
+  /**
+   * The 'port' global argument for the destination server.
+   */
+  private IntegerArgument portDestinationArg = null;
+
+  /**
+   * The 'useSSLArg' argument for the destination server.
+   */
+  protected BooleanArgument useSSLDestinationArg = null;
+
+  /**
+   * The 'useStartTLSDestinationArg' argument for the destination server.
+   */
+  protected BooleanArgument useStartTLSDestinationArg = null;
+
+  /**
+   * The 'suffixes' global argument.
+   */
+  private StringArgument baseDNsArg = null;
+
+  /**
+   * The 'admin UID' global argument.
+   */
+  private StringArgument adminUidArg;
+
+  /**
+   * The 'admin Password' global argument.
+   */
+  private StringArgument adminPasswordArg;
+
+  /**
+   * The 'admin Password File' global argument.
+   */
+  private FileBasedArgument adminPasswordFileArg;
+
+  /**
+   * The 'quiet' argument.
+   */
+  private BooleanArgument quietArg;
+
+  /**
+   * The text of the enable replication subcommand.
+   */
+  public static final String ENABLE_REPLICATION_SUBCMD_NAME = "enable";
+
+  /**
+   * The text of the disable replication subcommand.
+   */
+  public static final String DISABLE_REPLICATION_SUBCMD_NAME = "disable";
+
+  /**
+   * The text of the initialize replication subcommand.
+   */
+  public static final String INITIALIZE_REPLICATION_SUBCMD_NAME = "initialize";
+
+  /**
+   * Creates a new instance of this argument parser with no arguments.
+   *
+   * @param mainClassName
+   *          The fully-qualified name of the Java class that should
+   *          be invoked to launch the program with which this
+   *          argument parser is associated.
+   */
+  public ReplicationCliParser(String mainClassName)
+  {
+    super(mainClassName,
+        INFO_REPLICATION_TOOL_DESCRIPTION.get(ENABLE_REPLICATION_SUBCMD_NAME,
+            INITIALIZE_REPLICATION_SUBCMD_NAME),
+            false);
+  }
+
+  /**
+   * Initialize the parser with the Global options and subcommands.
+   *
+   * @param outStream
+   *          The output stream to use for standard output, or <CODE>null</CODE>
+   *          if standard output is not needed.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used
+   *           to create this argument.
+   */
+  public void initializeParser(OutputStream outStream)
+      throws ArgumentException
+  {
+    initializeGlobalArguments(outStream);
+    createEnableReplicationSubCommand();
+    createDisableReplicationSubCommand();
+    createInitializeReplicationSubCommand();
+  }
+
+  /**
+   * Checks all the options parameters and updates the provided MessageBuilder
+   * with the errors that where encountered.
+   *
+   * This method assumes that the method parseArguments for the parser has
+   * already been called.
+   * @param buf the MessageBuilder object where we add the error messages
+   * describing the errors encountered.
+   */
+  public void validateOptions(MessageBuilder buf)
+  {
+    validateGlobalOptions(buf);
+    validateSubcommandOptions(buf);
+  }
+
+  /**
+   * {@inheritDoc}
+   */
+  public int validateGlobalOptions(MessageBuilder buf)
+  {
+    int returnValue;
+    super.validateGlobalOptions(buf);
+    ArrayList<Message> errors = new ArrayList<Message>();
+    if (adminPasswordArg.isPresent() && adminPasswordFileArg.isPresent()) {
+      Message message = ERR_TOOL_CONFLICTING_ARGS.get(
+          adminPasswordArg.getLongIdentifier(),
+          adminPasswordFileArg.getLongIdentifier());
+      errors.add(message);
+    }
+
+    if (!isInteractive())
+    {
+      // Check that we have the required data
+      if (!baseDNsArg.isPresent())
+      {
+        errors.add(ERR_REPLICATION_NO_BASE_DN_PROVIDED.get());
+      }
+      if (getBindPasswordAdmin() == null)
+      {
+        errors.add(ERR_REPLICATION_NO_ADMINISTRATOR_PASSWORD_PROVIDED.get(
+                adminPasswordArg.getLongIdentifier(),
+                adminPasswordFileArg.getLongIdentifier()));
+      }
+    }
+
+    if (baseDNsArg.isPresent())
+    {
+      LinkedList<String> baseDNs = baseDNsArg.getValues();
+      for (String dn : baseDNs)
+      {
+        if (!Utils.isDn(dn))
+        {
+          errors.add(ERR_REPLICATION_NOT_A_VALID_BASEDN.get(dn));
+        }
+      }
+    }
+    if (errors.size() > 0)
+    {
+      for (Message error : errors)
+      {
+        addMessage(buf, error);
+      }
+    }
+
+    if (buf.length() > 0)
+    {
+      returnValue = ReplicationCliReturnCode.CONFLICTING_ARGS.getReturnCode();
+    }
+    else
+    {
+      returnValue = ReplicationCliReturnCode.SUCCESSFUL_NOP.getReturnCode();
+    }
+    return returnValue;
+  }
+
+  /**
+   * Initialize Global option.
+   *
+   * @param outStream
+   *          The output stream used for the usage.
+   * @throws ArgumentException
+   *           If there is a problem with any of the parameters used
+   *           to create this argument.
+   */
+  private void initializeGlobalArguments(OutputStream outStream)
+  throws ArgumentException
+  {
+    ArrayList<Argument> defaultArgs =
+      new ArrayList<Argument>(createGlobalArguments(outStream));
+
+    Argument[] argsToRemove = {
+      hostNameArg,
+      portArg,
+      bindDnArg,
+      bindPasswordFileArg,
+      bindPasswordArg,
+      useSSLArg,
+      useStartTLSArg
+    };
+
+    for (int i=0; i<argsToRemove.length; i++)
+    {
+      defaultArgs.remove(argsToRemove[i]);
+    }
+
+    baseDNsArg = new StringArgument("baseDNs", 'b',
+        "baseDNs", false, true, true, OPTION_VALUE_BASEDN, null,
+        null, INFO_DESCRIPTION_REPLICATION_BASEDNS.get());
+    defaultArgs.add(baseDNsArg);
+
+    adminUidArg = new StringArgument("adminUID", 'I',
+        "adminUID", false, false, true, "adminUID",
+        Constants.GLOBAL_ADMIN_UID, null,
+        INFO_DESCRIPTION_REPLICATION_ADMIN_UID.get(
+            ENABLE_REPLICATION_SUBCMD_NAME));
+    defaultArgs.add(adminUidArg);
+
+    adminPasswordArg = new StringArgument("adminPassword",
+        OPTION_SHORT_BINDPWD, "adminPassword", false, false, true,
+        OPTION_VALUE_BINDPWD, null, null,
+        INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORD.get());
+    defaultArgs.add(adminPasswordArg);
+
+    adminPasswordFileArg = new FileBasedArgument("adminPasswordFile",
+        OPTION_SHORT_BINDPWD_FILE, "adminPasswordFile", false, false,
+        OPTION_VALUE_BINDPWD_FILE, null, null,
+        INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORDFILE.get());
+    defaultArgs.add(adminPasswordFileArg);
+
+    defaultArgs.remove(verboseArg);
+    interactive = new BooleanArgument(
+        INTERACTIVE_OPTION_LONG,
+        INTERACTIVE_OPTION_SHORT,
+        INTERACTIVE_OPTION_LONG,
+        INFO_DESCRIPTION_INTERACTIVE.get());
+    defaultArgs.add(interactive);
+
+    quietArg = new BooleanArgument(
+        SecureConnectionCliParser.QUIET_OPTION_LONG,
+        SecureConnectionCliParser.QUIET_OPTION_SHORT,
+        SecureConnectionCliParser.QUIET_OPTION_LONG,
+        INFO_REPLICATION_DESCRIPTION_QUIET.get());
+    defaultArgs.add(quietArg);
+    initializeGlobalArguments(defaultArgs);
+  }
+
+  /**
+   * Creates the enable replication subcommand and all the specific options
+   * for the subcommand.
+   */
+  private void createEnableReplicationSubCommand()
+  throws ArgumentException
+  {
+
+    hostName1Arg = new StringArgument("host1", 'h',
+        "host1", false, false, true, OPTION_VALUE_HOST, "localhost",
+        null, INFO_DESCRIPTION_ENABLE_REPLICATION_HOST1.get());
+
+    port1Arg = new IntegerArgument("port1", 'p', "port1",
+        false, false, true, OPTION_VALUE_PORT, 389, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_SERVER_PORT1.get());
+
+    bindDn1Arg = new StringArgument("bindDN1", 'D',
+        "bindDN1", false, false, true, OPTION_VALUE_BINDDN,
+        "cn=Directory Manager", null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDDN1.get());
+
+    bindPassword1Arg = new StringArgument("bindPassword1",
+        'w', "bindPassword1", false, false, true,
+        OPTION_VALUE_BINDPWD, null, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORD1.get());
+
+    bindPasswordFile1Arg = new FileBasedArgument("bindPasswordFile1",
+        'j', "bindPasswordFile1", false, false,
+        OPTION_VALUE_BINDPWD_FILE, null, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORDFILE1.get());
+
+    useSSL1Arg = new BooleanArgument("useSSL1", 'Z',
+        "useSSL1", INFO_DESCRIPTION_ENABLE_REPLICATION_USE_SSL1.get());
+
+    useStartTLS1Arg = new BooleanArgument("startTLS1", 'q',
+        "startTLS1",
+        INFO_DESCRIPTION_ENABLE_REPLICATION_STARTTLS1.get());
+
+    replicationPort1Arg = new IntegerArgument("replicationPort1", 'r',
+        "replicationPort1", false, false, true, OPTION_VALUE_PORT, 8989, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_PORT1.get());
+
+    hostName2Arg = new StringArgument("host2", 'H',
+        "host2", false, false, true, OPTION_VALUE_HOST, "localhost",
+        null, INFO_DESCRIPTION_ENABLE_REPLICATION_HOST2.get());
+
+    port2Arg = new IntegerArgument("port2", 'P', "port2",
+        false, false, true, OPTION_VALUE_PORT, 389, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_SERVER_PORT2.get());
+
+    bindDn2Arg = new StringArgument("bindDN2", 'N',
+        "bindDN2", false, false, true, OPTION_VALUE_BINDDN,
+        "cn=Directory Manager", null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDDN2.get());
+
+    bindPassword2Arg = new StringArgument("bindPassword2",
+        'W', "bindPassword2", false, false, true,
+        OPTION_VALUE_BINDPWD, null, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORD2.get());
+
+    bindPasswordFile2Arg = new FileBasedArgument("bindPasswordFile2",
+        'F', "bindPasswordFile2", false, false,
+        OPTION_VALUE_BINDPWD_FILE, null, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORDFILE2.get());
+
+    useSSL2Arg = new BooleanArgument("useSSL2", 'S',
+        "useSSL2", INFO_DESCRIPTION_ENABLE_REPLICATION_USE_SSL2.get());
+
+    useStartTLS2Arg = new BooleanArgument("startTLS2", 'Q',
+        "startTLS2",
+        INFO_DESCRIPTION_ENABLE_REPLICATION_STARTTLS2.get());
+
+    replicationPort2Arg = new IntegerArgument("replicationPort2", 'R',
+        "replicationPort2", false, false, true, OPTION_VALUE_PORT, 8989, null,
+        INFO_DESCRIPTION_ENABLE_REPLICATION_PORT2.get());
+
+    enableReplicationSubCmd = new SubCommand(this,
+        ENABLE_REPLICATION_SUBCMD_NAME,
+        INFO_DESCRIPTION_SUBCMD_ENABLE_REPLICATION.get());
+
+    Argument[] argsToAdd = {
+        hostName1Arg, port1Arg, bindDn1Arg, bindPassword1Arg,
+        bindPasswordFile1Arg, useStartTLS1Arg, useSSL1Arg, replicationPort1Arg,
+        hostName2Arg, port2Arg, bindDn2Arg, bindPassword2Arg,
+        bindPasswordFile2Arg, useStartTLS2Arg, useSSL2Arg, replicationPort2Arg,
+    };
+    for (int i=0; i<argsToAdd.length; i++)
+    {
+      enableReplicationSubCmd.addArgument(argsToAdd[i]);
+    }
+  }
+
+  /**
+   * Creates the disable replication subcommand and all the specific options
+   * for the subcommand.  Note: this method assumes that
+   * initializeGlobalArguments has already been called and that hostNameArg,
+   * portArg, startTLSArg and useSSLArg have been created.
+   */
+  private void createDisableReplicationSubCommand()
+  throws ArgumentException
+  {
+    disableReplicationSubCmd = new SubCommand(this,
+        DISABLE_REPLICATION_SUBCMD_NAME,
+        INFO_DESCRIPTION_SUBCMD_DISABLE_REPLICATION.get());
+
+    Argument[] argsToAdd = {
+        hostNameArg, portArg,
+        useSSLArg, useStartTLSArg
+    };
+    for (int i=0; i<argsToAdd.length; i++)
+    {
+      disableReplicationSubCmd.addArgument(argsToAdd[i]);
+    }
+  }
+
+  /**
+   * Creates the initialize replication subcommand and all the specific options
+   * for the subcommand.
+   */
+  private void createInitializeReplicationSubCommand()
+  throws ArgumentException
+  {
+    hostNameSourceArg = new StringArgument("hostSource", 'h',
+        "hostSource", false, false, true, OPTION_VALUE_HOST, "localhost",
+        null, INFO_DESCRIPTION_INITIALIZE_REPLICATION_HOST_SOURCE.get());
+
+    portSourceArg = new IntegerArgument("portSource", 'p', "portSource",
+        false, false, true, OPTION_VALUE_PORT, 389, null,
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_SERVER_PORT_SOURCE.get());
+
+    useSSLSourceArg = new BooleanArgument("useSSLSource", 'Z',
+        "useSSLSource",
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_USE_SSL_SOURCE.get());
+
+    useStartTLSSourceArg = new BooleanArgument("startTLSSource", 'q',
+        "startTLSSource",
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_STARTTLS_SOURCE.get());
+
+    hostNameDestinationArg = new StringArgument("hostDestination", 'H',
+        "hostDestination", false, false, true, OPTION_VALUE_HOST, "localhost",
+        null, INFO_DESCRIPTION_INITIALIZE_REPLICATION_HOST_DESTINATION.get());
+
+    portDestinationArg = new IntegerArgument("portDestination", 'P',
+        "portDestination", false, false, true, OPTION_VALUE_PORT, 389, null,
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_SERVER_PORT_DESTINATION.get());
+
+    useSSLDestinationArg = new BooleanArgument("useSSLDestination", 'S',
+        "useSSLDestination",
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_USE_SSL_DESTINATION.get());
+
+    useStartTLSDestinationArg = new BooleanArgument("startTLSDestination", 'Q',
+        "startTLSDestination",
+        INFO_DESCRIPTION_INITIALIZE_REPLICATION_STARTTLS_DESTINATION.get());
+
+    initializeReplicationSubCmd = new SubCommand(this,
+        INITIALIZE_REPLICATION_SUBCMD_NAME,
+        INFO_DESCRIPTION_SUBCMD_INITIALIZE_REPLICATION.get());
+
+    Argument[] argsToAdd = {
+        hostNameSourceArg, portSourceArg, useSSLSourceArg, useStartTLSSourceArg,
+        hostNameDestinationArg, portDestinationArg, useSSLDestinationArg,
+        useStartTLSDestinationArg
+    };
+    for (int i=0; i<argsToAdd.length; i++)
+    {
+      initializeReplicationSubCmd.addArgument(argsToAdd[i]);
+    }
+  }
+
+  /**
+   * Tells whether the user specified to have an interactive operation or not.
+   * This method must be called after calling parseArguments.
+   * @return <CODE>true</CODE> if the user specified to have an interactive
+   * operation and <CODE>false</CODE> otherwise.
+   */
+  public boolean isInteractive()
+  {
+    return interactive.isPresent();
+  }
+
+  /**
+   * Tells whether the user specified to have a quite operation or not.
+   * This method must be called after calling parseArguments.
+   * @return <CODE>true</CODE> if the user specified to have a quite operation
+   * and <CODE>false</CODE> otherwise.
+   */
+  public boolean isQuiet()
+  {
+    return quietArg.isPresent();
+  }
+
+  /**
+   * Get the password which has to be used for the command to connect to the
+   * first server without prompting the user in the enable replication
+   * subcommand.  If no password was specified return null.
+   *
+   * @return the password which has to be used for the command to connect to the
+   * first server without prompting the user in the enable replication
+   * subcommand.  If no password was specified return null.
+   */
+  public String getBindPassword1()
+  {
+    return getBindPassword(bindPassword1Arg, bindPasswordFile1Arg);
+  }
+
+  /**
+   * Get the password which has to be used for the command to connect to the
+   * second server without prompting the user in the enable replication
+   * subcommand.  If no password was specified return null.
+   *
+   * @return the password which has to be used for the command to connect to the
+   * second server without prompting the user in the enable replication
+   * subcommand.  If no password was specified return null.
+   */
+  public String getBindPassword2()
+  {
+    return getBindPassword(bindPassword2Arg, bindPasswordFile2Arg);
+  }
+
+  /**
+   * Get the global administrator password which has to be used for the command
+   * to connect to the server(s) without prompting the user.  If no password was
+   * specified, return null.
+   *
+   * @return the global administrator password which has to be used for the
+   * command to connect to the server(s) without prompting the user.  If no
+   * password was specified, return null.
+   */
+  public String getBindPasswordAdmin()
+  {
+    return getBindPassword(adminPasswordArg, adminPasswordFileArg);
+  }
+
+  /**
+   * Get the password of the first server which has to be used in the
+   * enable replication subcommand.
+   *
+   * @param dn
+   *          The user DN for which to password could be asked.
+   * @param out
+   *          The input stream to used if we have to prompt to the
+   *          user.
+   * @param err
+   *          The error stream to used if we have to prompt to the
+   *          user.
+   * @return the password of the first server which has to be used n the
+   *          enable replication subcommand.
+   */
+  public String getBindPassword1(
+      String dn, OutputStream out, OutputStream err)
+  {
+    return getBindPassword(dn, out, err, bindPassword1Arg,
+        bindPasswordFile1Arg);
+  }
+
+  /**
+   * Get the password of the second server which has to be used in the
+   * enable replication subcommand.
+   *
+   * @param dn
+   *          The user DN for which to password could be asked.
+   * @param out
+   *          The input stream to used if we have to prompt to the
+   *          user.
+   * @param err
+   *          The error stream to used if we have to prompt to the
+   *          user.
+   * @return the password of the second server which has to be used in the
+   *          enable replication subcommand.
+   */
+  public String getBindPassword2(
+      String dn, OutputStream out, OutputStream err)
+  {
+    return getBindPassword(dn, out, err, bindPassword2Arg,
+        bindPasswordFile2Arg);
+  }
+
+  /**
+   * Get the password of the global administrator which has to be used for the
+   * command.
+   *
+   * @param dn
+   *          The user DN for which to password could be asked.
+   * @param out
+   *          The input stream to used if we have to prompt to the
+   *          user.
+   * @param err
+   *          The error stream to used if we have to prompt to the
+   *          user.
+   * @return the password of the global administrator which has to be used for
+   *          the command.
+   */
+  public String getBindPasswordAdmin(
+      String dn, OutputStream out, OutputStream err)
+  {
+    return getBindPassword(dn, out, err, adminPasswordArg,
+        adminPasswordFileArg);
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the first server in the enable
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the first server in
+   * the enable replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSSL1()
+  {
+    return useSSL1Arg.isPresent();
+  }
+
+  /**
+   * Indicate if the startTLS mode is required for the first server in the
+   * enable replication subcommand.
+   *
+   * @return <CODE>true</CODE> if startTLS mode is required for the first server
+   * in the enable replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useStartTLS1()
+  {
+    return useStartTLS1Arg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the second server in the enable
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the second server in
+   * the enable replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSSL2()
+  {
+    return useSSL2Arg.isPresent();
+  }
+
+  /**
+   * Indicate if the startTLS mode is required for the second server in the
+   * enable replication subcommand.
+   *
+   * @return <CODE>true</CODE> if startTLS mode is required for the second
+   * server in the enable replication subcommand and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean useStartTLS2()
+  {
+    return useStartTLS2Arg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the source server in the
+   * initialize replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the source server
+   * in the initialize replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSSLSource()
+  {
+    return useSSLSourceArg.isPresent();
+  }
+
+  /**
+   * Indicate if the StartTLS mode is required for the source server in the
+   * initialize replication subcommand.
+   *
+   * @return <CODE>true</CODE> if StartTLS mode is required for the source
+   * server in the initialize replication subcommand and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean useStartTLSSource()
+  {
+    return useStartTLSSourceArg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the destinaton server in the
+   * initialize replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the destination
+   * server in the initialize replication subcommand and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean useSSLDestination()
+  {
+    return useSSLDestinationArg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the destination server in the
+   * initialize replication subcommand.
+   *
+   * @return <CODE>true</CODE> if StartTLS mode is required for the destination
+   * server in the initialize replication subcommand and <CODE>false</CODE>
+   * otherwise.
+   */
+  public boolean useStartTLSDestination()
+  {
+    return useStartTLSDestinationArg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the server in the disable
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the server in the
+   * disable replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSSLToDisable()
+  {
+    return useSSLArg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the server in the disable
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if StartTLS mode is required for the server in
+   * the disable replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useStartTLSToDisable()
+  {
+    return useStartTLSArg.isPresent();
+  }
+
+  /**
+   * Returns the Administrator UID explicitly provided in the command-line.
+   * @return the Administrator UID explicitly provided in the command-line.
+   */
+  public String getAdministratorUID()
+  {
+    return getValue(adminUidArg);
+  }
+
+  /**
+   * Returns the default Administrator UID value.
+   * @return the default Administrator UID value.
+   */
+  public String getDefaultAdministratorUID()
+  {
+    return getDefaultValue(adminUidArg);
+  }
+
+  /**
+   * Returns the first host name explicitly provided in the enable replication
+   * subcommand.
+   * @return the first host name explicitly provided in the enable replication
+   * subcommand.
+   */
+  public String getHostName1()
+  {
+    return getValue(hostName1Arg);
+  }
+
+  /**
+   * Returns the first host name default value in the enable replication
+   * subcommand.
+   * @return the first host name default value in the enable replication
+   * subcommand.
+   */
+  public String getDefaultHostName1()
+  {
+    return getDefaultValue(hostName1Arg);
+  }
+
+  /**
+   * Returns the first server port explicitly provided in the enable replication
+   * subcommand.
+   * @return the first server port explicitly provided in the enable replication
+   * subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPort1()
+  {
+    return getValue(port1Arg);
+  }
+
+  /**
+   * Returns the first server port default value in the enable replication
+   * subcommand.
+   * @return the first server port default value in the enable replication
+   * subcommand.
+   */
+  public int getDefaultPort1()
+  {
+    return getDefaultValue(port1Arg);
+  }
+
+  /**
+   * Returns the first server bind dn explicitly provided in the enable
+   * replication subcommand.
+   * @return the first server bind dn explicitly provided in the enable
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public String getBindDn1()
+  {
+    return getValue(bindDn1Arg);
+  }
+
+  /**
+   * Returns the first server bind dn default value in the enable replication
+   * subcommand.
+   * @return the first server bind dn default value in the enable replication
+   * subcommand.
+   */
+  public String getDefaultBindDn1()
+  {
+    return getDefaultValue(bindDn1Arg);
+  }
+
+  /**
+   * Returns the first server replication port explicitly provided in the enable
+   * replication subcommand.
+   * @return the first server replication port explicitly provided in the enable
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getReplicationPort1()
+  {
+    return getValue(replicationPort1Arg);
+  }
+
+  /**
+   * Returns the first server replication port default value in the enable
+   * replication subcommand.
+   * @return the first server replication port default value in the enable
+   * replication subcommand.
+   */
+  public int getDefaultReplicationPort1()
+  {
+    return getDefaultValue(replicationPort1Arg);
+  }
+
+  /**
+   * Returns the second host name explicitly provided in the enable replication
+   * subcommand.
+   * @return the second host name explicitly provided in the enable replication
+   * subcommand.
+   */
+  public String getHostName2()
+  {
+    return getValue(hostName2Arg);
+  }
+
+  /**
+   * Returns the second host name default value in the enable replication
+   * subcommand.
+   * @return the second host name default value in the enable replication
+   * subcommand.
+   */
+  public String getDefaultHostName2()
+  {
+    return getDefaultValue(hostName2Arg);
+  }
+
+  /**
+   * Returns the second server port explicitly provided in the enable
+   * replication subcommand.
+   * @return the second server port explicitly provided in the enable
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPort2()
+  {
+    return getValue(port2Arg);
+  }
+
+  /**
+   * Returns the second server port default value in the enable replication
+   * subcommand.
+   * @return the second server port default value in the enable replication
+   * subcommand.
+   */
+  public int getDefaultPort2()
+  {
+    return getDefaultValue(port2Arg);
+  }
+
+  /**
+   * Returns the second server bind dn explicitly provided in the enable
+   * replication subcommand.
+   * @return the second server bind dn explicitly provided in the enable
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public String getBindDn2()
+  {
+    return getValue(bindDn2Arg);
+  }
+
+  /**
+   * Returns the second server bind dn default value in the enable replication
+   * subcommand.
+   * @return the second server bind dn default value in the enable replication
+   * subcommand.
+   */
+  public String getDefaultBindDn2()
+  {
+    return getDefaultValue(bindDn2Arg);
+  }
+
+  /**
+   * Returns the second server replication port explicitly provided in the
+   * enable replication subcommand.
+   * @return the second server replication port explicitly provided in the
+   * enable replication subcommand.  Returns -1 if no port was explicitly
+   * provided.
+   */
+  public int getReplicationPort2()
+  {
+    return getValue(replicationPort2Arg);
+  }
+
+  /**
+   * Returns the second server replication port default value in the enable
+   * replication subcommand.
+   * @return the second server replication port default value in the enable
+   * replication subcommand.
+   */
+  public int getDefaultReplicationPort2()
+  {
+    return getDefaultValue(replicationPort2Arg);
+  }
+
+  /**
+   * Returns the host name explicitly provided in the disable replication
+   * subcommand.
+   * @return the host name explicitly provided in the disable replication
+   * subcommand.
+   */
+  public String getHostNameToDisable()
+  {
+    return getValue(hostNameArg);
+  }
+
+  /**
+   * Returns the host name default value in the disable replication
+   * subcommand.
+   * @return the host name default value in the disable replication
+   * subcommand.
+   */
+  public String getDefaultHostNameToDisable()
+  {
+    return getDefaultValue(hostNameArg);
+  }
+
+  /**
+   * Returns the source host name explicitly provided in the initialize
+   * replication subcommand.
+   * @return the source host name explicitly provided in the initialize
+   * replication subcommand.
+   */
+  public String getHostNameSource()
+  {
+    return getValue(hostNameSourceArg);
+  }
+
+  /**
+   * Returns the first host name default value in the initialize replication
+   * subcommand.
+   * @return the first host name default value in the initialize replication
+   * subcommand.
+   */
+  public String getDefaultHostNameSource()
+  {
+    return getDefaultValue(hostNameSourceArg);
+  }
+
+  /**
+   * Returns the destination host name explicitly provided in the initialize
+   * replication subcommand.
+   * @return the destination host name explicitly provided in the initialize
+   * replication subcommand.
+   */
+  public String getHostNameDestination()
+  {
+    return getValue(hostNameDestinationArg);
+  }
+
+  /**
+   * Returns the destination host name default value in the initialize
+   * replication subcommand.
+   * @return the destination host name default value in the initialize
+   * replication subcommand.
+   */
+  public String getDefaultHostNameDestination()
+  {
+    return getDefaultValue(hostNameDestinationArg);
+  }
+
+  /**
+   * Returns the source server port explicitly provided in the initialize
+   * replication subcommand.
+   * @return the source server port explicitly provided in the initialize
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPortSource()
+  {
+    return getValue(portSourceArg);
+  }
+
+  /**
+   * Returns the source server port default value in the initialize replication
+   * subcommand.
+   * @return the source server port default value in the initialize replication
+   * subcommand.
+   */
+  public int getDefaultPortSource()
+  {
+    return getDefaultValue(portSourceArg);
+  }
+
+  /**
+   * Returns the destination server port explicitly provided in the initialize
+   * replication subcommand.
+   * @return the destination server port explicitly provided in the initialize
+   * replication subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPortDestination()
+  {
+    return getValue(portDestinationArg);
+  }
+
+  /**
+   * Returns the destination server port default value in the initialize
+   * replication subcommand.
+   * @return the destination server port default value in the initialize
+   * replication subcommand.
+   */
+  public int getDefaultPortDestination()
+  {
+    return getDefaultValue(portDestinationArg);
+  }
+
+  /**
+   * Returns the server port explicitly provided in the disable replication
+   * subcommand.
+   * @return the server port explicitly provided in the disable replication
+   * subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPortToDisable()
+  {
+    return getValue(portArg);
+  }
+
+  /**
+   * Returns the server port default value in the disable replication
+   * subcommand.
+   * @return the server port default value in the disable replication
+   * subcommand.
+   */
+  public int getDefaultPortToDisable()
+  {
+    return getDefaultValue(portArg);
+  }
+
+  /**
+   * Returns the list of base DNs provided by the user.
+   * @return the list of base DNs provided by the user.
+   */
+  public LinkedList<String> getBaseDNs()
+  {
+    return baseDNsArg.getValues();
+  }
+
+  /**
+   * Returns the value of the provided argument only if the user provided it
+   * explicitly.
+   * @param arg the StringArgument to be handled.
+   * @return the value of the provided argument only if the user provided it
+   * explicitly.
+   */
+  private String getValue(StringArgument arg)
+  {
+    String v = null;
+    if (arg.isPresent())
+    {
+      v = arg.getValue();
+    }
+    return v;
+  }
+
+  /**
+   * Returns the default value of the provided argument.
+   * @param arg the StringArgument to be handled.
+   * @return the default value of the provided argument.
+   */
+  private String getDefaultValue(StringArgument arg)
+  {
+    return arg.getDefaultValue();
+  }
+
+  /**
+   * Returns the value of the provided argument only if the user provided it
+   * explicitly.
+   * @param arg the StringArgument to be handled.
+   * @return the value of the provided argument only if the user provided it
+   * explicitly.
+   */
+  private int getValue(IntegerArgument arg)
+  {
+    int v = -1;
+    if (arg.isPresent())
+    {
+      try
+      {
+        v = arg.getIntValue();
+      }
+      catch (ArgumentException ae)
+      {
+        // This is a bug
+        throw new IllegalStateException(
+            "There was an argument exception calling "+
+            "ReplicationCliParser.getValue().  This appears to be a bug "+
+            "because this method should be called after calling "+
+            "parseArguments which should result in an error.", ae);
+      }
+    }
+    return v;
+  }
+
+  /**
+   * Returns the default value of the provided argument.
+   * @param arg the StringArgument to be handled.
+   * @return the default value of the provided argument.
+   */
+  private int getDefaultValue(IntegerArgument arg)
+  {
+    int returnValue = -1;
+    String defaultValue = arg.getDefaultValue();
+    if (defaultValue != null)
+    {
+      returnValue = Integer.parseInt(arg.getDefaultValue());
+    }
+    return returnValue;
+  }
+
+  /**
+   * Checks the subcommand options and updates the provided MessageBuilder
+   * with the errors that were encountered with the subcommand options.
+   *
+   * This method assumes that the method parseArguments for the parser has
+   * already been called.
+   * @param buf the MessageBuilder object where we add the error messages
+   * describing the errors encountered.
+   */
+  public void validateSubcommandOptions(MessageBuilder buf)
+  {
+    if (isEnableReplicationSubcommand())
+    {
+      validateEnableReplicationOptions(buf);
+    }
+    else if (isDisableReplicationSubcommand())
+    {
+      validateDisableReplicationOptions(buf);
+    }
+    else  if (isInitializeReplicationSubcommand())
+    {
+      validateInitializeReplicationOptions(buf);
+    }
+
+    else
+    {
+      // This can occur if the user did not provide any subcommand.  We assume
+      // that the error informing of this will be generated in
+      // validateGlobalOptions.
+    }
+  }
+
+  /**
+   * Returns whether the user provided subcommand is the enable replication
+   * or not.
+   * @return <CODE>true</CODE> if the user provided subcommand is the
+   * enable replication and <CODE>false</CODE> otherwise.
+   */
+  public boolean isEnableReplicationSubcommand()
+  {
+    return isSubcommand(ENABLE_REPLICATION_SUBCMD_NAME);
+  }
+
+  /**
+   * Returns whether the user provided subcommand is the disable replication
+   * or not.
+   * @return <CODE>true</CODE> if the user provided subcommand is the
+   * disable replication and <CODE>false</CODE> otherwise.
+   */
+  public boolean isDisableReplicationSubcommand()
+  {
+    return isSubcommand(DISABLE_REPLICATION_SUBCMD_NAME);
+  }
+
+  /**
+   * Returns whether the user provided subcommand is the initialize replication
+   * or not.
+   * @return <CODE>true</CODE> if the user provided subcommand is the
+   * initialize replication and <CODE>false</CODE> otherwise.
+   */
+  public boolean isInitializeReplicationSubcommand()
+  {
+    return isSubcommand(INITIALIZE_REPLICATION_SUBCMD_NAME);
+  }
+
+  /**
+   * Returns whether the command-line subcommand has the name provided
+   * or not.
+   * @param name the name of the subcommand.
+   * @return <CODE>true</CODE> if command-line subcommand has the name provided
+   * and <CODE>false</CODE> otherwise.
+   */
+  private boolean isSubcommand(String name)
+  {
+    boolean isSubcommand = false;
+    SubCommand subCommand = getSubCommand();
+    if (subCommand != null)
+    {
+      isSubcommand = subCommand.getName().equalsIgnoreCase(name);
+    }
+    return isSubcommand;
+  }
+
+  /**
+   * Checks the enable replication subcommand options and updates the provided
+   * MessageBuilder with the errors that were encountered with the subcommand
+   * options.
+   *
+   * This method assumes that the method parseArguments for the parser has
+   * already been called.
+   * @param buf the MessageBuilder object where we add the error messages
+   * describing the errors encountered.
+   */
+  private void validateEnableReplicationOptions(MessageBuilder buf)
+  {
+    Argument[][] conflictingPairs =
+    {
+        {bindPassword1Arg, bindPasswordFile1Arg},
+        {useStartTLS1Arg, useSSL1Arg},
+        {bindPassword2Arg, bindPasswordFile2Arg},
+        {useStartTLS2Arg, useSSL2Arg}
+    };
+
+    for (int i=0; i< conflictingPairs.length; i++)
+    {
+      Argument arg1 = conflictingPairs[i][0];
+      Argument arg2 = conflictingPairs[i][1];
+      if (arg1.isPresent() && arg2.isPresent())
+      {
+        Message message = ERR_TOOL_CONFLICTING_ARGS.get(
+            arg1.getLongIdentifier(), arg2.getLongIdentifier());
+        addMessage(buf, message);
+      }
+    }
+
+    if (hostName1Arg.getValue().equalsIgnoreCase(hostName2Arg.getValue()))
+    {
+      if (port1Arg.getValue() == port2Arg.getValue())
+      {
+        Message message = ERR_REPLICATION_SAME_SERVER_PORT.get(
+            hostName1Arg.getValue(), port1Arg.getValue());
+        addMessage(buf, message);
+      }
+
+      // If the user explicitly provides the same port in the same host,
+      // reject it.
+      if (getValue(replicationPort1Arg) == getValue(replicationPort2Arg))
+      {
+        Message message = ERR_REPLICATION_SAME_REPLICATION_PORT.get(
+            replicationPort1Arg.getValue(), hostName1Arg.getValue());
+        addMessage(buf, message);
+      }
+
+      try
+      {
+        if (replicationPort1Arg.getIntValue() == port1Arg.getIntValue())
+        {
+          Message message = ERR_REPLICATION_SAME_REPLICATION_PORT.get(
+              replicationPort1Arg.getValue(), hostName1Arg.getValue());
+          addMessage(buf, message);
+        }
+      } catch (ArgumentException ae)
+      {
+        // This is a bug
+        throw new IllegalStateException(
+            "There was an argument exception calling "+
+            "ReplicationCliParser.validateEnableReplicationOptions().  "+
+            "This appears to be a bug "+
+            "because this method should be called after calling "+
+            "parseArguments which should result in an error.", ae);
+      }
+    }
+  }
+
+  /**
+   * Checks the disable replication subcommand options and updates the provided
+   * MessageBuilder with the errors that were encountered with the subcommand
+   * options.
+   *
+   * This method assumes that the method parseArguments for the parser has
+   * already been called.
+   * @param buf the MessageBuilder object where we add the error messages
+   * describing the errors encountered.
+   */
+  private void validateDisableReplicationOptions(MessageBuilder buf)
+  {
+    Argument[][] conflictingPairs =
+    {
+        {useStartTLSSourceArg, useSSLSourceArg},
+        {useStartTLSDestinationArg, useSSLDestinationArg}
+    };
+
+    for (int i=0; i< conflictingPairs.length; i++)
+    {
+      Argument arg1 = conflictingPairs[i][0];
+      Argument arg2 = conflictingPairs[i][1];
+      if (arg1.isPresent() && arg2.isPresent())
+      {
+        Message message = ERR_TOOL_CONFLICTING_ARGS.get(
+            arg1.getLongIdentifier(), arg2.getLongIdentifier());
+        addMessage(buf, message);
+      }
+    }
+
+    if (hostNameSourceArg.getValue().equalsIgnoreCase(
+        hostNameDestinationArg.getValue()))
+    {
+      if (portSourceArg.getValue() == portDestinationArg.getValue())
+      {
+        Message message = ERR_REPLICATION_SAME_SERVER_PORT.get(
+            hostNameSourceArg.getValue(), portSourceArg.getValue());
+        addMessage(buf, message);
+      }
+    }
+  }
+
+  /**
+   * Checks the initialize replication subcommand options and updates the
+   * provided MessageBuilder with the errors that were encountered with the
+   * subcommand options.
+   *
+   * This method assumes that the method parseArguments for the parser has
+   * already been called.
+   * @param buf the MessageBuilder object where we add the error messages
+   * describing the errors encountered.
+   */
+  private void validateInitializeReplicationOptions(MessageBuilder buf)
+  {
+    // The startTLS and useSSL arguments are already validated in
+    // SecureConnectionCliParser.validateGlobalOptions.
+  }
+
+  /**
+   * Adds a message to the provided MessageBuilder.
+   * @param buf the MessageBuilder.
+   * @param message the message to be added.
+   */
+  private void addMessage(MessageBuilder buf, Message message)
+  {
+    if (buf.length() > 0)
+    {
+      buf.append(EOL);
+    }
+    buf.append(message);
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java
new file mode 100644
index 0000000..51cdac8
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java
@@ -0,0 +1,188 @@
+/*
+ * 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.guitools.replicationcli;
+
+import static org.opends.messages.AdminToolMessages.*;
+
+import org.opends.messages.Message;
+
+/**
+ *
+ * The enumeration which defines the return code.
+ *
+ */
+public enum ReplicationCliReturnCode
+{
+  /**
+   * successful.
+   */
+  SUCCESSFUL(0, INFO_REPLICATION_SUCCESSFUL.get()),
+
+  /**
+   * successful but no operation was performed.
+   */
+  SUCCESSFUL_NOP(SUCCESSFUL.getReturnCode(),
+      INFO_REPLICATION_SUCCESSFUL_NOP.get()),
+
+  /**
+   * Unable to initialize arguments.
+   */
+  CANNOT_INITIALIZE_ARGS(1, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Cannot parse argument.
+   */
+  ERROR_PARSING_ARGS(2, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * The user cancelled the operation in interactive mode.
+   */
+  USER_CANCELLED(3, ERR_REPLICATION_USER_CANCELLED.get()),
+
+  /**
+   * Unexpected error (potential bug).
+   */
+  CONFLICTING_ARGS(4, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * The provided base DNs cannot be used to enable replication.
+   */
+  REPLICATION_CANNOT_BE_ENABLED_ON_BASEDN(5, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * The provided base DNs cannot be used to disable replication.
+   */
+  REPLICATION_CANNOT_BE_DISABLED_ON_BASEDN(6, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * The provided base DNs cannot be used to initialize the contents of the
+   * replicas.
+   */
+  REPLICATION_CANNOT_BE_INITIALIZED_ON_BASEDN(7,
+      ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error connecting with the provided credentials.
+   */
+  ERROR_CONNECTING(8, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Could not find the replication ID of the domain to be used to initialize
+   * the replica.
+   */
+  REPLICATIONID_NOT_FOUND(9, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * The number of tries we perform to start the initialization are over.
+   * We systematically receive a peer not found error.
+   */
+  INITIALIZING_TRIES_COMPLETED(10, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error enabling replication on a base DN.
+   */
+  ERROR_ENABLING_REPLICATION_ON_BASEDN(11, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error initializing base DN.
+   */
+  ERROR_INITIALIZING_BASEDN_GENERIC(12, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error reading configuration.
+   */
+  ERROR_READING_CONFIGURATION(13, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error updating ADS.
+   */
+  ERROR_UPDATING_ADS(14, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error reading ADS.
+   */
+  ERROR_READING_ADS(15, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error reading TopologyCache.
+   */
+  ERROR_READING_TOPOLOGY_CACHE(16, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error configuring replication server.
+   */
+  ERROR_CONFIGURING_REPLICATIONSERVER(17, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Unsupported ADS scenario.
+   */
+  REPLICATION_ADS_MERGE_NOT_SUPPORTED(18, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error disabling replication on base DN.
+   */
+  ERROR_DISABLING_REPLICATION_ON_BASEDN(19, ERR_REPLICATION_NO_MESSAGE.get()),
+
+  /**
+   * Error removing replication port reference on base DN.
+   */
+  ERROR_DISABLING_REPLICATION_REMOVE_REFERENCE_ON_BASEDN(20,
+      ERR_REPLICATION_NO_MESSAGE.get());
+
+
+
+  private Message message;
+  private int returnCode;
+
+  // Private constructor.
+  private ReplicationCliReturnCode(int returnCode, Message message)
+  {
+    this.returnCode = returnCode;
+    this.message = message;
+  }
+
+  /**
+   * Get the corresponding message.
+   *
+   * @return The corresponding message.
+   */
+  public Message getMessage()
+  {
+    return message;
+  }
+
+  /**
+   * Get the corresponding return code value.
+   *
+   * @return The corresponding return code value.
+   */
+  public int getReturnCode()
+  {
+    return returnCode;
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java
new file mode 100644
index 0000000..c22ff9e
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java
@@ -0,0 +1,98 @@
+/*
+ * 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.guitools.replicationcli;
+
+import java.util.LinkedList;
+
+/**
+ * This class is used to store the information provided by the user in the
+ * replication command line.  It is required because when we are in interactive
+ * mode the ReplicationCliArgumentParser is not enough.
+ *
+ */
+abstract class ReplicationUserData
+{
+  private LinkedList<String> baseDNs = new LinkedList<String>();
+  private String adminUid;
+  private String adminPwd;
+
+  /**
+   * Returns the Global Administrator password.
+   * @return the Global Administrator password.
+   */
+  String getAdminPwd()
+  {
+    return adminPwd;
+  }
+
+  /**
+   * Sets the Global Administrator password.
+   * @param adminPwd the Global Administrator password.
+   */
+  void setAdminPwd(String adminPwd)
+  {
+    this.adminPwd = adminPwd;
+  }
+
+  /**
+   * Returns the Global Administrator UID.
+   * @return the Global Administrator UID.
+   */
+  String getAdminUid()
+  {
+    return adminUid;
+  }
+
+  /**
+   * Sets the Global Administrator UID.
+   * @param adminUid the Global Administrator UID.
+   */
+  void setAdminUid(String adminUid)
+  {
+    this.adminUid = adminUid;
+  }
+
+  /**
+   * Returns the Base DNs to replicate.
+   * @return the Base DNs to replicate.
+   */
+  LinkedList<String> getBaseDNs()
+  {
+    return new LinkedList<String>(baseDNs);
+  }
+
+  /**
+   * Sets the Base DNs to replicate.
+   * @param baseDNs the Base DNs to replicate.
+   */
+  void setBaseDNs(LinkedList<String> baseDNs)
+  {
+    this.baseDNs.clear();
+    this.baseDNs.addAll(baseDNs);
+  }
+}
diff --git a/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java b/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java
new file mode 100644
index 0000000..887517f
--- /dev/null
+++ b/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java
@@ -0,0 +1,40 @@
+/*
+ * 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.
+ */
+
+
+
+/**
+ * Defines the  classes that are you used by the replication
+ * command lines.  This includes the command line parsers
+ * (ReplicationCliParser), the classes that actually execute the configuration
+ * operations (ReplicationCliMain), the enumeration that defines the return
+ * codes of the command-line (ReplicationCliReturnCode), a particular exception
+ * used only for the package (ReplicationCliException) and the different data
+ * models that represent the data provided by the user directly as command-line
+ * parameters and also interactively.
+ * */
+package org.opends.guitools.replicationcli;
diff --git a/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java b/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
index 346965a..a26ae7b 100644
--- a/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
+++ b/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
@@ -178,7 +178,7 @@
               directoryManagerDn, directoryManagerPwd);
           ConfigFromLDAP onLineConf = new ConfigFromLDAP();
           ConnectionProtocolPolicy policy;
-          if (startTLSArg.isPresent())
+          if (useStartTLSArg.isPresent())
           {
             policy = ConnectionProtocolPolicy.USE_STARTTLS;
           }
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java b/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
index f4081b8..e1e4d3a 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
+++ b/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
@@ -555,25 +555,6 @@
     return confirm(INFO_CLI_UNINSTALL_CONFIRM_DELETE_FILES.get());
   }
 
-  private boolean confirm(Message msg) {
-    boolean confirm = true;
-    Message[] validValues = {
-        INFO_CLI_YES_SHORT.get(),
-        INFO_CLI_NO_SHORT.get(),
-        INFO_CLI_YES_LONG.get(),
-        INFO_CLI_NO_LONG.get(),
-    };
-    Message answer = promptConfirm(msg, validValues[2], validValues);
-    if (INFO_CLI_NO_SHORT.get().toString()
-            .equalsIgnoreCase(answer.toString()) ||
-        INFO_CLI_NO_LONG.get().toString()
-                .equalsIgnoreCase(answer.toString()))
-    {
-      confirm = false;
-    }
-    return confirm;
-  }
-
   /**
    *  Ask for confirmation to update configuration on remote servers.
    *  @return <CODE>true</CODE> if the user wants to continue and stop the
@@ -626,7 +607,7 @@
     {
       while (uid == null)
       {
-        uid = askForAdministratorUID();
+        uid = askForAdministratorUID(parser.getDefaultAdministratorUID());
       }
       while (pwd == null)
       {
@@ -727,17 +708,6 @@
     return accepted;
   }
 
-  private String askForAdministratorUID()
-  {
-    return promptForString(INFO_UNINSTALL_CLI_ADMINISTRATOR_UID_PROMPT.get(),
-        Constants.GLOBAL_ADMIN_UID);
-  }
-
-  private String askForAdministratorPwd()
-  {
-    return promptForPassword(INFO_UNINSTALL_CLI_ADMINISTRATOR_PWD_PROMPT.get());
-  }
-
   private String askForReferencedHostName(String defaultHostName)
   {
     return promptForString(INFO_UNINSTALL_CLI_REFERENCED_HOSTNAME_PROMPT.get(),
@@ -916,7 +886,7 @@
     } catch (TopologyCacheException te)
     {
       LOG.log(Level.WARNING, "Error connecting to server: "+te, te);
-      printErrorMessage(Utils.getStringRepresentation(te));
+      printErrorMessage(Utils.getMessage(te));
 
     } catch (Throwable t)
     {
@@ -973,7 +943,7 @@
         exceptions.add(e);
       }
     }
-    Set<String> exceptionMsgs = new LinkedHashSet<String>();
+    Set<Message> exceptionMsgs = new LinkedHashSet<Message>();
     /* Check the exceptions and see if we throw them or not. */
     for (TopologyCacheException e : exceptions)
     {
@@ -1007,21 +977,18 @@
           else
           {
             stopProcessing = true;
-            String url = e.getLdapUrl();
-            int index = url.indexOf("//");
-            String hostPort = url.substring(index + 2);
             printErrorMessage(
                 INFO_ERROR_READING_CONFIG_LDAP_CERTIFICATE_SERVER.get(
-                hostPort, e.getCause().getMessage()));
+                e.getHostPort(), e.getCause().getMessage()));
           }
         }
         else
         {
-          exceptionMsgs.add(Utils.getStringRepresentation(e));
+          exceptionMsgs.add(Utils.getMessage(e));
         }
         break;
       default:
-        exceptionMsgs.add(Utils.getStringRepresentation(e));
+        exceptionMsgs.add(Utils.getMessage(e));
       }
     }
     if (interactive)
@@ -1029,9 +996,9 @@
       if (!stopProcessing && (exceptionMsgs.size() > 0))
       {
         returnValue = confirm(
-            ERR_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.get(
-                Utils.getStringFromCollection(exceptionMsgs,
-                  Constants.LINE_SEPARATOR)));
+            ERR_UNINSTALL_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.get(
+                Utils.getMessageFromCollection(exceptionMsgs,
+                  Constants.LINE_SEPARATOR).toString()));
       }
       else if (reloadTopologyCache)
       {
@@ -1047,7 +1014,7 @@
     {
       if (exceptionMsgs.size() > 0)
       {
-        printErrorMessage(Utils.getStringFromCollection(exceptionMsgs,
+        printErrorMessage(Utils.getMessageFromCollection(exceptionMsgs,
             Constants.LINE_SEPARATOR));
         returnValue = false;
       }
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java b/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
index ea62557..cb7cf07 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
+++ b/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
@@ -1374,8 +1374,8 @@
             if (throwable instanceof TopologyCacheException)
             {
               qs.displayError(
-                      Message.raw(getStringRepresentation(
-                              (TopologyCacheException)throwable)),
+                      getMessage(
+                              (TopologyCacheException)throwable),
                       INFO_ERROR_TITLE.get());
             }
             else
@@ -1438,7 +1438,7 @@
         exceptions.add(e);
       }
     }
-    Set<String> exceptionMsgs = new LinkedHashSet<String>();
+    Set<Message> exceptionMsgs = new LinkedHashSet<Message>();
     /* Check the exceptions and see if we throw them or not. */
     for (TopologyCacheException e : exceptions)
     {
@@ -1504,13 +1504,13 @@
           }
         }
       }
-      exceptionMsgs.add(getStringRepresentation(e));
+      exceptionMsgs.add(getMessage(e));
     }
     if (!stopProcessing && (exceptionMsgs.size() > 0))
     {
       Message confirmationMsg =
-        ERR_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.get(
-                getStringFromCollection(exceptionMsgs, "n"));
+        ERR_UNINSTALL_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.get(
+                getMessageFromCollection(exceptionMsgs, "\n").toString());
       stopProcessing = !qs.displayConfirmation(confirmationMsg,
           INFO_CONFIRMATION_TITLE.get());
     }
@@ -1568,8 +1568,7 @@
             {
               if (throwable instanceof TopologyCacheException)
               {
-                qs.displayError(Message.raw(
-                    getStringRepresentation((TopologyCacheException)throwable)),
+                qs.displayError(getMessage((TopologyCacheException)throwable),
                     INFO_ERROR_TITLE.get());
               }
               else
diff --git a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java b/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
index 702fad5..04fd1b9 100644
--- a/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
+++ b/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
@@ -167,7 +167,7 @@
         SecureConnectionCliParser.QUIET_OPTION_LONG,
         SecureConnectionCliParser.QUIET_OPTION_SHORT,
         SecureConnectionCliParser.QUIET_OPTION_LONG,
-        INFO_UNINSTALLDS_DESCRIPTION_SILENT.get());
+        INFO_UNINSTALLDS_DESCRIPTION_QUIET.get());
     args.add(quiet);
 
     adminUidArg = new StringArgument("adminUID", 'I',
diff --git a/opends/src/messages/messages/admin_tool.properties b/opends/src/messages/messages/admin_tool.properties
index ec4b5af..04c0762 100644
--- a/opends/src/messages/messages/admin_tool.properties
+++ b/opends/src/messages/messages/admin_tool.properties
@@ -103,8 +103,6 @@
 OpenDS servers the server must be started and then you must provide \
 administrator authentication.  Do you want to start the server and then \
 provide authentication to remove the remote references?
-INFO_UNINSTALL_CLI_ADMINISTRATOR_UID_PROMPT=Global Administrator User ID
-INFO_UNINSTALL_CLI_ADMINISTRATOR_PWD_PROMPT=Global Administrator Password:
 INFO_UNINSTALL_CLI_REFERENCED_HOSTNAME_PROMPT=The name of this host (or IP \
 address) as it is referenced in remote servers for replication
 INFO_UNINSTALL_CONFIRM_PROVIDE_AUTHENTICATION_AGAIN=Do you want to provide \
@@ -159,8 +157,8 @@
  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.
-MILD_ERR_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE=The following \
- errors were encountered reading the configuration of the existing \
+MILD_ERR_UNINSTALL_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE=The \
+ following errors were encountered reading the configuration of the existing \
  servers:\n%s\nDo you want the uninstaller to try to remove the references to \
  this server in a best-effort mode?
 INFO_CONFIRM_UNINSTALL_SERVER_RUNNING_TITLE=Server is Running
@@ -347,7 +345,7 @@
  install.  If not specified the graphical interface will be launched.  The \
  rest of the options (excluding help and version) will only be taken into \
  account if this option is specified
-INFO_UNINSTALLDS_DESCRIPTION_SILENT=Perform a quiet uninstall (no \
+INFO_UNINSTALLDS_DESCRIPTION_QUIET=Perform a quiet uninstall (no \
  progress information is written to the standard output)
 INFO_UNINSTALLDS_DESCRIPTION_REMOVE_ALL=Remove all components of \
  OpenDS (this option is not compatible with the rest of remove options)
@@ -441,15 +439,21 @@
  StartTLS to secure communication with the source server
 INFO_REPLICATION_TOOL_DESCRIPTION=This utility may be used to configure \
  replication between servers so that the data of the servers is synchronized.\
- In order replication to work you have first to enable replication between two \
- servers using the {%s} subcommand and then initialize the contents of one of \
+ In order replication to work you have first to enable replication using the \
+ {%s} subcommand and then initialize the contents of one of \
  servers with the contents of the other using the {%s} subcommand.
+INFO_REPLICATION_DESCRIPTION_QUIET=Perform a quiet operation (no \
+ progress information is written to the standard output)
 INFO_DESCRIPTION_SUBCMD_INITIALIZE_REPLICATION=Initialize the contents of the \
  data under the specified Bind DN on the destination server with the contents \
  on the source server.  This operation is required after enabling replication \
  in order replication to work.
-INFO_DESCRIPTION_SUBCMD_ENABLE_REPLICATION=Configures the two specified \
- servers to replicate the data under the specified Bind DN.
+INFO_DESCRIPTION_SUBCMD_ENABLE_REPLICATION=Updates the configuration of the \
+ servers to replicate the data under the specified Base DN.  If one of the \
+ specified servers is already replicating the data under the Base DN with \
+ other servers, executing this subcommand will update the configuration of all \
+ the servers (so it is sufficient to execute the command line once for each \
+ server we add to the replication topology).
 INFO_DESCRIPTION_SUBCMD_DISABLE_REPLICATION=Disables replication on the \
  specified server for the provided Base DN and removes references in the other \
  servers with which it is replicating data.
@@ -460,3 +464,130 @@
  provide it using the {%s} or the {%s} options.
 SEVERE_ERR_REPLICATION_NOT_A_VALID_BASEDN=The provided value %s is not a valid \
  base DN.
+SEVERE_ERR_REPLICATION_SAME_SERVER_PORT=You have to provide two different \
+ servers to replicate.  You have provided twice the server %s:%s
+SEVERE_ERR_REPLICATION_SAME_REPLICATION_PORT=You have provided the same \
+ replication port (%s) for two servers located on the same machine (%s).
+SEVERE_ERR_REPLICATION_VALID_SUBCOMMAND_NOT_FOUND=Could not find a valid \
+ subcommand.
+INFO_REPLICATION_SUCCESSFUL=The operation has been successfully completed
+INFO_REPLICATION_SUCCESSFUL_NOP=The operation has been successfully completed, \
+ but no action was required
+MILD_ERR_REPLICATION_USER_CANCELLED=User cancelled the operation
+SEVERE_ERR_REPLICATION_NO_MESSAGE=
+
+INFO_ADMINISTRATOR_UID_PROMPT=Global Administrator User ID:
+INFO_ADMINISTRATOR_PWD_PROMPT=Global Administrator Password:
+INFO_ADMINISTRATOR_PWD_CONFIRM_PROMPT=Confirm Password:
+MILD_ERR_ADMINISTRATOR_PWD_DO_NOT_MATCH=The provided passwords do not match.
+MILD_ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN=Could not connect to the \
+ Directory Server %s with the provided credentials.%nProvide again the \
+ required information to connect to the server:
+INFO_REPLICATION_ENABLE_HOSTNAME1_PROMPT=Host name of the first server:
+INFO_REPLICATION_ENABLE_PORT1_PROMPT=LDAP port of the first server:
+INFO_REPLICATION_ENABLE_REPLICATIONPORT1_PROMPT=Replication port for the first \
+server (the port must be free):
+INFO_REPLICATION_ENABLE_HOSTNAME2_PROMPT=Host name of the second server:
+INFO_REPLICATION_ENABLE_PORT2_PROMPT=LDAP port of the second server:
+INFO_REPLICATION_ENABLE_REPLICATIONPORT2_PROMPT=Replication port for the \
+second server (the port must be free):
+INFO_REPLICATION_INITIALIZE_HOSTNAMESOURCE_PROMPT=Host name of the source \
+server:
+INFO_REPLICATION_INITIALIZE_PORTSOURCE_PROMPT=LDAP port of the source server:
+INFO_REPLICATION_DISABLE_HOSTNAME_PROMPT=Host name of the server:
+INFO_REPLICATION_DISABLE_PORT_PROMPT=LDAP port of the server:
+INFO_REPLICATION_INITIALIZE_HOSTNAMEDESTINATION_PROMPT=Host name of the \
+destination server:
+INFO_REPLICATION_INITIALIZE_PORTDESTINATION_PROMPT=LDAP port of the \
+destination server:
+INFO_REPLICATION_BINDDN_PROMPT=Bind DN
+INFO_REPLICATION_PASSWORD_PROMPT=Password
+INFO_REPLICATION_USESSL_PROMPT=Use SSL to connect
+INFO_CLI_INVALID_PORT=The provided value is not a valid port
+INFO_REPLICATION_USESTARTTLS_PROMPT=Use StartTLS to connect
+SEVERE_ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL=The server LDAP port \
+ and the replication port cannot have the same value.  You provided %s for both.
+SEVERE_ERR_NO_SUFFIXES_AVAILABLE_TO_ENABLE_REPLICATION=There are no base DNs \
+ available to enable replication between the two servers.
+INFO_ALREADY_REPLICATED_SUFFIXES=The following base DNs are already replicated \
+ between the two servers:%n%s
+INFO_ALREADY_NOT_REPLICATED_SUFFIXES=The following base DNs are not replicated \
+ between the two servers:%n%s
+MILD_ERR_REPLICATION_ENABLE_SUFFIXES_NOT_FOUND=The following base DNs cannot \
+ be replicated between the two servers because they could not be found in at \
+ least one of the servers:%n%s
+MILD_ERR_NO_SUFFIXES_SELECTED_TO_REPLICATE=You must choose at least one base \
+ DN to be replicated.
+INFO_REPLICATION_ENABLE_SUFFIX_PROMPT=Replicate base DN %s?
+SEVERE_ERR_NO_SUFFIXES_AVAILABLE_TO_INITIALIZE_REPLICATION=There are no base \
+ DNs replicated between the two servers.
+MILD_ERR_SUFFIXES_CANNOT_BE_INITIALIZED=The following base DNs cannot be \
+ initialized because they are not replicated or they are not configured on \
+ both servers:%n%s
+MILD_ERR_NO_SUFFIXES_SELECTED_TO_INITIALIZE=You must choose at least one \
+ base DN to be initialized.
+INFO_REPLICATION_INITIALIZE_SUFFIX_PROMPT=Initialize base DN %s?
+SEVERE_ERR_NO_SUFFIXES_AVAILABLE_TO_DISABLE_REPLICATION=There are no base \
+ DNs replicated in the server.
+MILD_ERR_REPLICATION_DISABLE_SUFFIXES_NOT_FOUND=The following base DNs could \
+ not be found on the server:%n%s
+MILD_ERR_NO_SUFFIXES_SELECTED_TO_DISABLE=You must choose at least one \
+ base DN to be disabled.
+INFO_REPLICATION_DISABLE_SUFFIX_PROMPT=Disable replication on base DN %s?
+MILD_ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE=The \
+ following errors were encountered reading the configuration of the existing \
+ servers:\n%s\nIf you continue the replication tool will to try to update the \
+ configuration of all the servers in a best-effort mode.  However it cannot \
+ guarantee that the servers that are generating errors will be updated.  Do \
+ you want to continue?
+MILD_ERR_NOT_ADMINISTRATIVE_USER=You do not have access rights to the \
+ configuration of the server.
+INFO_REPLICATION_CONFIRM_DISABLE_ADS=You chose to disable replication on \
+ base DN %s.  This base DN is used by the replication mechanism and by some \
+ administrative tools and it is not recommended to configure it directly.  Do \
+ you want to continue?
+INFO_REPLICATION_CONFIRM_DISABLE_GENERIC=Disabling replication will make the \
+ data under the selected base DNs not to be synchronized with other servers \
+ any more.  Do you want to continue?
+INFO_REPLICATION_CONFIRM_INITIALIZE_ADS=You chose to initialize the contents \
+ of base DN %s on server %s with the contents in server %s.  This base DN is \
+ used by the replication mechanism and by some administrative tools and it is \
+ not recommended to configure it directly.  Do you want to continue?
+INFO_REPLICATION_CONFIRM_INITIALIZE_GENERIC=Initializing the contents of a \
+ base DN removes all the existing contents of that base DN.  Do you want to \
+ remove the contents of the selected base DNs on server %s and replace them \
+ with the contents of server %s?
+MILD_ERR_REPLICATION_READING_REGISTERED_SERVERS_WARNING=The following errors \
+ were encountered reading the configuration of the existing servers:\n%s\nThe \
+ replication tool will to try to update the configuration of all the servers \
+ in a best-effort mode.  However it cannot guarantee that the servers that are \
+ generating errors will be updated.
+INFO_REPLICATION_CONNECTING=Establishing connections
+INFO_REPLICATION_ENABLE_UPDATING_ADS_CONTENTS=Checking Registration information
+INFO_REPLICATION_ENABLE_CONFIGURING_REPLICATION_SERVER=Configuring Replication \
+ port on server %s
+INFO_REPLICATION_ENABLE_CONFIGURING_BASEDN=Enabling Replication for baseDN %s \
+ on server %s
+INFO_ENABLE_REPLICATION_INITIALIZING_ADS=Initializing Registration information \
+ on server %s with the contents of server %s
+SEVERE_ERR_INITIALIZING_REPLICATIONID_NOT_FOUND=Error initializing.  Could not \
+ find replication ID in the server %s for base DN %s.
+SEVERE_ERR_REPLICATION_INITIALIZING_TRIES_COMPLETED=Error initializing.  Could \
+ not find a peer to start the initialization after several tries.  Details: %s
+SEVERE_ERR_REPLICATION_CONFIGURING_REPLICATIONSERVER=Error configuring \
+ replication port on server %s.
+SEVERE_ERR_REPLICATION_CONFIGURING_BASEDN=Error updating replication \
+ configuration on base DN %s of server %s.
+SEVERE_ERR_REPLICATION_UPDATING_ADS=Error updating Registration information.  \
+ Details: %s
+SEVERE_ERR_REPLICATION_READING_ADS=Error reading Registration information.  \
+ Details: %s
+SEVERE_ERR_REPLICATION_ADS_MERGE_NOT_SUPPORTED=The registry information found \
+in servers %s and %s is different.  This tool does not allow to handle this \
+scenario.
+SEVERE_ERR_REPLICATION_ERROR_READING_CONFIGURATION=Error reading replication \
+configuration of server %s.  Details: %s
+INFO_REPLICATION_REMOVING_REFERENCES_ON_REMOTE=Removing references on base DN \
+%s of server %s
+INFO_REPLICATION_DISABLING_BASEDN=Disabling replication on base DN %s of \
+server %s
\ No newline at end of file
diff --git a/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opends/src/quicksetup/org/opends/quicksetup/Application.java
index 990c769..20e604e 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/Application.java
@@ -682,9 +682,9 @@
    * @param e the exception we want to obtain the representation from.
    * @return a localized representation of a TopologyCacheException object.
    */
-  protected String getStringRepresentation(TopologyCacheException e)
+  protected Message getMessage(TopologyCacheException e)
   {
-    return Utils.getStringRepresentation(e);
+    return Utils.getMessage(e);
   }
 
   /**
diff --git a/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java b/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
index 01c0113..fd6cf28 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
@@ -195,6 +195,43 @@
   }
 
   /**
+   * Prompts the user to provide a port.
+   * @param msg the message to be displayed.
+   * @param defaultValue the default value to be proposed.
+   * @return the user to provide a port.
+   */
+  protected int promptForPort(Message msg, int defaultValue)
+  {
+    int port = -1;
+    while (port == -1)
+    {
+      String s = promptForString(msg, String.valueOf(defaultValue));
+      if ((s != null) && (s.trim().length() > 0))
+      {
+        try
+        {
+          port = Integer.parseInt(s);
+          if ((port < 0) || (port > 65535))
+          {
+            port = -1;
+          }
+        }
+        catch (Throwable t)
+        {
+          port = -1;
+        }
+        if (port == -1)
+        {
+          Message message = INFO_CLI_INVALID_PORT.get();
+          System.err.println(StaticUtils.wrapText(message,
+                  Utils.getCommandLineMaxLineWidth()));
+        }
+      }
+    }
+    return port;
+  }
+
+  /**
    * Reads a line of text from standard input.
    * @return  The line of text read from standard input, or <CODE>null</CODE>
    *          if the end of the stream is reached or an error occurs while
@@ -406,6 +443,74 @@
   }
 
   /**
+   * Prompts the user to give the Global Administrator UID.
+   * @param defaultValue the default value that will be proposed in the prompt
+   * message.
+   * @return the Global Administrator UID as provided by the user.
+   */
+  protected String askForAdministratorUID(String defaultValue)
+  {
+    return promptForString(INFO_ADMINISTRATOR_UID_PROMPT.get(), defaultValue);
+  }
+
+  /**
+   * Prompts the user to give the Global Administrator password.
+   * @return the Global Administrator password as provided by the user.
+   */
+  protected String askForAdministratorPwd()
+  {
+    return promptForPassword(INFO_ADMINISTRATOR_PWD_PROMPT.get());
+  }
+
+  /**
+   * Prompts the user to confirm a question.  The default proposed value as
+   * answer is to confirm the question.
+   * @param msg the message to be displayed to the user.
+   * @return <CODE>true</CODE> if the user accepted the message and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean confirm(Message msg)
+  {
+    return confirm(msg, true);
+  }
+
+  /**
+   * Prompts the user to confirm a question.
+   * @param msg the message to be displayed to the user.
+   * @param defaultTrue whether the default proposed value as answer is to
+   * accept the message or not.
+   * @return <CODE>true</CODE> if the user accepted the message and
+   * <CODE>false</CODE> otherwise.
+   */
+  protected boolean confirm(Message msg, boolean defaultTrue) {
+    boolean confirm = true;
+    Message[] validValues = {
+        INFO_CLI_YES_SHORT.get(),
+        INFO_CLI_NO_SHORT.get(),
+        INFO_CLI_YES_LONG.get(),
+        INFO_CLI_NO_LONG.get(),
+    };
+    Message defaultMessage;
+    if (defaultTrue)
+    {
+      defaultMessage = validValues[2];
+    }
+    else
+    {
+      defaultMessage = validValues[3];
+    }
+    Message answer = promptConfirm(msg, defaultMessage, validValues);
+    if (INFO_CLI_NO_SHORT.get().toString()
+            .equalsIgnoreCase(answer.toString()) ||
+        INFO_CLI_NO_LONG.get().toString()
+                .equalsIgnoreCase(answer.toString()))
+    {
+      confirm = false;
+    }
+    return confirm;
+  }
+
+  /**
    * Prompts the user to accept the certificate.
    * @param t the throwable that was generated because the certificate was
    * not trusted.
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 092ca4d..a257e5b 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -74,7 +74,6 @@
 import org.opends.quicksetup.installer.ui.ServerSettingsPanel;
 import org.opends.quicksetup.installer.ui.SuffixesToReplicatePanel;
 import org.opends.server.util.SetupUtils;
-import org.opends.server.types.OpenDsException;
 import org.opends.messages.Message;
 import org.opends.messages.MessageBuilder;
 import static org.opends.messages.QuickSetupMessages.*;
@@ -1927,8 +1926,7 @@
           adsContext.createAdminData(null);
           adsContext.createAdministrator(getAdministratorProperties());
           adsContext.registerServer(
-              getRemoteServerProperties(auth.getHostName(),
-                  adsContext.getDirContext()));
+              getRemoteServerProperties(adsContext.getDirContext()));
           createdRemoteAds = true;
           notifyListeners(getFormattedDone());
           notifyListeners(getLineBreak());
@@ -2841,7 +2839,7 @@
         }
         Set<TopologyCacheException> exceptions =
         updateUserDataWithSuffixesInADS(adsContext, trustManager);
-        Set<String> exceptionMsgs = new LinkedHashSet<String>();
+        Set<Message> exceptionMsgs = new LinkedHashSet<Message>();
         /* Check the exceptions and see if we throw them or not. */
         for (TopologyCacheException e : exceptions)
         {
@@ -2901,13 +2899,13 @@
               }
             }
           }
-          exceptionMsgs.add(getStringRepresentation(e));
+          exceptionMsgs.add(getMessage(e));
         }
         if (exceptionMsgs.size() > 0)
         {
           Message confirmationMsg =
             INFO_ERROR_READING_REGISTERED_SERVERS_CONFIRM.get(
-                    getStringFromCollection(exceptionMsgs, "n"));
+                    getMessageFromCollection(exceptionMsgs, "\n"));
           throw new UserDataConfirmationException(Step.REPLICATION_OPTIONS,
               confirmationMsg);
         }
@@ -2984,7 +2982,6 @@
       }
       else if (t instanceof ADSContextException)
       {
-        String[] args = {host+":"+port, t.toString()};
         errorMsgs.add(INFO_REMOTE_ADS_EXCEPTION.get(
                 host+":"+port, t.toString()));
       }
@@ -3365,66 +3362,11 @@
   }
 
   private Map<ADSContext.ServerProperty, Object> getRemoteServerProperties(
-      String hostName, InitialLdapContext ctx) throws NamingException
+      InitialLdapContext ctx) throws NamingException
   {
     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;
+    server.updateAdsPropertiesWithServerProperties();
+    return server.getAdsProperties();
   }
 
   /**
@@ -3739,7 +3681,21 @@
         trustManager);
   }
 
-  private void initializeSuffix(InitialLdapContext ctx, int replicaId,
+  /**
+   * Initializes a suffix with the contents of a replica that has a given
+   * replication id.
+   * @param ctx the connection to the server whose suffix we want to initialize.
+   * @param replicaId the replication ID of the replica we want to use to
+   * initialize the contents of the suffix.
+   * @param suffixDn the dn of the suffix.
+   * @param displayProgress whether we want to display progress or not.
+   * @param sourceServerDisplay the string to be used to represent the server
+   * that contains the data that will be used to initialize the suffix.
+   * @throws ApplicationException if an unexpected error occurs.
+   * @throws PeerNotFoundException if the replication mechanism cannot find
+   * a peer.
+   */
+  public void initializeSuffix(InitialLdapContext ctx, int replicaId,
       String suffixDn, boolean displayProgress, String sourceServerDisplay)
   throws ApplicationException, PeerNotFoundException
   {
@@ -3983,23 +3939,4 @@
     value = (random.nextInt() & modulo);
     return value;
   }
-}
-
-/**
- * The exception that is thrown during initialization if the peer specified
- * could not be found.
- *
- */
-class PeerNotFoundException extends OpenDsException {
-
-  private static final long serialVersionUID = -362726764261560341L;
-
-  /**
-   * The constructor for the exception.
-   * @param message the localized message.
-   */
-  PeerNotFoundException(Message message)
-  {
-    super(message);
-  }
-}
+}
\ No newline at end of file
diff --git a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
index 6464814..fe56f11 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -572,7 +572,12 @@
                 ERR_NO_REACHABLE_PEER_IN_THE_DOMAIN.getId()) != -1;
   }
 
-  private int getReplicationId(Set<Integer> usedIds)
+  /**
+   * Returns the ID to be used for a new replication server or domain.
+   * @param usedIds the list of already used ids.
+   * @return the ID to be used for a new replication server or domain.
+   */
+  public static int getReplicationId(Set<Integer> usedIds)
   {
     Random r = new Random();
     int id = 0;
@@ -583,7 +588,13 @@
     return id;
   }
 
-  private String getDomainName(String[] existingDomains, int newDomainId)
+  /**
+   * Returns the name to be used for a new replication domain.
+   * @param existingDomains the existing domains names.
+   * @param newDomainId the new domain replication id.
+   * @return the name to be used for a new replication domain.
+   */
+  public static String getDomainName(String[] existingDomains, int newDomainId)
   {
     String domainName = DOMAIN_BASE_NAME+newDomainId;
     boolean nameExists = true;
diff --git a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 54ebfe5..1cc5976 100644
--- a/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -517,18 +517,17 @@
   public static String getStringFromCollection(Collection<String> col,
       String separator)
   {
-    String msg = null;
+    StringBuffer msg = new StringBuffer();
     for (String m : col)
     {
-      if (msg == null)
+
+      if (msg.length() > 0)
       {
-        msg = m;
-      } else
-      {
-        msg += separator + m;
+        msg.append(separator);
       }
+      msg.append(m);
     }
-    return msg;
+    return msg.toString();
   }
 
   /**
@@ -669,7 +668,7 @@
    * @param te the exception.
    * @return a localized representation of the provide TopologyCacheException.
    */
-  public static String getStringRepresentation(TopologyCacheException te)
+  public static Message getMessage(TopologyCacheException te)
   {
     MessageBuilder buf = new MessageBuilder();
 
@@ -690,7 +689,7 @@
       // This is unexpected.
       buf.append(getThrowableMsg(INFO_BUG_MSG.get(), te.getCause()));
     }
-    return buf.toString();
+    return buf.toMessage();
   }
 
   /**
diff --git a/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java b/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
index 98fd8aa..9f62f5f 100644
--- a/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
+++ b/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
@@ -690,7 +690,7 @@
 
       // Check that propName is a known prop.
       AdministratorProperty adminUserProperty = ADSContext
-          .getAdminUSerPropFromName(propertyName);
+          .getAdminUserPropFromName(propertyName);
       if (adminUserProperty == null)
       {
         Message message = ERR_CLI_ERROR_PROPERTY_UNRECOGNIZED.get(propertyName);
diff --git a/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java b/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
index 7e6b4cb..d2acf17 100644
--- a/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
+++ b/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
@@ -157,20 +157,20 @@
   protected BooleanArgument useSSLArg = null;
 
   /**
-   * The 'startTLSArg' global argument.
+   * The 'useStartTLSArg' global argument.
    */
-  protected BooleanArgument startTLSArg = null;
+  protected BooleanArgument useStartTLSArg = null;
 
   /** Short form of the option for specifying a noninteractive session. */
   static public final Character INTERACTIVE_OPTION_SHORT = 'i';
 
-  /** Long form of the option for specifying a noninteractive session. */
+  /** Long form of the option for specifying a quiet session. */
   static public final String QUIET_OPTION_LONG = "quiet";
 
   /** Long form of the option for specifying a noninteractive session. */
   static public final String INTERACTIVE_OPTION_LONG = "interactive";
 
-  /** Short form of the option for specifying a noninteractive session. */
+  /** Short form of the option for specifying a quiet session. */
   static public final Character QUIET_OPTION_SHORT = 'Q';
 
   /**
@@ -181,7 +181,7 @@
   /**
    * End Of Line.
    */
-  protected static String EOL = System.getProperty("line.separator");
+  public static String EOL = System.getProperty("line.separator");
 
   /**
    * The Logger.
@@ -400,10 +400,10 @@
         OPTION_LONG_USE_SSL, INFO_DESCRIPTION_USE_SSL.get());
     set.add(useSSLArg);
 
-    startTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
+    useStartTLSArg = new BooleanArgument("startTLS", OPTION_SHORT_START_TLS,
         OPTION_LONG_START_TLS,
         INFO_DESCRIPTION_START_TLS.get());
-    set.add(startTLSArg);
+    set.add(useStartTLSArg);
 
     hostNameArg = new StringArgument("host", OPTION_SHORT_HOST,
         OPTION_LONG_HOST, false, false, true, OPTION_VALUE_HOST, "localhost",
@@ -584,10 +584,10 @@
 
     // Couldn't have at the same time startTLSArg and
     // useSSLArg
-    if (startTLSArg.isPresent()
+    if (useStartTLSArg.isPresent()
             && useSSLArg.isPresent()) {
       Message message = ERR_TOOL_CONFLICTING_ARGS.get(
-              startTLSArg
+              useStartTLSArg
                       .getLongIdentifier(), useSSLArg.getLongIdentifier());
       errors.add(message);
     }
@@ -666,7 +666,7 @@
    */
   public boolean startTLS()
   {
-    if (startTLSArg.isPresent())
+    if (useStartTLSArg.isPresent())
     {
       return true;
     }

--
Gitblit v1.10.0