From 2e7a20a59e968a6b73e3fb9e11f4fffc7e73d121 Mon Sep 17 00:00:00 2001
From: jvergara <jvergara@localhost>
Date: Tue, 25 Sep 2007 14:45:59 +0000
Subject: [PATCH] Fix for issue  2261 (dsreplication should provide a view of the replicated baseDNs in a topology).

---
 opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java          |    4 
 opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java                                |   55 ++
 opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/StatusReplicationUserData.java    |  139 ++++++
 opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java                       |    2 
 opendj-sdk/opends/src/ads/org/opends/admin/ads/ReplicaDescriptor.java                               |   38 +
 opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java           |  710 ++++++++++++++++++++++++++++++++++
 opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java |  169 ++++++++
 opendj-sdk/opends/src/messages/messages/admin_tool.properties                                       |   54 ++
 8 files changed, 1,140 insertions(+), 31 deletions(-)

diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ReplicaDescriptor.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ReplicaDescriptor.java
index 598de7f..0004c04 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ReplicaDescriptor.java
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ReplicaDescriptor.java
@@ -41,6 +41,8 @@
   private ServerDescriptor server;
   private Set<String> replicationServers = new HashSet<String>();
   private int replicationId = -1;
+  private int missingChanges = -1;
+  private int ageOfOldestMissingChange = -1;
 
   /**
    * Returns the number of entries contained in the replica.
@@ -160,4 +162,40 @@
   {
     this.replicationId = replicationId;
   }
+
+  /**
+   * Returns the age of the oldest missing change.
+   * @return the age of the oldest missing change.
+   */
+  public int getAgeOfOldestMissingChange()
+  {
+    return ageOfOldestMissingChange;
+  }
+
+  /**
+   * Sets the age of the oldest missing change.
+   * @param ageOfOldestMissingChange the age of the oldest missing change.
+   */
+  public void setAgeOfOldestMissingChange(int ageOfOldestMissingChange)
+  {
+    this.ageOfOldestMissingChange = ageOfOldestMissingChange;
+  }
+
+  /**
+   * Returns the number of missing changes.
+   * @return the number of missing changes.
+   */
+  public int getMissingChanges()
+  {
+    return missingChanges;
+  }
+
+  /**
+   * Sets the number of missing changes.
+   * @param missingChanges the number of missing changes.
+   */
+  public void setMissingChanges(int missingChanges)
+  {
+    this.missingChanges = missingChanges;
+  }
 }
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index d9aadca..a336fc7 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
+++ b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
@@ -44,6 +44,7 @@
 import javax.naming.ldap.Rdn;
 
 import org.opends.admin.ads.util.ConnectionUtils;
+import org.opends.quicksetup.util.Utils;
 
 /**
  * The object of this class represent an OpenDS server.
@@ -688,6 +689,7 @@
       InitialLdapContext ctx) throws NamingException
   {
     boolean replicationEnabled = false;
+    boolean oneDomainReplicated = false;
     SearchControls ctls = new SearchControls();
     ctls.setSearchScope(SearchControls.OBJECT_SCOPE);
     ctls.setReturningAttributes(
@@ -747,6 +749,7 @@
         Set<String> replicationServers = getValues(sr,
             "ds-cfg-replication-server");
         Set<String> dns = getValues(sr, "ds-cfg-replication-dn");
+        oneDomainReplicated = dns.size() > 0;
         for (String dn : dns)
         {
           for (ReplicaDescriptor replica : desc.getReplicas())
@@ -818,6 +821,58 @@
     {
       /* ignore */
     }
+
+    ctls = new SearchControls();
+    ctls.setSearchScope(SearchControls.ONELEVEL_SCOPE);
+    ctls.setReturningAttributes(
+    new String[] {
+      "approximate-delay", "waiting-changes", "base-dn"
+    });
+    filter = "(approximate-delay=*)";
+
+    jndiName = new LdapName("cn=monitor");
+
+    if (oneDomainReplicated)
+    {
+      try
+      {
+        NamingEnumeration monitorEntries = ctx.search(jndiName, filter, ctls);
+
+        while(monitorEntries.hasMore())
+        {
+          SearchResult sr = (SearchResult)monitorEntries.next();
+
+          String dn = getFirstValue(sr, "base-dn");
+
+          for (ReplicaDescriptor replica: desc.getReplicas())
+          {
+            if (Utils.areDnsEqual(dn, replica.getSuffix().getDN()) &&
+                replica.isReplicated())
+            {
+              try
+              {
+                replica.setAgeOfOldestMissingChange(
+                    new Integer(getFirstValue(sr, "approximate-delay")));
+              }
+              catch (Throwable t)
+              {
+              }
+              try
+              {
+                replica.setMissingChanges(
+                    new Integer(getFirstValue(sr, "waiting-changes")));
+              }
+              catch (Throwable t)
+              {
+              }
+            }
+          }
+        }
+      }
+      catch (NameNotFoundException nse)
+      {
+      }
+    }
   }
 
   /**
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
index acfe338..234fb31 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliArgumentParser.java
@@ -59,6 +59,7 @@
   private SubCommand enableReplicationSubCmd;
   private SubCommand disableReplicationSubCmd;
   private SubCommand initializeReplicationSubCmd;
+  private SubCommand statusReplicationSubCmd;
 
   private BooleanArgument noPromptArg;
 
@@ -218,6 +219,11 @@
   private BooleanArgument quietArg;
 
   /**
+   * The 'scriptFriendly' argument.
+   */
+  private BooleanArgument scriptFriendlyArg;
+
+  /**
    * The text of the enable replication subcommand.
    */
   public static final String ENABLE_REPLICATION_SUBCMD_NAME = "enable";
@@ -233,6 +239,11 @@
   public static final String INITIALIZE_REPLICATION_SUBCMD_NAME = "initialize";
 
   /**
+   * The text of the status replication subcommand.
+   */
+  public static final String STATUS_REPLICATION_SUBCMD_NAME = "status";
+
+  /**
    * Creates a new instance of this argument parser with no arguments.
    *
    * @param mainClassName
@@ -265,6 +276,7 @@
     createEnableReplicationSubCommand();
     createDisableReplicationSubCommand();
     createInitializeReplicationSubCommand();
+    createStatusReplicationSubCommand();
   }
 
   /**
@@ -300,7 +312,7 @@
     if (!isInteractive())
     {
       // Check that we have the required data
-      if (!baseDNsArg.isPresent())
+      if (!baseDNsArg.isPresent() && !isStatusReplicationSubcommand())
       {
         errors.add(ERR_REPLICATION_NO_BASE_DN_PROVIDED.get());
       }
@@ -598,6 +610,31 @@
   }
 
   /**
+   * Creates the status 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 createStatusReplicationSubCommand() throws ArgumentException
+  {
+    statusReplicationSubCmd = new SubCommand(this,
+        STATUS_REPLICATION_SUBCMD_NAME,
+        INFO_DESCRIPTION_SUBCMD_STATUS_REPLICATION.get());
+    scriptFriendlyArg = new BooleanArgument(
+        "script-friendly",
+        's',
+        "script-friendly",
+        INFO_DESCRIPTION_SCRIPT_FRIENDLY.get());
+    Argument[] argsToAdd = { secureArgsList.hostNameArg,
+        secureArgsList.portArg, secureArgsList.useSSLArg,
+        secureArgsList.useStartTLSArg, scriptFriendlyArg };
+    for (int i=0; i<argsToAdd.length; i++)
+    {
+      statusReplicationSubCmd.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
@@ -620,6 +657,17 @@
   }
 
   /**
+   * Tells whether the user specified to have a script-friendly output or not.
+   * This method must be called after calling parseArguments.
+   * @return <CODE>true</CODE> if the user specified to have a script-friendly
+   * output and <CODE>false</CODE> otherwise.
+   */
+  public boolean isScriptFriendly()
+  {
+    return scriptFriendlyArg.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.
@@ -852,6 +900,30 @@
   }
 
   /**
+   * Indicate if the SSL mode is required for the server in the status
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if SSL mode is required for the server in the
+   * status replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useSSLToStatus()
+  {
+    return secureArgsList.useSSLArg.isPresent();
+  }
+
+  /**
+   * Indicate if the SSL mode is required for the server in the status
+   * replication subcommand.
+   *
+   * @return <CODE>true</CODE> if StartTLS mode is required for the server in
+   * the status replication subcommand and <CODE>false</CODE> otherwise.
+   */
+  public boolean useStartTLSToStatus()
+  {
+    return secureArgsList.useStartTLSArg.isPresent();
+  }
+
+  /**
    * Returns the Administrator UID explicitly provided in the command-line.
    * @return the Administrator UID explicitly provided in the command-line.
    */
@@ -1112,6 +1184,26 @@
   }
 
   /**
+   * Returns the host name explicitly provided in the status replication
+   * subcommand.
+   * @return the host name explicitly provided in the status replication
+   * subcommand.
+   */
+  public String getHostNameToStatus()
+  {
+    return getValue(secureArgsList.hostNameArg);
+  }
+
+  /**
+   * Returns the host name default value in the status replication subcommand.
+   * @return the host name default value in the status replication subcommand.
+   */
+  public String getDefaultHostNameToStatus()
+  {
+    return getDefaultValue(secureArgsList.hostNameArg);
+  }
+
+  /**
    * Returns the source host name explicitly provided in the initialize
    * replication subcommand.
    * @return the source host name explicitly provided in the initialize
@@ -1222,6 +1314,26 @@
   }
 
   /**
+   * Returns the server port explicitly provided in the status replication
+   * subcommand.
+   * @return the server port explicitly provided in the status replication
+   * subcommand.  Returns -1 if no port was explicitly provided.
+   */
+  public int getPortToStatus()
+  {
+    return getValue(secureArgsList.portArg);
+  }
+
+  /**
+   * Returns the server port default value in the status replication subcommand.
+   * @return the server port default value in the status replication subcommand.
+   */
+  public int getDefaultPortToStatus()
+  {
+    return getDefaultValue(secureArgsList.portArg);
+  }
+
+  /**
    * Returns the list of base DNs provided by the user.
    * @return the list of base DNs provided by the user.
    */
@@ -1321,6 +1433,10 @@
     {
       validateDisableReplicationOptions(buf);
     }
+    else if (isStatusReplicationSubcommand())
+    {
+      validateStatusReplicationOptions(buf);
+    }
     else  if (isInitializeReplicationSubcommand())
     {
       validateInitializeReplicationOptions(buf);
@@ -1357,6 +1473,17 @@
   }
 
   /**
+   * Returns whether the user provided subcommand is the status replication
+   * or not.
+   * @return <CODE>true</CODE> if the user provided subcommand is the
+   * status replication and <CODE>false</CODE> otherwise.
+   */
+  public boolean isStatusReplicationSubcommand()
+  {
+    return isSubcommand(STATUS_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
@@ -1443,8 +1570,7 @@
   {
     Argument[][] conflictingPairs =
     {
-        {useStartTLSSourceArg, useSSLSourceArg},
-        {useStartTLSDestinationArg, useSSLDestinationArg},
+        {secureArgsList.useStartTLSArg, secureArgsList.useSSLArg},
         {adminUidArg, secureArgsList.bindDnArg}
     };
 
@@ -1462,6 +1588,43 @@
   }
 
   /**
+   * Checks the status 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 validateStatusReplicationOptions(MessageBuilder buf)
+  {
+    Argument[][] conflictingPairs =
+    {
+        {secureArgsList.useStartTLSArg, secureArgsList.useSSLArg}
+    };
+
+    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 (quietArg.isPresent())
+    {
+      Message message = ERR_REPLICATION_STATUS_QUIET.get(
+          STATUS_REPLICATION_SUBCMD_NAME, quietArg.getLongIdentifier());
+      addMessage(buf, message);
+    }
+  }
+
+  /**
    * Checks the initialize replication subcommand options and updates the
    * provided MessageBuilder with the errors that were encountered with the
    * subcommand options.
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
index b35863a..8246061 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
@@ -97,7 +97,8 @@
 /**
  * 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.
+ * of another suffix.  It also allows to display the replicated status of the
+ * different base DNs of the servers that are registered in the ADS.
  */
 public class ReplicationCliMain extends CliApplicationHelper
 {
@@ -312,6 +313,10 @@
         {
           returnValue = initializeReplication();
         }
+        else if (argParser.isStatusReplicationSubcommand())
+        {
+          returnValue = statusReplication();
+        }
         else
         {
           err.println(wrapText(ERR_REPLICATION_VALID_SUBCOMMAND_NOT_FOUND.get(),
@@ -390,6 +395,35 @@
   }
 
   /**
+   * Based on the data provided in the command-line it displays replication
+   * status.
+   * @return the error code if the operation failed and SUCCESSFUL if it was
+   * successful.
+   */
+  private ReplicationCliReturnCode statusReplication()
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    StatusReplicationUserData uData = new StatusReplicationUserData();
+    if (argParser.isInteractive())
+    {
+      if (promptIfRequired(uData))
+      {
+        returnValue = statusReplication(uData);
+      }
+      else
+      {
+        returnValue = USER_CANCELLED;
+      }
+    }
+    else
+    {
+      initializeWithArgParser(uData);
+      returnValue = statusReplication(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
@@ -1126,6 +1160,148 @@
   }
 
   /**
+   * Updates the contents of the provided StatusReplicationUserData 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(StatusReplicationUserData uData)
+  {
+    boolean cancelled = false;
+
+    String adminPwd = argParser.getBindPasswordAdmin();
+    String adminUid = argParser.getAdministratorUID();
+
+    String host = argParser.getHostNameToStatus();
+    if (host == null)
+    {
+      host = promptForString(
+          INFO_REPLICATION_STATUS_HOSTNAME_PROMPT.get(),
+          argParser.getDefaultHostNameToStatus(), false);
+    }
+    int port = argParser.getPortToStatus();
+    if (port == -1)
+    {
+      port = promptForPort(
+          INFO_REPLICATION_STATUS_PORT_PROMPT.get(),
+          argParser.getDefaultPortToStatus(), false);
+    }
+    boolean useSSL = argParser.useSSLToStatus();
+    boolean useStartTLS = argParser.useStartTLSToStatus();
+    if (!useSSL && !useStartTLS)
+    {
+      useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), false);
+      if (!useSSL)
+      {
+        useStartTLS =
+          confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), false);
+      }
+    }
+
+    if (adminUid == null)
+    {
+      adminUid = askForAdministratorUID(argParser.getDefaultAdministratorUID());
+    }
+
+    if (adminPwd == null)
+    {
+      adminPwd = askForAdministratorPwd();
+    }
+
+    /*
+     * Try to connect to the server.
+     */
+    InitialLdapContext ctx = 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 = ConnectionUtils.getLDAPUrl(host, port, useSSL);
+          if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
+              getTrustManager()))
+          {
+            cancelled = true;
+          }
+        }
+        else
+        {
+          printLineBreak();
+          printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
+              host+":"+port, ne.toString()));
+          printLineBreak();
+          host = promptForString(
+                INFO_REPLICATION_STATUS_HOSTNAME_PROMPT.get(),
+                getValue(host, argParser.getDefaultHostNameToStatus()), false);
+          port = promptForPort(
+                INFO_REPLICATION_STATUS_PORT_PROMPT.get(),
+              getValue(port, argParser.getDefaultPortToStatus()), false);
+          useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), useSSL);
+          if (!useSSL)
+          {
+            useStartTLS =
+              confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), useStartTLS);
+          }
+          adminUid = askForAdministratorUID(adminUid);
+          adminPwd = askForAdministratorPwd();
+        }
+      }
+    }
+    if (!cancelled)
+    {
+      uData.setHostName(host);
+      uData.setPort(port);
+      uData.setUseSSL(useSSL);
+      uData.setUseStartTLS(useStartTLS);
+      uData.setAdminUid(adminUid);
+      uData.setAdminPwd(adminPwd);
+      uData.setScriptFriendly(argParser.isScriptFriendly());
+    }
+    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
+      // statusReplication(StatusReplicationUserData) method.  Here we have
+      // to load the ADS to ask the user to accept the certificates and
+      // eventually admin authentication data.
+      InitialLdapContext[] aux = new InitialLdapContext[] {ctx};
+      cancelled = !loadADSAndAcceptCertificates(aux, uData, false);
+      ctx = aux[0];
+    }
+
+    if (!cancelled)
+    {
+      LinkedList<String> suffixes = argParser.getBaseDNs();
+      uData.setBaseDNs(suffixes);
+    }
+
+    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.
@@ -1652,6 +1828,34 @@
     uData.setUseStartTLS(argParser.useStartTLSToDisable());
   }
 
+
+  /**
+   * Initializes the contents of the provided status 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(StatusReplicationUserData 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.getHostNameToStatus(),
+        argParser.getDefaultHostNameToStatus());
+    uData.setHostName(hostName);
+    int port = getValue(argParser.getPortToStatus(),
+        argParser.getDefaultPortToStatus());
+    uData.setPort(port);
+    uData.setUseSSL(argParser.useSSLToStatus());
+    uData.setUseStartTLS(argParser.useStartTLSToStatus());
+
+    uData.setScriptFriendly(argParser.isScriptFriendly());
+  }
+
   /**
    * Tells whether the server to which the LdapContext is connected has a
    * replication port or not.
@@ -1866,10 +2070,21 @@
         }
         if ((exceptionMsgs.size() > 0) && !cancelled)
         {
-          cancelled = !confirm(
-              ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.
-              get(Utils.getMessageFromCollection(exceptionMsgs,
+          if (uData instanceof StatusReplicationUserData)
+          {
+            printWarningMessage(
+                ERR_REPLICATION_STATUS_READING_REGISTERED_SERVERS.get(
+                    Utils.getMessageFromCollection(exceptionMsgs,
+                        Constants.LINE_SEPARATOR).toString()));
+            printLineBreak();
+          }
+          else
+          {
+            cancelled = !confirm(
+               ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.
+                get(Utils.getMessageFromCollection(exceptionMsgs,
                     Constants.LINE_SEPARATOR).toString()));
+          }
         }
       }
     }
@@ -2335,6 +2550,69 @@
   }
 
   /**
+   * Displays the replication status of the baseDNs specified in the
+   * StatusReplicationUserData object.  This method does not prompt
+   * to the user for information if something is missing.
+   * @param uData the StatusReplicationUserData object.
+   * @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
+   * successful.
+   * and the replication could be enabled and an error code otherwise.
+   */
+  private ReplicationCliReturnCode statusReplication(
+      StatusReplicationUserData uData)
+  {
+    ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
+    InitialLdapContext ctx = null;
+    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)
+    {
+      uData.setBaseDNs(uData.getBaseDNs());
+      try
+      {
+        displayStatus(ctx, uData);
+        returnValue = SUCCESSFUL;
+      }
+      catch (ReplicationCliException rce)
+      {
+        returnValue = rce.getErrorCode();
+        printLineBreak();
+        printErrorMessage(rce.getMessageObject());
+        LOG.log(Level.SEVERE, "Complete error stack:", rce);
+      }
+    }
+    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
@@ -2577,8 +2855,10 @@
             printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_REPLICATE.get());
             for (String dn : availableSuffixes)
             {
-              if (!Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(),
-                  dn) && !Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
+              if (!Utils.areDnsEqual(dn,
+                  ADSContext.getAdministrationSuffixDN()) &&
+                  !Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
+                  !Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
               {
                 if (confirm(INFO_REPLICATION_ENABLE_SUFFIX_PROMPT.get(dn)))
                 {
@@ -2732,8 +3012,10 @@
             printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_DISABLE.get());
             for (String dn : availableSuffixes)
             {
-              if (!Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(),
-                  dn) && !Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
+              if (!Utils.areDnsEqual(dn,
+                  ADSContext.getAdministrationSuffixDN()) &&
+                  !Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
+                  !Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
               {
                 if (confirm(INFO_REPLICATION_DISABLE_SUFFIX_PROMPT.get(dn)))
                 {
@@ -2829,8 +3111,10 @@
 
             for (String dn : availableSuffixes)
             {
-              if (!Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(),
-                  dn) && !Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
+              if (!Utils.areDnsEqual(dn,
+                  ADSContext.getAdministrationSuffixDN()) &&
+                  !Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
+                  !Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
               {
                 if (confirm(INFO_REPLICATION_INITIALIZE_SUFFIX_PROMPT.get(dn)))
                 {
@@ -2850,7 +3134,7 @@
    * @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.
+   * parameters to update the configuration.
    * @throws ReplicationCliException if there is an error.
    */
   private void updateConfiguration(InitialLdapContext ctx1,
@@ -3099,7 +3383,7 @@
     if (uData.replicateSchema())
     {
       baseDNs = uData.getBaseDNs();
-      baseDNs.add("cn=schema");
+      baseDNs.add(Constants.SCHEMA_DN);
       uData.setBaseDNs(baseDNs);
     }
     TopologyCache cache1 = null;
@@ -3318,7 +3602,7 @@
    * 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.
+   * parameters to update the configuration.
    * @throws ReplicationCliException if there is an error.
    */
   private void updateConfiguration(InitialLdapContext ctx,
@@ -3421,6 +3705,406 @@
   }
 
   /**
+   * Displays the replication status of the different base DNs in the servers
+   * registered in the ADS.
+   * @param ctx the connection to the server.
+   * @param uData the StatusReplicationUserData object containing the required
+   * parameters to update the configuration.
+   * @throws ReplicationCliException if there is an error.
+   */
+  private void displayStatus(InitialLdapContext ctx,
+      StatusReplicationUserData uData) throws ReplicationCliException
+  {
+    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())
+      {
+        Message msg =
+            ERR_REPLICATION_STATUS_READING_REGISTERED_SERVERS.get(
+                Utils.getMessageFromCollection(messages,
+                    Constants.LINE_SEPARATOR).toString());
+        printWarningMessage(msg);
+      }
+    }
+
+    LinkedList<String> userBaseDNs = uData.getBaseDNs();
+    LinkedList<Set<ReplicaDescriptor>> replicaLists =
+      new LinkedList<Set<ReplicaDescriptor>>();
+
+    boolean oneReplicated = false;
+    for (SuffixDescriptor suffix : cache.getSuffixes())
+    {
+      String dn = suffix.getDN();
+
+      // If no base DNs where specified display all the base DNs but the schema
+      // and cn=admin data.
+      boolean found = userBaseDNs.isEmpty() &&
+      !Utils.areDnsEqual(dn, ADSContext.getAdministrationSuffixDN()) &&
+      !Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
+      !Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN);
+      for (String baseDN : userBaseDNs)
+      {
+        found = Utils.areDnsEqual(baseDN, dn);
+        if (found)
+        {
+          break;
+        }
+      }
+      if (found)
+      {
+        boolean replicated = false;
+        for (ReplicaDescriptor replica : suffix.getReplicas())
+        {
+          if (replica.isReplicated())
+          {
+            replicated = true;
+            break;
+          }
+        }
+        if (replicated)
+        {
+          oneReplicated = true;
+          replicaLists.add(suffix.getReplicas());
+        }
+        else
+        {
+          // Check if there are already some non replicated base DNs.
+          found = false;
+          for (Set<ReplicaDescriptor> replicas : replicaLists)
+          {
+            ReplicaDescriptor replica = replicas.iterator().next();
+            if (!replica.isReplicated() &&
+                Utils.areDnsEqual(dn, replica.getSuffix().getDN()))
+            {
+              replicas.addAll(suffix.getReplicas());
+              found = true;
+              break;
+            }
+          }
+          if (!found)
+          {
+            replicaLists.add(suffix.getReplicas());
+          }
+        }
+      }
+    }
+
+    if (replicaLists.isEmpty())
+    {
+      printProgressMessage(INFO_REPLICATION_STATUS_NO_BASEDNS.get());
+      printProgressLineBreak();
+    }
+    else
+    {
+      LinkedList<Set<ReplicaDescriptor>> orderedReplicaLists =
+        new LinkedList<Set<ReplicaDescriptor>>();
+      for (Set<ReplicaDescriptor> replicas1 : replicaLists)
+      {
+        String dn1 = replicas1.iterator().next().getSuffix().getDN();
+        boolean inserted = false;
+        for (int i=0; i<orderedReplicaLists.size() && !inserted; i++)
+        {
+          String dn2 =
+            orderedReplicaLists.get(i).iterator().next().getSuffix().getDN();
+          if (dn1.compareTo(dn2) < 0)
+          {
+            orderedReplicaLists.add(i, replicas1);
+            inserted = true;
+          }
+        }
+        if (!inserted)
+        {
+          orderedReplicaLists.add(replicas1);
+        }
+      }
+      for (Set<ReplicaDescriptor> replicas : orderedReplicaLists)
+      {
+        printProgressLineBreak();
+        displayStatus(replicas, uData.isScriptFriendly());
+      }
+      if (oneReplicated && !uData.isScriptFriendly())
+      {
+        printProgressLineBreak();
+        printProgressMessage(INFO_REPLICATION_STATUS_REPLICATED_LEGEND.get());
+        printProgressLineBreak();
+      }
+    }
+  }
+
+  /**
+   * Displays the replication status of the replicas provided.  The code assumes
+   * that all the replicas have the same baseDN and that if they are replicated
+   * all the replicas are replicated with each other.
+   * @param replicas the list of replicas that we are trying to display.
+   * @param scriptFriendly wheter to display it on script-friendly mode or not.
+   */
+  private void displayStatus(Set<ReplicaDescriptor> replicas,
+      boolean scriptFriendly)
+  {
+
+    boolean isReplicated = false;
+    Set<ReplicaDescriptor> orderedReplicas =
+      new LinkedHashSet<ReplicaDescriptor>();
+    Set<String> hostPorts = new TreeSet<String>();
+    for (ReplicaDescriptor replica : replicas)
+    {
+      if (replica.isReplicated())
+      {
+        isReplicated = true;
+      }
+      hostPorts.add(replica.getServer().getHostPort(true));
+    }
+    for (String hostPort : hostPorts)
+    {
+      for (ReplicaDescriptor replica : replicas)
+      {
+        if (replica.getServer().getHostPort(true).equals(hostPort))
+        {
+          orderedReplicas.add(replica);
+        }
+      }
+    }
+    int nCols;
+    final int SERVERPORT = 0;
+    final int NUMBER_ENTRIES = 1;
+    final int MISSING_CHANGES = 2;
+    final int AGE_OF_OLDEST_MISSING_CHANGE = 3;
+    Message[] headers;
+    if (scriptFriendly)
+    {
+      if (isReplicated)
+      {
+        nCols = 4;
+        headers = new Message[] {
+            INFO_REPLICATION_STATUS_LABEL_SERVERPORT.get(),
+            INFO_REPLICATION_STATUS_LABEL_NUMBER_ENTRIES.get(),
+            INFO_REPLICATION_STATUS_LABEL_MISSING_CHANGES.get(),
+            INFO_REPLICATION_STATUS_LABEL_AGE_OF_OLDEST_MISSING_CHANGE.get()
+        };
+      }
+      else
+      {
+        nCols = 2;
+        headers = new Message[] {
+            INFO_REPLICATION_STATUS_LABEL_SERVERPORT.get(),
+            INFO_REPLICATION_STATUS_LABEL_NUMBER_ENTRIES.get()
+        };
+      }
+    }
+    else
+    {
+      if (isReplicated)
+      {
+        nCols = 4;
+        headers = new Message[] {
+            INFO_REPLICATION_STATUS_HEADER_SERVERPORT.get(),
+            INFO_REPLICATION_STATUS_HEADER_NUMBER_ENTRIES.get(),
+            INFO_REPLICATION_STATUS_HEADER_MISSING_CHANGES.get(),
+            INFO_REPLICATION_STATUS_HEADER_AGE_OF_OLDEST_MISSING_CHANGE.get()
+        };
+      }
+      else
+      {
+        nCols = 2;
+        headers = new Message[] {
+            INFO_REPLICATION_STATUS_HEADER_SERVERPORT.get(),
+            INFO_REPLICATION_STATUS_HEADER_NUMBER_ENTRIES.get()
+        };
+      }
+    }
+    Message[][] values = new Message[orderedReplicas.size()][nCols];
+
+    int[] maxWidths = new int[nCols];
+    int i;
+    for (i=0; i<maxWidths.length; i++)
+    {
+      maxWidths[i] = Message.toString(headers[i]).length();
+    }
+
+    i = 0;
+    for (ReplicaDescriptor replica : orderedReplicas)
+    {
+      Message v;
+      for (int j=0; j<nCols; j++)
+      {
+        switch (j)
+        {
+        case SERVERPORT:
+          v = Message.raw(replica.getServer().getHostPort(true));
+          break;
+        case NUMBER_ENTRIES:
+          int nEntries = replica.getEntries();
+          if (nEntries >= 0)
+          {
+            v = Message.raw(String.valueOf(nEntries));
+          }
+          else
+          {
+            v = INFO_NOT_AVAILABLE_LABEL.get();
+          }
+          break;
+        case MISSING_CHANGES:
+          int missingChanges = replica.getMissingChanges();
+          if (missingChanges >= 0)
+          {
+            v = Message.raw(String.valueOf(missingChanges));
+          }
+          else
+          {
+            v = INFO_NOT_AVAILABLE_LABEL.get();
+          }
+          break;
+        case AGE_OF_OLDEST_MISSING_CHANGE:
+          int ageOfOldestMissingChange = replica.getAgeOfOldestMissingChange();
+          if (ageOfOldestMissingChange >= 0)
+          {
+            v = Message.raw(String.valueOf(ageOfOldestMissingChange));
+          }
+          else
+          {
+            v = INFO_NOT_AVAILABLE_LABEL.get();
+          }
+          break;
+        default:
+          throw new IllegalStateException("Unknown index: "+j);
+        }
+        values[i][j] = v;
+        maxWidths[j] = Math.max(maxWidths[j], v.toString().length());
+      }
+      i++;
+    }
+
+    int totalWidth = 0;
+    for (i=0; i<maxWidths.length; i++)
+    {
+      if (i < maxWidths.length - 1)
+      {
+        maxWidths[i] += 5;
+      }
+      totalWidth += maxWidths[i];
+    }
+
+    String dn = replicas.iterator().next().getSuffix().getDN();
+    if (scriptFriendly)
+    {
+      Message[] labels = {
+          INFO_REPLICATION_STATUS_BASEDN.get(),
+          INFO_REPLICATION_STATUS_IS_REPLICATED.get()
+      };
+      Message[] vs = {
+          Message.raw(dn),
+          isReplicated ? INFO_BASEDN_REPLICATED_LABEL.get() :
+            INFO_BASEDN_NOT_REPLICATED_LABEL.get()
+      };
+      for (i=0; i<labels.length; i++)
+      {
+        printProgressMessage(labels[i]+": "+vs[i]);
+        printProgressLineBreak();
+      }
+
+      for (i=0; i<values.length; i++)
+      {
+        printProgressMessage("-");
+        printProgressLineBreak();
+        for (int j=0; j<values[i].length; j++)
+        {
+          printProgressMessage(headers[j]+": "+values[i][j]);
+          printProgressLineBreak();
+        }
+      }
+    }
+    else
+    {
+      if (isReplicated)
+      {
+        printProgressMessage(
+            INFO_REPLICATION_STATUS_REPLICATED.get(dn));
+        printProgressLineBreak();
+      }
+      else
+      {
+        printProgressMessage(
+            INFO_REPLICATION_STATUS_NOT_REPLICATED.get(dn));
+        printProgressLineBreak();
+      }
+
+      MessageBuilder headerLine = new MessageBuilder();
+      for (i=0; i<maxWidths.length; i++)
+      {
+        String header = headers[i].toString();
+        headerLine.append(header);
+        int extra = maxWidths[i] - header.length();
+        for (int j=0; j<extra; j++)
+        {
+          headerLine.append(" ");
+        }
+      }
+      StringBuilder builder = new StringBuilder();
+      for (i=0; i<headerLine.length(); i++)
+      {
+        builder.append("=");
+      }
+      printProgressMessage(builder.toString());
+      printProgressLineBreak();
+      printProgressMessage(headerLine.toMessage());
+      printProgressLineBreak();
+      builder = new StringBuilder();
+      for (i=0; i<headerLine.length(); i++)
+      {
+        builder.append("-");
+      }
+      printProgressMessage(builder.toString());
+      printProgressLineBreak();
+
+      for (i=0; i<values.length; i++)
+      {
+        MessageBuilder line = new MessageBuilder();
+        for (int j=0; j<values[i].length; j++)
+        {
+          int extra = maxWidths[j];
+          line.append(values[i][j]);
+          extra -= values[i][j].length();
+          for (int k=0; k<extra; k++)
+          {
+            line.append(" ");
+          }
+        }
+        printProgressMessage(line.toMessage());
+        printProgressLineBreak();
+      }
+    }
+  }
+
+  /**
    * 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
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/StatusReplicationUserData.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/StatusReplicationUserData.java
new file mode 100644
index 0000000..ce9d0c1
--- /dev/null
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/StatusReplicationUserData.java
@@ -0,0 +1,139 @@
+/*
+ * 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
+ * show replication configuration.  It is required because when we are in
+ * interactive mode the ReplicationCliArgumentParser is not enough.
+ *
+ */
+class StatusReplicationUserData extends ReplicationUserData
+{
+  private String hostName;
+  private int port;
+  private boolean useStartTLS;
+  private boolean useSSL;
+  private boolean scriptFriendly;
+
+  /**
+   * 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;
+  }
+
+  /**
+   * Whether we must display information in a script-friendly mode or not.
+   * @return <CODE>true</CODE> if we must display the information in a
+   * script-friendly mode and <CODE>false</CODE> otherwise.
+   */
+  public boolean isScriptFriendly()
+  {
+    return scriptFriendly;
+  }
+
+  /**
+   * Sets whether we must display information in a script-friendly mode or not.
+   * @param scriptFriendly whether we must display information in a
+   * script-friendly mode or not.
+   */
+  public void setScriptFriendly(boolean scriptFriendly)
+  {
+    this.scriptFriendly = scriptFriendly;
+  }
+}
+
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
index 77f1d55..ffa8fc4 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
@@ -1125,7 +1125,7 @@
       labelWidth = Math.max(labelWidth, labels[i].length());
     }
 
-    Message replicatedLabel = INFO_SUFFIX_REPLICATED_LABEL.get();
+    Message replicatedLabel = INFO_BASEDN_REPLICATED_LABEL.get();
     for (int i=0; i<tableModel.getRowCount(); i++)
     {
       if (i > 0)
diff --git a/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
index 8d6039a..c028965 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
+++ b/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/ui/DatabasesTableModel.java
@@ -560,11 +560,11 @@
     Message s;
     if (rep.getType() == BaseDNDescriptor.Type.REPLICATED)
     {
-      s = INFO_SUFFIX_REPLICATED_LABEL.get();
+      s = INFO_BASEDN_REPLICATED_LABEL.get();
     }
     else
     {
-      s = INFO_SUFFIX_NOT_REPLICATED_LABEL.get();
+      s = INFO_BASEDN_NOT_REPLICATED_LABEL.get();
     }
     return s;
   }
diff --git a/opendj-sdk/opends/src/messages/messages/admin_tool.properties b/opendj-sdk/opends/src/messages/messages/admin_tool.properties
index 919a251..b64e3b6 100644
--- a/opendj-sdk/opends/src/messages/messages/admin_tool.properties
+++ b/opendj-sdk/opends/src/messages/messages/admin_tool.properties
@@ -306,8 +306,8 @@
 INFO_STATUSPANEL_DIALOG_TITLE=OpenDS Status Panel
 INFO_STOP_BUTTON_LABEL=Stop
 INFO_STOP_BUTTON_TOOLTIP=Stops the Directory Server
-INFO_SUFFIX_NOT_REPLICATED_LABEL=Disabled
-INFO_SUFFIX_REPLICATED_LABEL=Enabled
+INFO_BASEDN_NOT_REPLICATED_LABEL=Disabled
+INFO_BASEDN_REPLICATED_LABEL=Enabled
 INFO_SUMMARY_DELETING_EXTERNAL_DB_FILES=Deleting Database Files outside the \
  Installation Path...
 INFO_SUMMARY_DELETING_EXTERNAL_LOG_FILES=Deleting Log Files outside the \
@@ -496,6 +496,10 @@
 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.
+INFO_DESCRIPTION_SUBCMD_STATUS_REPLICATION=Displays a list with the basic \
+ replication configuration of the base DNs of the servers defined in the \
+ registration information.  If no base DNs are specified as parameter the \
+ information for all base DNs is displayed.
 SEVERE_ERR_REPLICATION_NO_BASE_DN_PROVIDED=You must provide at least one base \
  DN in no interactive mode.
 SEVERE_ERR_REPLICATION_NO_ADMINISTRATOR_PASSWORD_PROVIDED=You must provide the \
@@ -516,6 +520,8 @@
  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.
+SEVERE_ERR_REPLICATION_STATUS_QUIET=The {%s} subcommand is not compatible with \
+ the {%s} argument.
 INFO_REPLICATION_SUCCESSFUL=The operation has been successfully completed
 INFO_REPLICATION_SUCCESSFUL_NOP=The operation has been successfully completed, \
  but no action was required
@@ -567,6 +573,8 @@
 INFO_REPLICATION_DISABLE_BINDDN_PROMPT=Global Administrator User ID (or bind \
  DN if no Global Administrator is defined)
 INFO_REPLICATION_DISABLE_PASSWORD_PROMPT=Password for %s:
+INFO_REPLICATION_STATUS_HOSTNAME_PROMPT=Host name of the server
+INFO_REPLICATION_STATUS_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 \
@@ -608,10 +616,13 @@
 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?
+ servers:%n%s%n%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_REPLICATION_STATUS_READING_REGISTERED_SERVERS=The displayed \
+ information might not be complete because the following errors were \
+ encountered reading the configuration of the existing servers:%n%s
 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 \
@@ -650,7 +661,7 @@
 INFO_ENABLE_REPLICATION_INITIALIZING_ADS=Initializing Registration information \
  on server %s with the contents of server %s
 SEVERE_ERR_REPLICATION_ENABLE_SEEDING_TRUSTSTORE=An unexpected error occurred \
- seeding the truststore contentes.  Details: %s
+ seeding the truststore contents.  Details: %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 \
@@ -664,11 +675,30 @@
 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.
+ 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
+ configuration of server %s.  Details: %s
 INFO_REPLICATION_REMOVING_REFERENCES_ON_REMOTE=Removing references on base DN \
-%s of server %s
+ %s of server %s
 INFO_REPLICATION_DISABLING_BASEDN=Disabling replication on base DN %s of \
-server %s
\ No newline at end of file
+ server %s
+INFO_REPLICATION_STATUS_NO_BASEDNS=No base DNs found.
+INFO_REPLICATION_STATUS_BASEDN=Base DN
+INFO_REPLICATION_STATUS_IS_REPLICATED=Replication
+INFO_REPLICATION_STATUS_REPLICATED=%s - Replication Enabled
+INFO_REPLICATION_STATUS_NOT_REPLICATED=%s - Replication Disabled
+INFO_REPLICATION_STATUS_HEADER_SERVERPORT=Server:port
+INFO_REPLICATION_STATUS_HEADER_NUMBER_ENTRIES=Entries
+INFO_REPLICATION_STATUS_HEADER_MISSING_CHANGES=Missing Changes (1)
+INFO_REPLICATION_STATUS_HEADER_AGE_OF_OLDEST_MISSING_CHANGE=A.O.M.C. (2)
+INFO_REPLICATION_STATUS_REPLICATED_LEGEND=[1] The number of changes that are \
+ still missing on this server (and that have been at least applied to one of \
+ the other servers).%n[2] Age of oldest missing change: the age (in \
+ seconds) of the oldest change that has not arrived to this server.
+INFO_REPLICATION_STATUS_LABEL_SERVERPORT=Server
+INFO_REPLICATION_STATUS_LABEL_NUMBER_ENTRIES=Entries
+INFO_REPLICATION_STATUS_LABEL_MISSING_CHANGES=Missing Changes
+INFO_REPLICATION_STATUS_LABEL_AGE_OF_OLDEST_MISSING_CHANGE=Age of oldest \
+missing change
+

--
Gitblit v1.10.0