From 943a2d7d4cca6371830b33db941af3ec0431fb5c 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.
---
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java | 15
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java | 109
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java | 117
opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCache.java | 29
opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java | 15
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java | 17
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java | 2
opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContext.java | 14
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java | 325 ++
opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java | 2
opendj-sdk/opends/src/messages/messages/admin_tool.properties | 149 +
opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java | 20
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java | 63
opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java | 101
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java | 1462 ++++++++++++
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java | 4
opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java | 13
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java | 98
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java | 203 +
opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java | 105
opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java | 2
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java | 188 +
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java | 40
opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java | 233 +
opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java | 3780 +++++++++++++++++++++++++++++++
opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java | 53
26 files changed, 6,933 insertions(+), 226 deletions(-)
diff --git a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContext.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContext.java
index 629dbad..8c21966 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/ADSContext.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/ServerDescriptor.java
index 2034463..49d63ee 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
@@ -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/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCache.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCache.java
index 666f59a..4b0cff2 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCache.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java
index 759bd9d..3fa64dd 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/TopologyCacheException.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java b/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
index 0d117c0..57dd0e7 100644
--- a/opendj-sdk/opends/src/ads/org/opends/admin/ads/util/ConnectionUtils.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/DisableReplicationUserData.java
new file mode 100644
index 0000000..99219ea
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/EnableReplicationUserData.java
new file mode 100644
index 0000000..e17ca87
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/InitializeReplicationUserData.java
new file mode 100644
index 0000000..4f68e23
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliException.java
new file mode 100644
index 0000000..baa9d01
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliMain.java
new file mode 100644
index 0000000..d9ed908
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliParser.java
new file mode 100644
index 0000000..a00fd16
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationCliReturnCode.java
new file mode 100644
index 0000000..51cdac8
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/ReplicationUserData.java
new file mode 100644
index 0000000..c22ff9e
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/replicationcli/package-info.java
new file mode 100644
index 0000000..887517f
--- /dev/null
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/statuspanel/StatusCli.java
index 346965a..a26ae7b 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
@@ -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/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
index f4081b8..e1e4d3a 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallCliHelper.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
index ea62557..cb7cf07 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/Uninstaller.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java b/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
index 702fad5..04fd1b9 100644
--- a/opendj-sdk/opends/src/guitools/org/opends/guitools/uninstaller/UninstallerArgumentParser.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/messages/messages/admin_tool.properties b/opendj-sdk/opends/src/messages/messages/admin_tool.properties
index ec4b5af..04c0762 100644
--- a/opendj-sdk/opends/src/messages/messages/admin_tool.properties
+++ b/opendj-sdk/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/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java
index 990c769..20e604e 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/Application.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
index 01c0113..fd6cf28 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/CliApplicationHelper.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
index 092ca4d..a257e5b 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/Installer.java
@@ -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/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
index 6464814..fe56f11 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/installer/InstallerHelper.java
@@ -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/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
index 54ebfe5..1cc5976 100644
--- a/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
+++ b/opendj-sdk/opends/src/quicksetup/org/opends/quicksetup/util/Utils.java
@@ -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/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
index 98fd8aa..9f62f5f 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/DsFrameworkCliGlobalAdmin.java
+++ b/opendj-sdk/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/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java b/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
index 7e6b4cb..d2acf17 100644
--- a/opendj-sdk/opends/src/server/org/opends/server/admin/client/cli/SecureConnectionCliParser.java
+++ b/opendj-sdk/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