/*
* 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.quicksetup.util.Utils.getFirstValue;
import static org.opends.quicksetup.util.Utils.getThrowableMsg;
import static org.opends.server.util.ServerConstants.MAX_LINE_WIDTH;
import static org.opends.server.util.StaticUtils.wrapText;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.InetAddress;
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.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.Attribute;
import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;
import javax.naming.directory.DirContext;
import javax.naming.directory.SearchControls;
import javax.naming.directory.SearchResult;
import javax.naming.ldap.InitialLdapContext;
import org.opends.admin.ads.ADSContext;
import org.opends.admin.ads.ADSContextException;
import org.opends.admin.ads.ReplicaDescriptor;
import org.opends.admin.ads.ServerDescriptor;
import org.opends.admin.ads.SuffixDescriptor;
import org.opends.admin.ads.TopologyCache;
import org.opends.admin.ads.TopologyCacheException;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.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.QuickSetupLog;
import org.opends.quicksetup.ReturnCode;
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.AttributeTypePropertyDefinition;
import org.opends.server.admin.ClassLoaderProvider;
import org.opends.server.admin.ClassPropertyDefinition;
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.core.DirectoryServer;
import org.opends.server.types.DN;
import org.opends.server.types.InitializationException;
import org.opends.server.types.NullOutputStream;
import org.opends.server.types.OpenDsException;
import org.opends.server.util.SetupUtils;
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. It also allows to display the replicated status of the
* different base DNs of the servers that are registered in the ADS.
*/
public class ReplicationCliMain extends CliApplicationHelper
{
/**
* The fully-qualified name of this class.
*/
private static final String CLASS_NAME = ReplicationCliMain.class.getName();
/** Prefix for log files. */
static public final String LOG_FILE_PREFIX = "opends-replication-";
/** Suffix for log files. */
static public final String LOG_FILE_SUFFIX = ".log";
private static final Logger LOG =
Logger.getLogger(CliApplicationHelper.class.getName());
// The argument parser to be used.
private ReplicationCliArgumentParser 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.
* @param in the input stream to use for standard input.
*/
public ReplicationCliMain(PrintStream out, PrintStream err, InputStream in)
{
super(out, err, in);
}
/**
* 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, System.in);
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, System.in);
}
/**
* 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
* null if standard output is not
* needed.
* @param errStream The output stream to use for standard error, or
* null if standard error is not
* needed.
* @param inStream The input stream to use for standard input.
* @return The error code.
*/
public static int mainCLI(String[] args, boolean initializeServer,
OutputStream outStream, OutputStream errStream, InputStream inStream)
{
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);
}
try {
QuickSetupLog.initLogFileHandler(
File.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX),
"org.opends.guitools.replicationcli");
QuickSetupLog.disableConsoleLogging();
} catch (Throwable t) {
System.err.println("Unable to initialize log");
t.printStackTrace();
}
ReplicationCliMain replicationCli = new ReplicationCliMain(out, err,
inStream);
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 ReplicationCliArgumentParser(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);
printLineBreak();
printErrorMessage(argParser.getUsage());
LOG.log(Level.SEVERE, "Complete error stack:", ae);
returnValue = ERROR_USER_DATA;
}
}
if (!argParser.usageOrVersionDisplayed())
{
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_USER_DATA;
}
}
if (initializeServer)
{
DirectoryServer.bootstrapClient();
// Bootstrap definition classes.
try
{
ClassLoaderProvider.getInstance().enable();
// Switch off class name validation in client.
ClassPropertyDefinition.setAllowClassValidation(false);
// Switch off attribute type name validation in client.
AttributeTypePropertyDefinition.setCheckSchema(false);
}
catch (InitializationException ie)
{
printErrorMessage(ie.getMessage());
returnValue = ERROR_INITIALIZING_ADMINISTRATION_FRAMEWORK;
}
}
if (returnValue == SUCCESSFUL_NOP)
{
if (argParser.isEnableReplicationSubcommand())
{
returnValue = enableReplication();
}
else if (argParser.isDisableReplicationSubcommand())
{
returnValue = disableReplication();
}
else if (argParser.isInitializeReplicationSubcommand())
{
returnValue = initializeReplication();
}
else if (argParser.isInitializeAllReplicationSubcommand())
{
returnValue = initializeAllReplication();
}
else if (argParser.isStatusReplicationSubcommand())
{
returnValue = statusReplication();
}
else
{
err.println(wrapText(ERR_REPLICATION_VALID_SUBCOMMAND_NOT_FOUND.get(),
MAX_LINE_WIDTH));
err.println(argParser.getUsage());
returnValue = ERROR_USER_DATA;
}
}
}
return returnValue.getReturnCode();
}
/**
* {@inheritDoc}
*/
protected boolean isQuiet()
{
return argParser.isQuiet();
}
/**
* 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 initialize the contents
* of the whole replication topology.
* @return the error code if the operation failed and SUCCESSFUL if it was
* successful.
*/
private ReplicationCliReturnCode initializeAllReplication()
{
ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
InitializeAllReplicationUserData uData =
new InitializeAllReplicationUserData();
if (argParser.isInteractive())
{
if (promptIfRequired(uData))
{
returnValue = initializeAllReplication(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
else
{
initializeWithArgParser(uData);
returnValue = initializeAllReplication(uData);
}
return returnValue;
}
/**
* Based on the data provided in the command-line it displays replication
* status.
* @return the error code if the operation failed and SUCCESSFUL if it was
* successful.
*/
private ReplicationCliReturnCode statusReplication()
{
ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
StatusReplicationUserData uData = new StatusReplicationUserData();
if (argParser.isInteractive())
{
if (promptIfRequired(uData))
{
returnValue = statusReplication(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
else
{
initializeWithArgParser(uData);
returnValue = statusReplication(uData);
}
return returnValue;
}
/**
* Based on the data provided in the command-line it initializes replication
* between two servers.
* @return the error code if the operation failed and SUCCESSFUL if it was
* 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 true if the object was successfully updated and
* false if the user cancelled the operation.
*/
private boolean promptIfRequired(EnableReplicationUserData uData)
{
boolean cancelled = false;
boolean administratorDefined = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
boolean prompted = false;
/*
* Prompt for information on the first server.
*/
String host1 = argParser.getHostName1();
if (host1 == null)
{
host1 = promptForString(
INFO_REPLICATION_ENABLE_HOSTNAME1_PROMPT.get(),
argParser.getDefaultHostName1(), false);
prompted = true;
}
int port1 = argParser.getPort1();
if (port1 == -1)
{
port1 = promptForPort(
INFO_REPLICATION_ENABLE_PORT1_PROMPT.get(),
argParser.getDefaultPort1(), false);
prompted = true;
}
boolean useSSL1 = argParser.useSSL1();
boolean useStartTLS1 = argParser.useStartTLS1();
if (!useSSL1 && !useStartTLS1)
{
useSSL1 = confirm(INFO_REPLICATION_ENABLE_USESSL1_PROMPT.get(), false);
prompted = true;
if (!useSSL1)
{
useStartTLS1 =
confirm(INFO_REPLICATION_ENABLE_USESTARTTLS1_PROMPT.get(), false);
prompted = true;
}
}
String bindDn1 = argParser.getBindDn1();
String pwd1 = argParser.getBindPassword1();
if ((bindDn1 == null) && (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;
}
else
{
// Ask for the bind dn to connect to server 1.
if (bindDn1 == null)
{
bindDn1 = promptForString(
INFO_REPLICATION_ENABLE_BINDDN1_PROMPT.get(),
getValue(bindDn1, argParser.getDefaultBindDn1()), false);
prompted = true;
}
if (pwd1 == null)
{
pwd1 = promptForPassword(
INFO_REPLICATION_ENABLE_PASSWORD1_PROMPT.get(bindDn1));
prompted = true;
}
}
/*
* Try to connect to the first server.
*/
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.
while ((ctx1 == null) && !cancelled)
{
try
{
ctx1 = createContext(host1, port1, useSSL1, useStartTLS1, bindDn1,
pwd1, getTrustManager());
}
catch (NamingException ne)
{
prompted = true;
LOG.log(Level.WARNING, "Error connecting to "+host1+":"+port1, ne);
if (Utils.isCertificateException(ne))
{
String usedUrl = ConnectionUtils.getLDAPUrl(host1, port1, useSSL1);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host1+":"+port1, ne.toString()));
printLineBreak();
host1 = promptForString(
INFO_REPLICATION_ENABLE_HOSTNAME1_PROMPT.get(),
getValue(host1, argParser.getDefaultHostName1()), false);
port1 = promptForPort(INFO_REPLICATION_ENABLE_PORT1_PROMPT.get(),
getValue(port1, argParser.getDefaultPort1()), false);
bindDn1 = promptForString(
INFO_REPLICATION_ENABLE_BINDDN1_PROMPT.get(),
getValue(bindDn1, argParser.getDefaultBindDn1()), false);
pwd1 = promptForPassword(
INFO_REPLICATION_ENABLE_PASSWORD1_PROMPT.get(bindDn1));
useSSL1 = confirm(INFO_REPLICATION_ENABLE_USESSL1_PROMPT.get(),
useSSL1);
if (!useSSL1)
{
useStartTLS1 = confirm(
INFO_REPLICATION_ENABLE_USESTARTTLS1_PROMPT.get(),
useStartTLS1);
}
}
}
}
if (!cancelled)
{
uData.setHostName1(host1);
uData.setPort1(port1);
uData.setBindDn1(bindDn1);
uData.setPwd1(pwd1);
uData.setUseSSL1(useSSL1);
uData.setUseStartTLS1(useStartTLS1);
}
int replicationPort1 = -1;
boolean secureReplication1 = argParser.isSecureReplication1();
if (ctx1 != null)
{
// Try to get the replication port for server 1 only if it is required.
if (!hasReplicationPort(ctx1))
{
boolean tryWithDefault = argParser.getReplicationPort1() != -1;
while (replicationPort1 == -1)
{
if (tryWithDefault)
{
replicationPort1 = argParser.getReplicationPort1();
tryWithDefault = false;
}
else
{
replicationPort1 = promptForPort(
INFO_REPLICATION_ENABLE_REPLICATIONPORT1_PROMPT.get(),
argParser.getDefaultReplicationPort1(), false);
}
if (!argParser.skipReplicationPortCheck() && isLocalHost(host1))
{
if (!SetupUtils.canUseAsPort(replicationPort1))
{
printLineBreak();
printErrorMessage(getCannotBindToPortError(replicationPort1));
printLineBreak();
replicationPort1 = -1;
}
}
else
{
// This is something that we must do in any case... this test is
// already included when we call SetupUtils.canUseAsPort
if (replicationPort1 == port1)
{
printLineBreak();
printErrorMessage(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host1, String.valueOf(replicationPort1)));
replicationPort1 = -1;
}
}
}
if (!secureReplication1)
{
secureReplication1 =
confirm(INFO_REPLICATION_ENABLE_SECURE1_PROMPT.get(
String.valueOf(replicationPort1)), false);
}
}
// 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.
InitialLdapContext[] aux = new InitialLdapContext[] {ctx1};
cancelled = !loadADSAndAcceptCertificates(aux, uData, true);
ctx1 = aux[0];
if (!cancelled)
{
administratorDefined |= hasAdministrator(ctx1);
}
}
uData.setReplicationPort1(replicationPort1);
uData.setSecureReplication1(secureReplication1);
/*
* Prompt for information on the second server.
*/
String host2 = null;
int port2 = -1;
String bindDn2 = null;
String pwd2 = null;
boolean useSSL2 = false;
boolean useStartTLS2 = false;
if (!cancelled)
{
host2 = argParser.getHostName2();
if (prompted)
{
printLineBreak();
}
if (host2 == null)
{
host2 = promptForString(
INFO_REPLICATION_ENABLE_HOSTNAME2_PROMPT.get(),
argParser.getDefaultHostName2(), false);
}
port2 = argParser.getPort2();
while (port2 == -1)
{
port2 = promptForPort(
INFO_REPLICATION_ENABLE_PORT2_PROMPT.get(),
argParser.getDefaultPort2(), false);
if (host1.equalsIgnoreCase(host2))
{
if (port1 == port2)
{
port2 = -1;
Message message = ERR_REPLICATION_ENABLE_SAME_SERVER_PORT.get(
host1, String.valueOf(port1));
printLineBreak();
printErrorMessage(message);
printLineBreak();
}
}
}
useSSL2 = argParser.useSSL2();
useStartTLS2 = argParser.useStartTLS2();
if (!useSSL2 && !useStartTLS2)
{
useSSL2 = confirm(INFO_REPLICATION_ENABLE_USESSL2_PROMPT.get(), false);
if (!useSSL2)
{
useStartTLS2 =
confirm(INFO_REPLICATION_ENABLE_USESTARTTLS2_PROMPT.get(), false);
}
}
bindDn2 = argParser.getBindDn2();
pwd2 = argParser.getBindPassword2();
if ((bindDn2 == null) && (pwd2 == null) && (adminPwd != null) &&
(adminUid != null))
{
// No information provided to connect to the first server. Try
// to use global administrator.
bindDn2 = ADSContext.getAdministratorDN(adminUid);
pwd2 = adminPwd;
}
else
{
// Ask for the bind dn to connect to server 2.
if (bindDn2 == null)
{
bindDn2 = promptForString(
INFO_REPLICATION_ENABLE_BINDDN2_PROMPT.get(),
getValue(bindDn2, argParser.getDefaultBindDn2()), false);
}
if (pwd2 == null)
{
pwd2 = promptForPassword(
INFO_REPLICATION_ENABLE_PASSWORD2_PROMPT.get(bindDn1));
}
}
}
/**
* Try to connect to second server
*/
InitialLdapContext ctx2 = 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 = ConnectionUtils.getLDAPUrl(host2, port2, useSSL2);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
if (pwd2 != null)
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host2+":"+port2, ne.toString()));
}
printLineBreak();
host2 = promptForString(
INFO_REPLICATION_ENABLE_HOSTNAME2_PROMPT.get(),
getValue(host2, argParser.getDefaultHostName2()), false);
port2 = promptForPort(INFO_REPLICATION_ENABLE_PORT2_PROMPT.get(),
getValue(port2, argParser.getDefaultPort2()), false);
bindDn2 = promptForString(
INFO_REPLICATION_ENABLE_BINDDN2_PROMPT.get(),
getValue(bindDn2, argParser.getDefaultBindDn2()), false);
pwd2 = promptForPassword(
INFO_REPLICATION_ENABLE_PASSWORD2_PROMPT.get(bindDn2));
useSSL2 = confirm(INFO_REPLICATION_ENABLE_USESSL2_PROMPT.get(),
useSSL2);
if (!useSSL2)
{
useStartTLS2 = confirm(
INFO_REPLICATION_ENABLE_USESTARTTLS2_PROMPT.get(),
useStartTLS2);
}
}
}
}
if (!cancelled)
{
uData.setHostName2(host2);
uData.setPort2(port2);
uData.setBindDn2(bindDn2);
uData.setPwd2(pwd2);
uData.setUseSSL2(useSSL2);
uData.setUseStartTLS2(useStartTLS2);
}
int replicationPort2 = -1;
boolean secureReplication2 = argParser.isSecureReplication2();
if (ctx2 != null)
{
if (!hasReplicationPort(ctx2))
{
boolean tryWithDefault = argParser.getReplicationPort2() != -1;
while (replicationPort2 == -1)
{
if (tryWithDefault)
{
replicationPort2 = argParser.getReplicationPort2();
tryWithDefault = false;
}
else
{
replicationPort2 = promptForPort(
INFO_REPLICATION_ENABLE_REPLICATIONPORT2_PROMPT.get(),
argParser.getDefaultReplicationPort2(), false);
}
if (!argParser.skipReplicationPortCheck() && isLocalHost(host2))
{
if (!SetupUtils.canUseAsPort(replicationPort2))
{
printLineBreak();
printErrorMessage(getCannotBindToPortError(replicationPort2));
printLineBreak();
replicationPort2 = -1;
}
}
else
{
// This is something that we must do in any case... this test is
// already included when we call SetupUtils.canUseAsPort
if (replicationPort2 == port2)
{
printLineBreak();
printErrorMessage(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host2, String.valueOf(replicationPort2)));
replicationPort2 = -1;
}
}
if (host1.equalsIgnoreCase(host2))
{
if ((replicationPort1 > 0) &&
(replicationPort1 == replicationPort2))
{
printLineBreak();
printErrorMessage(ERR_REPLICATION_SAME_REPLICATION_PORT.get(
String.valueOf(replicationPort2), host1));
printLineBreak();
replicationPort2 = -1;
}
}
}
if (!secureReplication2)
{
secureReplication2 =
confirm(INFO_REPLICATION_ENABLE_SECURE2_PROMPT.get(
String.valueOf(replicationPort2)), false);
}
}
// 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.
InitialLdapContext[] aux = new InitialLdapContext[] {ctx2};
cancelled = !loadADSAndAcceptCertificates(aux, uData, false);
ctx2 = aux[0];
if (!cancelled)
{
administratorDefined |= hasAdministrator(ctx2);
}
}
uData.setReplicationPort2(replicationPort2);
uData.setSecureReplication2(secureReplication2);
// 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.
boolean promptedForAdmin = false;
// There is a case where we haven't had need for the administrator
// credentials even if the administrators are defined: where all the servers
// can be accessed with another user (for instance if all the server have
// defined cn=directory manager and all the entries have the same password).
if (!cancelled && (uData.getAdminUid() == null) && !administratorDefined)
{
if (adminUid == null)
{
printLine(INFO_REPLICATION_ENABLE_ADMINISTRATOR_MUST_BE_CREATED.get(),
true);
promptedForAdmin = true;
adminUid= askForAdministratorUID(
argParser.getDefaultAdministratorUID());
}
uData.setAdminUid(adminUid);
}
if (!cancelled && (uData.getAdminPwd() == null) && !administratorDefined)
{
while (adminPwd == null)
{
if (!promptedForAdmin)
{
printLineBreak();
printLine(INFO_REPLICATION_ENABLE_ADMINISTRATOR_MUST_BE_CREATED.get(),
true);
}
adminPwd = askForAdministratorPwd();
String adminPwdConfirm =
promptForPassword(INFO_ADMINISTRATOR_PWD_CONFIRM_PROMPT.get());
if (!adminPwd.equals(adminPwdConfirm))
{
printLineBreak();
printErrorMessage(ERR_ADMINISTRATOR_PWD_DO_NOT_MATCH.get());
printLineBreak();
adminPwd = null;
}
}
uData.setAdminPwd(adminPwd);
}
if (!cancelled)
{
LinkedList 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)
{
}
}
uData.setReplicateSchema(!argParser.noSchemaReplication());
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 true if the object was successfully updated and
* false if the user cancelled the operation.
*/
private boolean promptIfRequired(DisableReplicationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String bindDn = argParser.getBindDNToDisable();
String host = argParser.getHostNameToDisable();
if (host == null)
{
host = promptForString(
INFO_REPLICATION_DISABLE_HOSTNAME_PROMPT.get(),
argParser.getDefaultHostNameToDisable(), false);
}
int port = argParser.getPortToDisable();
if (port == -1)
{
port = promptForPort(
INFO_REPLICATION_DISABLE_PORT_PROMPT.get(),
argParser.getDefaultPortToDisable(), false);
}
boolean useSSL = argParser.useSSLToDisable();
boolean useStartTLS = argParser.useStartTLSToDisable();
if (!useSSL && !useStartTLS)
{
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), false);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), false);
}
}
if ((adminUid == null) && (bindDn == null))
{
String v = askForBindDnDisable(argParser.getDefaultAdministratorUID());
if (Utils.isDn(v))
{
bindDn = v;
}
else
{
adminUid = v;
}
}
if (adminPwd == null)
{
adminPwd = askForPasswordDisable(adminUid != null ? adminUid : bindDn);
}
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
String lastBindDn;
if (adminUid != null)
{
lastBindDn = ADSContext.getAdministratorDN(adminUid);
}
else
{
lastBindDn = bindDn;
}
try
{
ctx = createContext(host, port, useSSL, useStartTLS, lastBindDn,
adminPwd, getTrustManager());
}
catch (NamingException ne)
{
LOG.log(Level.WARNING, "Error connecting to "+host+":"+port, ne);
if (Utils.isCertificateException(ne))
{
String usedUrl = ConnectionUtils.getLDAPUrl(host, port, useSSL);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host+":"+port, ne.toString()));
printLineBreak();
host = promptForString(
INFO_REPLICATION_DISABLE_HOSTNAME_PROMPT.get(),
getValue(host, argParser.getDefaultHostNameToDisable()), false);
port = promptForPort(
INFO_REPLICATION_DISABLE_PORT_PROMPT.get(),
getValue(port, argParser.getDefaultPortToDisable()), false);
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), useSSL);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), useStartTLS);
}
adminUid = null;
bindDn = null;
String v = askForBindDnDisable(lastBindDn);
if (Utils.isDn(v))
{
bindDn = v;
}
else
{
adminUid = v;
}
adminPwd = askForPasswordDisable(adminUid != null ?
adminUid : bindDn);
}
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
uData.setUseSSL(useSSL);
uData.setUseStartTLS(useStartTLS);
uData.setAdminUid(adminUid);
uData.setBindDn(bindDn);
uData.setAdminPwd(adminPwd);
}
if ((ctx != null) && (adminUid != 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.
InitialLdapContext[] aux = new InitialLdapContext[] {ctx};
cancelled = !loadADSAndAcceptCertificates(aux, uData, false);
ctx = aux[0];
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForDisableReplication(suffixes, ctx, true);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
if (!cancelled)
{
// Ask for confirmation to disable.
boolean disableADS = false;
boolean disableSchema = false;
for (String dn : uData.getBaseDNs())
{
if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
{
disableADS = true;
}
else if (Utils.areDnsEqual(Constants.SCHEMA_DN, dn))
{
disableSchema = true;
}
}
if (disableADS)
{
printLineBreak();
cancelled = !confirm(INFO_REPLICATION_CONFIRM_DISABLE_ADS.get(
ADSContext.getAdministrationSuffixDN()));
}
if (disableSchema)
{
printLineBreak();
cancelled = !confirm(INFO_REPLICATION_CONFIRM_DISABLE_SCHEMA.get());
}
if (!disableSchema && !disableADS)
{
printLineBreak();
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 InitializeAllReplicationUserData
* 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 true if the object was successfully updated and
* false if the user cancelled the operation.
*/
private boolean promptIfRequired(InitializeAllReplicationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String host = argParser.getHostNameToInitializeAll();
if (host == null)
{
host = promptForString(
INFO_REPLICATION_INITIALIZE_ALL_HOSTNAME_PROMPT.get(),
argParser.getDefaultHostNameToInitializeAll(), false);
}
int port = argParser.getPortToInitializeAll();
if (port == -1)
{
port = promptForPort(
INFO_REPLICATION_INITIALIZE_ALL_PORT_PROMPT.get(),
argParser.getDefaultPortToInitializeAll(), false);
}
boolean useSSL = argParser.useSSLToInitializeAll();
boolean useStartTLS = argParser.useStartTLSToInitializeAll();
if (!useSSL && !useStartTLS)
{
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), false);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), false);
}
}
if (adminUid == null)
{
adminUid = askForAdministratorUID(argParser.getDefaultAdministratorUID());
}
if (adminPwd == null)
{
adminPwd = askForAdministratorPwd();
}
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ctx = createContext(host, port, useSSL, useStartTLS,
ADSContext.getAdministratorDN(adminUid), adminPwd,
getTrustManager());
}
catch (NamingException ne)
{
LOG.log(Level.WARNING, "Error connecting to "+host+":"+port, ne);
if (Utils.isCertificateException(ne))
{
String usedUrl = ConnectionUtils.getLDAPUrl(host, port, useSSL);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host+":"+port, ne.toString()));
printLineBreak();
host = promptForString(
INFO_REPLICATION_INITIALIZE_ALL_HOSTNAME_PROMPT.get(),
getValue(host, argParser.getDefaultHostNameToInitializeAll()),
false);
port = promptForPort(
INFO_REPLICATION_INITIALIZE_ALL_PORT_PROMPT.get(),
getValue(port, argParser.getDefaultPortToInitializeAll()), false);
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), useSSL);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), useStartTLS);
}
adminUid = askForAdministratorUID(adminUid);
adminPwd = askForAdministratorPwd();
}
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
uData.setUseSSL(useSSL);
uData.setUseStartTLS(useStartTLS);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForInitializeAllReplication(suffixes, ctx, true);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
if (!cancelled)
{
// Ask for confirmation to initialize.
boolean initializeADS = false;
for (String dn : uData.getBaseDNs())
{
if (Utils.areDnsEqual(ADSContext.getAdministrationSuffixDN(), dn))
{
initializeADS = true;
}
}
String hostPortSource = ConnectionUtils.getHostPort(ctx);
if (initializeADS)
{
printLineBreak();
cancelled = !confirm(INFO_REPLICATION_CONFIRM_INITIALIZE_ALL_ADS.get(
ADSContext.getAdministrationSuffixDN(), hostPortSource));
}
else
{
printLineBreak();
cancelled = !confirm(
INFO_REPLICATION_CONFIRM_INITIALIZE_ALL_GENERIC.get(
hostPortSource));
}
}
if (ctx != null)
{
try
{
ctx.close();
}
catch (Throwable t)
{
}
}
return !cancelled;
}
/**
* Updates the contents of the provided StatusReplicationUserData object
* with the information provided in the command-line. If some information
* is missing, ask the user to provide valid data.
* We assume that if this method is called we are in interactive mode.
* @param uData the object to be updated.
* @return true if the object was successfully updated and
* false if the user cancelled the operation.
*/
private boolean promptIfRequired(StatusReplicationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String host = argParser.getHostNameToStatus();
if (host == null)
{
host = promptForString(
INFO_REPLICATION_STATUS_HOSTNAME_PROMPT.get(),
argParser.getDefaultHostNameToStatus(), false);
}
int port = argParser.getPortToStatus();
if (port == -1)
{
port = promptForPort(
INFO_REPLICATION_STATUS_PORT_PROMPT.get(),
argParser.getDefaultPortToStatus(), false);
}
boolean useSSL = argParser.useSSLToStatus();
boolean useStartTLS = argParser.useStartTLSToStatus();
if (!useSSL && !useStartTLS)
{
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), false);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), false);
}
}
if (adminUid == null)
{
adminUid = askForAdministratorUID(argParser.getDefaultAdministratorUID());
}
if (adminPwd == null)
{
adminPwd = askForAdministratorPwd();
}
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ctx = createContext(host, port, useSSL, useStartTLS,
ADSContext.getAdministratorDN(adminUid), adminPwd,
getTrustManager());
}
catch (NamingException ne)
{
LOG.log(Level.WARNING, "Error connecting to "+host+":"+port, ne);
if (Utils.isCertificateException(ne))
{
String usedUrl = ConnectionUtils.getLDAPUrl(host, port, useSSL);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host+":"+port, ne.toString()));
printLineBreak();
host = promptForString(
INFO_REPLICATION_STATUS_HOSTNAME_PROMPT.get(),
getValue(host, argParser.getDefaultHostNameToStatus()), false);
port = promptForPort(
INFO_REPLICATION_STATUS_PORT_PROMPT.get(),
getValue(port, argParser.getDefaultPortToStatus()), false);
useSSL = confirm(INFO_CLI_USESSL_PROMPT.get(), useSSL);
if (!useSSL)
{
useStartTLS =
confirm(INFO_CLI_USESTARTTLS_PROMPT.get(), useStartTLS);
}
adminUid = askForAdministratorUID(adminUid);
adminPwd = askForAdministratorPwd();
}
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
uData.setUseSSL(useSSL);
uData.setUseStartTLS(useStartTLS);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
uData.setScriptFriendly(argParser.isScriptFriendly());
}
if (ctx != null)
{
// If the server contains an ADS, try to load it and only load it: if
// there are issues with the ADS they will be encountered in the
// statusReplication(StatusReplicationUserData) method. Here we have
// to load the ADS to ask the user to accept the certificates and
// eventually admin authentication data.
InitialLdapContext[] aux = new InitialLdapContext[] {ctx};
cancelled = !loadADSAndAcceptCertificates(aux, uData, false);
ctx = aux[0];
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
uData.setBaseDNs(suffixes);
}
if (ctx != null)
{
try
{
ctx.close();
}
catch (Throwable t)
{
}
}
return !cancelled;
}
/**
* Updates the contents of the provided InitializeReplicationUserData object
* with the information provided in the command-line. If some information
* is missing, ask the user to provide valid data.
* We assume that if this method is called we are in interactive mode.
* @param uData the object to be updated.
* @return true if the object was successfully updated and
* false if the user cancelled the operation.
*/
private boolean promptIfRequired(InitializeReplicationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
boolean promptedForAdmin = false;
if (adminUid == null)
{
adminUid = askForAdministratorUID(argParser.getDefaultAdministratorUID());
promptedForAdmin = true;
}
if (adminPwd == null)
{
adminPwd = askForAdministratorPwd();
promptedForAdmin = true;
}
boolean promptedFor1 = false;
String hostSource = argParser.getHostNameSource();
if (hostSource == null)
{
if (promptedForAdmin)
{
printLineBreak();
}
hostSource = promptForString(
INFO_REPLICATION_INITIALIZE_HOSTNAMESOURCE_PROMPT.get(),
argParser.getDefaultHostNameSource(), false);
promptedFor1 = true;
}
int portSource = argParser.getPortSource();
if (portSource == -1)
{
if (promptedForAdmin && !promptedFor1)
{
printLineBreak();
}
portSource = promptForPort(
INFO_REPLICATION_INITIALIZE_PORTSOURCE_PROMPT.get(),
argParser.getDefaultPortSource(), false);
promptedFor1 = true;
}
boolean useSSLSource = argParser.useSSLSource();
boolean useStartTLSSource = argParser.useStartTLSSource();
if (!useSSLSource && !useStartTLSSource)
{
if (promptedForAdmin && !promptedFor1)
{
printLineBreak();
}
useSSLSource = confirm(
INFO_REPLICATION_INITIALIZE_USESSLSOURCE_PROMPT.get(), false);
if (!useSSLSource)
{
useStartTLSSource =
confirm(INFO_REPLICATION_INITIALIZE_USESTARTTLSSOURCE_PROMPT.get(),
false);
}
promptedFor1 = true;
}
/*
* Try to connect to the source server.
*/
InitialLdapContext ctxSource = 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 = ConnectionUtils.getLDAPUrl(hostSource, portSource,
useSSLSource);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
hostSource+":"+portSource, ne.toString()));
printLineBreak();
hostSource = promptForString(
INFO_REPLICATION_INITIALIZE_HOSTNAMESOURCE_PROMPT.get(),
getValue(hostSource, argParser.getDefaultHostNameSource()),
false);
portSource = promptForPort(
INFO_REPLICATION_INITIALIZE_PORTSOURCE_PROMPT.get(),
getValue(portSource, argParser.getDefaultPortSource()), false);
adminUid = askForAdministratorUID(adminUid);
adminPwd = askForAdministratorPwd();
useSSLSource = confirm(
INFO_REPLICATION_INITIALIZE_USESSLSOURCE_PROMPT.get(),
useSSLSource);
if (!useSSLSource)
{
useStartTLSSource = confirm(
INFO_REPLICATION_INITIALIZE_USESTARTTLSSOURCE_PROMPT.get(),
useStartTLSSource);
}
}
}
}
if (!cancelled)
{
uData.setHostNameSource(hostSource);
uData.setPortSource(portSource);
uData.setUseSSLSource(useSSLSource);
uData.setUseStartTLSSource(useStartTLSSource);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
/* Prompt for destination server credentials */
String hostDestination = argParser.getHostNameDestination();
boolean promptedFor2 = false;
if (hostDestination == null)
{
if (promptedFor1 || promptedForAdmin)
{
printLineBreak();
}
hostDestination = promptForString(
INFO_REPLICATION_INITIALIZE_HOSTNAMEDESTINATION_PROMPT.get(),
argParser.getDefaultHostNameDestination(), false);
promptedFor2 = true;
}
int portDestination = argParser.getPortDestination();
while (portDestination == -1)
{
if ((promptedFor1 || promptedForAdmin) && !promptedFor2)
{
printLineBreak();
}
portDestination = promptForPort(
INFO_REPLICATION_INITIALIZE_PORTDESTINATION_PROMPT.get(),
argParser.getDefaultPortDestination(), false);
if (hostSource.equalsIgnoreCase(hostDestination))
{
if (portSource == portDestination)
{
portDestination = -1;
Message message = ERR_REPLICATION_INITIALIZE_SAME_SERVER_PORT.get(
hostSource, String.valueOf(portSource));
printLineBreak();
printErrorMessage(message);
printLineBreak();
}
}
promptedFor2 = true;
}
boolean useSSLDestination = argParser.useSSLDestination();
boolean useStartTLSDestination = argParser.useStartTLSDestination();
if (!useSSLDestination && !useStartTLSDestination)
{
if ((promptedFor1 || promptedForAdmin) && !promptedFor2)
{
printLineBreak();
}
useSSLDestination = confirm(
INFO_REPLICATION_INITIALIZE_USESSLDESTINATION_PROMPT.get(), false);
if (!useSSLDestination)
{
useStartTLSDestination = confirm(
INFO_REPLICATION_INITIALIZE_USESTARTTLSDESTINATION_PROMPT.get(),
false);
}
promptedFor2 = true;
}
/*
* Try to connect to the destination server.
*/
InitialLdapContext ctxDestination = null;
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 = ConnectionUtils.getLDAPUrl(hostDestination,
portDestination, useSSLDestination);
if (!promptForCertificateConfirmation(ne, getTrustManager(), usedUrl,
getTrustManager()))
{
cancelled = true;
}
}
else
{
printLineBreak();
printErrorMessage(ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
hostDestination+":"+portDestination, ne.toString()));
printLineBreak();
hostDestination = promptForString(
INFO_REPLICATION_INITIALIZE_HOSTNAMEDESTINATION_PROMPT.get(),
getValue(hostDestination,
argParser.getDefaultHostNameDestination()), false);
portDestination = promptForPort(
INFO_REPLICATION_INITIALIZE_PORTDESTINATION_PROMPT.get(),
getValue(portDestination,
argParser.getDefaultPortDestination()), false);
useSSLDestination = confirm(
INFO_REPLICATION_INITIALIZE_USESSLDESTINATION_PROMPT.get(),
useSSLDestination);
if (!useSSLDestination)
{
useStartTLSDestination = confirm(
INFO_REPLICATION_INITIALIZE_USESTARTTLSDESTINATION_PROMPT.get(),
useStartTLSDestination);
}
}
}
}
if (!cancelled)
{
uData.setHostNameDestination(hostDestination);
uData.setPortDestination(portDestination);
uData.setUseSSLDestination(useSSLDestination);
uData.setUseStartTLSDestination(useStartTLSDestination);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForInitializeReplication(suffixes, ctxSource, ctxDestination,
true);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
if (!cancelled)
{
// Ask for confirmation to initialize.
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)
{
printLineBreak();
cancelled = !confirm(INFO_REPLICATION_CONFIRM_INITIALIZE_ADS.get(
ADSContext.getAdministrationSuffixDN(), hostPortDestination,
hostPortSource));
}
else
{
printLineBreak();
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 null returns it and if it is null
* returns the provided default value.
* @param v the value to analyze.
* @param defaultValue the default value.
* @return if the provided value is not null returns it and if it
* is null 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(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
{
// Best-effort: try to use admin, if it does not work, use bind DN.
try
{
InitialLdapContext ctx = createContext(uData.getHostName1(),
uData.getPort1(), uData.useSSL1(), uData.useStartTLS1(),
ADSContext.getAdministratorDN(adminUid), adminPwd,
getTrustManager());
uData.setBindDn1(ADSContext.getAdministratorDN(adminUid));
uData.setPwd1(adminPwd);
ctx.close();
}
catch (Throwable t)
{
String bindDn = getValue(argParser.getBindDn1(),
argParser.getDefaultBindDn1());
uData.setBindDn1(bindDn);
uData.setPwd1(pwd1);
}
}
int replicationPort1 = getValue(argParser.getReplicationPort1(),
argParser.getDefaultReplicationPort1());
uData.setReplicationPort1(replicationPort1);
uData.setSecureReplication1(argParser.isSecureReplication1());
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
{
// Best-effort: try to use admin, if it does not work, use bind DN.
try
{
InitialLdapContext ctx = createContext(uData.getHostName2(),
uData.getPort2(), uData.useSSL2(), uData.useStartTLS2(),
ADSContext.getAdministratorDN(adminUid), adminPwd,
getTrustManager());
uData.setBindDn2(ADSContext.getAdministratorDN(adminUid));
uData.setPwd2(adminPwd);
ctx.close();
}
catch (Throwable t)
{
String bindDn = getValue(argParser.getBindDn2(),
argParser.getDefaultBindDn2());
uData.setBindDn2(bindDn);
uData.setPwd2(pwd2);
}
}
int replicationPort2 = getValue(argParser.getReplicationPort2(),
argParser.getDefaultReplicationPort2());
uData.setReplicationPort2(replicationPort2);
uData.setSecureReplication2(argParser.isSecureReplication2());
uData.setReplicateSchema(!argParser.noSchemaReplication());
}
/**
* 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(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.getPortDestination(),
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(argParser.getBaseDNs()));
String adminUid = argParser.getAdministratorUID();
String bindDn = argParser.getBindDN();
if ((bindDn == null) && (adminUid == null))
{
adminUid = argParser.getDefaultAdministratorUID();
}
uData.setAdminUid(adminUid);
uData.setBindDn(bindDn);
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());
}
/**
* Initializes the contents of the provided initialize all 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(InitializeAllReplicationUserData uData)
{
uData.setBaseDNs(new LinkedList(argParser.getBaseDNs()));
String adminUid = getValue(argParser.getAdministratorUID(),
argParser.getDefaultAdministratorUID());
uData.setAdminUid(adminUid);
String adminPwd = argParser.getBindPasswordAdmin();
uData.setAdminPwd(adminPwd);
String hostName = getValue(argParser.getHostNameToInitializeAll(),
argParser.getDefaultHostNameToInitializeAll());
uData.setHostName(hostName);
int port = getValue(argParser.getPortToInitializeAll(),
argParser.getDefaultPortToInitializeAll());
uData.setPort(port);
uData.setUseSSL(argParser.useSSLToInitializeAll());
uData.setUseStartTLS(argParser.useStartTLSToInitializeAll());
}
/**
* Initializes the contents of the provided status replication user data
* object with what was provided in the command-line without prompting to the
* user.
* @param uData the disable replication user data object to be initialized.
*/
private void initializeWithArgParser(StatusReplicationUserData uData)
{
uData.setBaseDNs(new LinkedList(argParser.getBaseDNs()));
String adminUid = getValue(argParser.getAdministratorUID(),
argParser.getDefaultAdministratorUID());
uData.setAdminUid(adminUid);
String adminPwd = argParser.getBindPasswordAdmin();
uData.setAdminPwd(adminPwd);
String hostName = getValue(argParser.getHostNameToStatus(),
argParser.getDefaultHostNameToStatus());
uData.setHostName(hostName);
int port = getValue(argParser.getPortToStatus(),
argParser.getDefaultPortToStatus());
uData.setPort(port);
uData.setUseSSL(argParser.useSSLToStatus());
uData.setUseStartTLS(argParser.useStartTLSToStatus());
uData.setScriptFriendly(argParser.isScriptFriendly());
}
/**
* Tells whether the server to which the LdapContext is connected has a
* replication port or not.
* @param ctx the InitialLdapContext to be used.
* @return true if the replication port for the server could
* be found and false 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();
ReplicationSynchronizationProviderCfgClient sync = null;
sync = (ReplicationSynchronizationProviderCfgClient)
root.getSynchronizationProvider("Multimaster Synchronization");
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 in an array: note the context
* may be modified with the new credentials provided by the user.
* @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 true if everything went fine and the user accepted
* all the certificates and confirmed everything. Returns false
* 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[0]);
int port = ConnectionUtils.getPort(ctx[0]);
boolean isSSL = ConnectionUtils.isSSL(ctx[0]);
boolean isStartTLS = ConnectionUtils.isStartTLS(ctx[0]);
try
{
ADSContext adsContext = new ADSContext(ctx[0]);
if (adsContext.hasAdminData())
{
TopologyCache cache = new TopologyCache(adsContext, getTrustManager());
boolean reloadTopology = true;
LinkedList exceptionMsgs = new LinkedList();
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 exceptions =
new HashSet();
Set 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. */
boolean notGlobalAdministratorError = false;
for (TopologyCacheException e : exceptions)
{
if (notGlobalAdministratorError)
{
break;
}
switch (e.getType())
{
case NOT_GLOBAL_ADMINISTRATOR:
notGlobalAdministratorError = true;
boolean connected = false;
String adminUid = uData.getAdminUid();
String adminPwd = uData.getAdminPwd();
boolean errorDisplayed = false;
while (!connected)
{
if ((!triedWithUserProvidedAdmin) && (adminPwd == null))
{
adminUid = getValue(argParser.getAdministratorUID(),
argParser.getDefaultAdministratorUID());
adminPwd = argParser.getBindPasswordAdmin();
triedWithUserProvidedAdmin = true;
}
if (adminPwd == null)
{
if (!errorDisplayed)
{
printLineBreak();
printErrorMessage(
INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get());
errorDisplayed = true;
}
adminUid = askForAdministratorUID(
argParser.getDefaultAdministratorUID());
adminPwd = askForAdministratorPwd();
}
try
{
ctx[0].close();
}
catch (Throwable t)
{
}
try
{
ctx[0] = createContext(host, port, isSSL, isStartTLS,
ADSContext.getAdministratorDN(adminUid), adminPwd,
getTrustManager());
adsContext = new ADSContext(ctx[0]);
cache = new TopologyCache(adsContext, getTrustManager());
connected = true;
}
catch (Throwable t)
{
printLineBreak();
printErrorMessage(
ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host+":"+port, t.getMessage()));
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(),
e.getTrustManager(), e.getLdapUrl(), getTrustManager());
}
else
{
exceptionMsgs.add(Utils.getMessage(e));
}
break;
default:
exceptionMsgs.add(Utils.getMessage(e));
}
}
}
if ((exceptionMsgs.size() > 0) && !cancelled)
{
if (uData instanceof StatusReplicationUserData)
{
printWarningMessage(
ERR_REPLICATION_STATUS_READING_REGISTERED_SERVERS.get(
Utils.getMessageFromCollection(exceptionMsgs,
Constants.LINE_SEPARATOR).toString()));
printLineBreak();
}
else
{
cancelled = !confirm(
ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.
get(Utils.getMessageFromCollection(exceptionMsgs,
Constants.LINE_SEPARATOR).toString()));
}
}
}
}
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 true if we could find an administrator and
* false 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;
}
/**
* Helper type for the getCommonSuffixes method.
*/
private enum SuffixRelationType
{
NOT_REPLICATED, FULLY_REPLICATED, REPLICATED, NOT_FULLY_REPLICATED, ALL
}
/**
* 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 Collection getCommonSuffixes(
InitialLdapContext ctx1, InitialLdapContext ctx2, SuffixRelationType type)
{
LinkedList suffixes = new LinkedList();
try
{
ServerDescriptor server1 = ServerDescriptor.createStandalone(ctx1);
ServerDescriptor server2 = ServerDescriptor.createStandalone(ctx2);
Set replicas1 = server1.getReplicas();
Set replicas2 = server2.getReplicas();
for (ReplicaDescriptor rep1 : replicas1)
{
for (ReplicaDescriptor rep2 : replicas2)
{
switch (type)
{
case NOT_REPLICATED:
if (!areReplicated(rep1, rep2) &&
Utils.areDnsEqual(rep1.getSuffix().getDN(),
rep2.getSuffix().getDN()))
{
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) &&
Utils.areDnsEqual(rep1.getSuffix().getDN(),
rep2.getSuffix().getDN()))
{
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 true if we can assure that the two replicas are
* replicated using the replication server and replication port information
* and false 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 servers1 = rep1.getReplicationServers();
Set 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 true if we can assure that the two replicas are
* replicated and false 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 servers1 = rep1.getReplicationServers();
Set 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 getReplicas(InitialLdapContext ctx)
{
LinkedList suffixes =
new LinkedList();
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;
String host1 = uData.getHostName1();
String host2 = uData.getHostName2();
int port1 = uData.getPort1();
int port2 = uData.getPort2();
LinkedList errorMessages = new LinkedList();
printProgressLineBreak();
printProgressMessage(
formatter.getFormattedWithPoints(INFO_REPLICATION_CONNECTING.get()));
try
{
ctx1 = createContext(host1, port1, uData.useSSL1(), uData.useStartTLS1(),
uData.getBindDn1(), uData.getPwd1(), getTrustManager());
}
catch (NamingException ne)
{
String hostPort = host1+":"+port1;
errorMessages.add(getMessageForException(ne, hostPort));
LOG.log(Level.SEVERE, "Complete error stack:", ne);
}
try
{
ctx2 = createContext(host2, port2, uData.useSSL2(), uData.useStartTLS2(),
uData.getBindDn2(), uData.getPwd2(), getTrustManager());
}
catch (NamingException ne)
{
String hostPort = host2+":"+port2;
errorMessages.add(getMessageForException(ne, hostPort));
LOG.log(Level.SEVERE, "Complete error stack:", ne);
}
if (errorMessages.size() > 0)
{
returnValue = ERROR_CONNECTING;
}
if (errorMessages.isEmpty())
{
// This done is for the message informing that we are connecting.
printProgressMessage(formatter.getFormattedDone());
printProgressMessage(formatter.getLineBreak());
// If we are not in interactive mode do some checks...
if (!argParser.isInteractive())
{
boolean hasReplicationPort1 = hasReplicationPort(ctx1);
boolean hasReplicationPort2 = hasReplicationPort(ctx2);
int replPort1 = uData.getReplicationPort1();
int replPort2 = uData.getReplicationPort2();
if (!hasReplicationPort1)
{
if (!argParser.skipReplicationPortCheck() &&
isLocalHost(host1) &&
!SetupUtils.canUseAsPort(replPort1))
{
errorMessages.add(getCannotBindToPortError(replPort1));
}
}
if (!hasReplicationPort2)
{
if (!argParser.skipReplicationPortCheck() &&
isLocalHost(host2) &&
!SetupUtils.canUseAsPort(replPort2))
{
errorMessages.add(getCannotBindToPortError(replPort2));
}
}
if (!hasReplicationPort1 && !hasReplicationPort2 &&
(replPort1 == replPort2) &&
(host1.equalsIgnoreCase(host2)))
{
errorMessages.add(ERR_REPLICATION_SAME_REPLICATION_PORT.get(
String.valueOf(replPort1), host1));
}
if (argParser.skipReplicationPortCheck())
{
// This is something that we must do in any case... this test is
// already included when we call SetupUtils.canUseAsPort
if (replPort1 == port1)
{
errorMessages.add(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host1, String.valueOf(replPort1)));
}
if (replPort2 == port2)
{
errorMessages.add(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host2, String.valueOf(replPort2)));
}
}
}
if (errorMessages.size() > 0)
{
returnValue = ERROR_USER_DATA;
}
}
if (errorMessages.isEmpty())
{
LinkedList 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(getCriticalExceptionMessage(rce));
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;
}
}
for (Message msg : errorMessages)
{
printLineBreak();
printErrorMessage(msg);
}
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()));
String bindDn = uData.getAdminUid() == null ? uData.getBindDn() :
ADSContext.getAdministratorDN(uData.getAdminUid());
try
{
ctx = createContext(uData.getHostName(), uData.getPort(),
uData.useSSL(), uData.useStartTLS(), bindDn, 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 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(getCriticalExceptionMessage(rce));
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;
}
/**
* Displays the replication status of the baseDNs specified in the
* StatusReplicationUserData object. This method does not prompt
* to the user for information if something is missing.
* @param uData the StatusReplicationUserData object.
* @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
* successful.
* and the replication could be enabled and an error code otherwise.
*/
private ReplicationCliReturnCode statusReplication(
StatusReplicationUserData uData)
{
ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
InitialLdapContext ctx = null;
try
{
ctx = createContext(uData.getHostName(), uData.getPort(),
uData.useSSL(), uData.useStartTLS(),
ADSContext.getAdministratorDN(uData.getAdminUid()),
uData.getAdminPwd(), getTrustManager());
}
catch (NamingException ne)
{
String hostPort = uData.getHostName()+":"+uData.getPort();
printLineBreak();
printErrorMessage(getMessageForException(ne, hostPort));
LOG.log(Level.SEVERE, "Complete error stack:", ne);
}
if (ctx != null)
{
uData.setBaseDNs(uData.getBaseDNs());
try
{
displayStatus(ctx, uData);
returnValue = SUCCESSFUL;
}
catch (ReplicationCliException rce)
{
returnValue = rce.getErrorCode();
printLineBreak();
printErrorMessage(getCriticalExceptionMessage(rce));
LOG.log(Level.SEVERE, "Complete error stack:", rce);
}
}
else
{
returnValue = ERROR_CONNECTING;
}
if (ctx != null)
{
try
{
ctx.close();
}
catch (Throwable t)
{
}
}
return returnValue;
}
/**
* Initializes the contents of one server with the contents of the other
* using the parameters in the provided InitializeReplicationUserData.
* This method does not prompt to the user for information if something is
* 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 baseDNs = uData.getBaseDNs();
checkSuffixesForInitializeReplication(baseDNs, ctxSource, ctxDestination,
false);
if (!baseDNs.isEmpty())
{
for (String baseDN : baseDNs)
{
try
{
printProgressLineBreak();
Message msg = formatter.getFormattedProgress(
INFO_PROGRESS_INITIALIZING_SUFFIX.get(baseDN,
ConnectionUtils.getHostPort(ctxSource)));
printProgressMessage(msg);
printProgressLineBreak();
initializeSuffix(baseDN, ctxSource, ctxDestination, true);
}
catch (ReplicationCliException rce)
{
printLineBreak();
printErrorMessage(getCriticalExceptionMessage(rce));
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;
}
/**
* Initializes the contents of a whole topology with the contents of the other
* using the parameters in the provided InitializeAllReplicationUserData.
* This method does not prompt to the user for information if something is
* missing.
* @param uData the InitializeAllReplicationUserData object.
* @return ReplicationCliReturnCode.SUCCESSFUL if the operation was
* successful.
* and the replication could be enabled and an error code otherwise.
*/
private ReplicationCliReturnCode initializeAllReplication(
InitializeAllReplicationUserData uData)
{
ReplicationCliReturnCode returnValue = SUCCESSFUL_NOP;
InitialLdapContext ctx = null;
try
{
ctx = createContext(uData.getHostName(), uData.getPort(), uData.useSSL(),
uData.useStartTLS(),
ADSContext.getAdministratorDN(uData.getAdminUid()),
uData.getAdminPwd(), getTrustManager());
}
catch (NamingException ne)
{
String hostPort = uData.getHostName()+":"+uData.getPort();
printLineBreak();
printErrorMessage(getMessageForException(ne, hostPort));
LOG.log(Level.SEVERE, "Complete error stack:", ne);
}
if (ctx != null)
{
LinkedList baseDNs = uData.getBaseDNs();
checkSuffixesForInitializeAllReplication(baseDNs, ctx, false);
if (!baseDNs.isEmpty())
{
for (String baseDN : baseDNs)
{
try
{
printProgressLineBreak();
Message msg = formatter.getFormattedProgress(
INFO_PROGRESS_INITIALIZING_SUFFIX.get(baseDN,
ConnectionUtils.getHostPort(ctx)));
printProgressMessage(msg);
printProgressLineBreak();
initializeAllSuffix(baseDN, ctx, true);
}
catch (ReplicationCliException rce)
{
printLineBreak();
printErrorMessage(getCriticalExceptionMessage(rce));
returnValue = rce.getErrorCode();
LOG.log(Level.SEVERE, "Complete error stack:", rce);
}
}
}
else
{
returnValue = REPLICATION_CANNOT_BE_INITIALIZED_ON_BASEDN;
}
}
else
{
returnValue = ERROR_CONNECTING;
}
if (ctx != null)
{
try
{
ctx.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 suffixes,
InitialLdapContext ctx1, InitialLdapContext ctx2,
boolean interactive)
{
TreeSet availableSuffixes =
new TreeSet(getCommonSuffixes(ctx1, ctx2,
SuffixRelationType.NOT_FULLY_REPLICATED));
TreeSet alreadyReplicatedSuffixes =
new TreeSet(getCommonSuffixes(ctx1, ctx2,
SuffixRelationType.FULLY_REPLICATED));
if (availableSuffixes.size() == 0)
{
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_ENABLE_REPLICATION.get());
LinkedList userProvidedSuffixes = argParser.getBaseDNs();
TreeSet userProvidedReplicatedSuffixes = new TreeSet();
for (String s1 : userProvidedSuffixes)
{
for (String s2 : alreadyReplicatedSuffixes)
{
if (Utils.areDnsEqual(s1, s2))
{
userProvidedReplicatedSuffixes.add(s1);
}
}
}
if (userProvidedReplicatedSuffixes.size() > 0)
{
printLineBreak();
printErrorMessage(
INFO_ALREADY_REPLICATED_SUFFIXES.get(
Utils.getStringFromCollection(userProvidedReplicatedSuffixes,
Constants.LINE_SEPARATOR)));
}
suffixes.clear();
}
else
{
// Verify that the provided suffixes are configured in the servers.
TreeSet notFound = new TreeSet();
TreeSet alreadyReplicated = new TreeSet();
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())
{
boolean noSchemaOrAds = false;
for (String s: availableSuffixes)
{
if (!Utils.areDnsEqual(s, ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(s, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(s, Constants.REPLICATION_CHANGES_DN))
{
noSchemaOrAds = true;
}
}
if (!noSchemaOrAds)
{
// In interactive mode we do not propose to manage the
// administration suffix.
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_ENABLE_REPLICATION.get());
break;
}
else
{
printLineBreak();
printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_REPLICATE.get());
for (String dn : availableSuffixes)
{
if (!Utils.areDnsEqual(dn,
ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
{
if (confirm(INFO_REPLICATION_ENABLE_SUFFIX_PROMPT.get(dn)))
{
suffixes.add(dn);
}
}
}
}
}
}
}
}
/**
* 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 disabled 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 suffixes,
InitialLdapContext ctx, boolean interactive)
{
TreeSet availableSuffixes = new TreeSet();
TreeSet notReplicatedSuffixes = new TreeSet();
Collection 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 userProvidedSuffixes = argParser.getBaseDNs();
TreeSet userProvidedNotReplicatedSuffixes =
new TreeSet();
for (String s1 : userProvidedSuffixes)
{
for (String s2 : notReplicatedSuffixes)
{
if (Utils.areDnsEqual(s1, s2))
{
userProvidedNotReplicatedSuffixes.add(s1);
}
}
}
if (userProvidedNotReplicatedSuffixes.size() > 0)
{
printLineBreak();
printErrorMessage(
INFO_ALREADY_NOT_REPLICATED_SUFFIXES.get(
Utils.getStringFromCollection(
userProvidedNotReplicatedSuffixes,
Constants.LINE_SEPARATOR)));
}
suffixes.clear();
}
else
{
// Verify that the provided suffixes are configured in the servers.
TreeSet notFound = new TreeSet();
TreeSet alreadyNotReplicated = new TreeSet();
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())
{
boolean noSchemaOrAds = false;
for (String s: availableSuffixes)
{
if (!Utils.areDnsEqual(s, ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(s, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(s, Constants.REPLICATION_CHANGES_DN))
{
noSchemaOrAds = true;
}
}
if (!noSchemaOrAds)
{
// In interactive mode we do not propose to manage the
// administration suffix.
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_DISABLE_REPLICATION.get());
break;
}
else
{
printLineBreak();
printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_DISABLE.get());
for (String dn : availableSuffixes)
{
if (!Utils.areDnsEqual(dn,
ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
{
if (confirm(INFO_REPLICATION_DISABLE_SUFFIX_PROMPT.get(dn)))
{
suffixes.add(dn);
}
}
}
}
}
}
}
}
/**
* Checks that replication can actually be initialized 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 initialized 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 initialized.
*/
private void checkSuffixesForInitializeAllReplication(
Collection suffixes, InitialLdapContext ctx, boolean interactive)
{
TreeSet availableSuffixes = new TreeSet();
TreeSet notReplicatedSuffixes = new TreeSet();
Collection 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_INITIALIZE_ALL_REPLICATION.get());
LinkedList userProvidedSuffixes = argParser.getBaseDNs();
TreeSet userProvidedNotReplicatedSuffixes =
new TreeSet();
for (String s1 : userProvidedSuffixes)
{
for (String s2 : notReplicatedSuffixes)
{
if (Utils.areDnsEqual(s1, s2))
{
userProvidedNotReplicatedSuffixes.add(s1);
}
}
}
if (userProvidedNotReplicatedSuffixes.size() > 0)
{
printLineBreak();
printErrorMessage(
INFO_ALREADY_NOT_REPLICATED_SUFFIXES.get(
Utils.getStringFromCollection(
userProvidedNotReplicatedSuffixes,
Constants.LINE_SEPARATOR)));
}
suffixes.clear();
}
else
{
// Verify that the provided suffixes are configured in the servers.
TreeSet notFound = new TreeSet();
TreeSet alreadyNotReplicated = new TreeSet();
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_INITIALIZE_ALL_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())
{
boolean noSchemaOrAds = false;
for (String s: availableSuffixes)
{
if (!Utils.areDnsEqual(s, ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(s, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(s, Constants.REPLICATION_CHANGES_DN))
{
noSchemaOrAds = true;
}
}
if (!noSchemaOrAds)
{
// In interactive mode we do not propose to manage the
// administration suffix.
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_INITIALIZE_ALL_REPLICATION.get());
break;
}
else
{
printLineBreak();
printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_INITIALIZE_ALL.get());
for (String dn : availableSuffixes)
{
if (!Utils.areDnsEqual(dn,
ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
{
if (confirm(INFO_REPLICATION_INITIALIZE_ALL_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 suffixes, InitialLdapContext ctxSource,
InitialLdapContext ctxDestination, boolean interactive)
{
TreeSet availableSuffixes = new TreeSet(
getCommonSuffixes(ctxSource, ctxDestination,
SuffixRelationType.REPLICATED));
if (availableSuffixes.size() == 0)
{
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_INITIALIZE_REPLICATION.get());
suffixes.clear();
}
else
{
// Verify that the provided suffixes are configured in the servers.
LinkedList notFound = new LinkedList();
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())
{
boolean noSchemaOrAds = false;
for (String s: availableSuffixes)
{
if (!Utils.areDnsEqual(s, ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(s, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(s, Constants.REPLICATION_CHANGES_DN))
{
noSchemaOrAds = true;
}
}
if (!noSchemaOrAds)
{
// In interactive mode we do not propose to manage the
// administration suffix.
printLineBreak();
printErrorMessage(
ERR_NO_SUFFIXES_AVAILABLE_TO_INITIALIZE_REPLICATION.get());
break;
}
else
{
printLineBreak();
printErrorMessage(ERR_NO_SUFFIXES_SELECTED_TO_INITIALIZE.get());
for (String dn : availableSuffixes)
{
if (!Utils.areDnsEqual(dn,
ADSContext.getAdministrationSuffixDN()) &&
!Utils.areDnsEqual(dn, Constants.SCHEMA_DN) &&
!Utils.areDnsEqual(dn, Constants.REPLICATION_CHANGES_DN))
{
if (confirm(INFO_REPLICATION_INITIALIZE_SUFFIX_PROMPT.get(dn)))
{
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 configuration.
* @throws ReplicationCliException if there is an error.
*/
private void updateConfiguration(InitialLdapContext ctx1,
InitialLdapContext ctx2, EnableReplicationUserData uData)
throws ReplicationCliException
{
LinkedHashSet twoReplServers = new LinkedHashSet();
LinkedHashSet allRepServers = new LinkedHashSet();
HashMap> hmRepServers =
new HashMap>();
Set usedReplicationServerIds = new HashSet();
HashMap> hmUsedReplicationDomainIds =
new HashMap>();
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);
if (!argParser.isInteractive())
{
// Inform the user of the potential errors that we found in the already
// registered servers.
LinkedHashSet messages = new LinkedHashSet();
try
{
if (adsCtx1.hasAdminData())
{
TopologyCache cache = new TopologyCache(adsCtx1, getTrustManager());
cache.reloadTopology();
messages.addAll(getErrorMessages(cache));
}
if (adsCtx2.hasAdminData())
{
TopologyCache cache = new TopologyCache(adsCtx2, getTrustManager());
cache.reloadTopology();
messages.addAll(getErrorMessages(cache));
}
}
catch (TopologyCacheException tce)
{
throw new ReplicationCliException(
ERR_REPLICATION_READING_ADS.get(tce.getMessage()),
ERROR_READING_TOPOLOGY_CACHE, tce);
}
catch (ADSContextException adce)
{
throw new ReplicationCliException(
ERR_REPLICATION_READING_ADS.get(adce.getMessage()),
ERROR_READING_ADS, adce);
}
if (!messages.isEmpty())
{
printWarningMessage(
ERR_REPLICATION_READING_REGISTERED_SERVERS_WARNING.get(
Utils.getMessageFromCollection(messages,
Constants.LINE_SEPARATOR).toString()));
}
}
// These are used to identify which server we use to initialize
// the contents of the other server (if any).
InitialLdapContext ctxSource = null;
InitialLdapContext ctxDestination = null;
ADSContext adsCtxSource = null;
boolean adsAlreadyReplicated = false;
printProgressMessage(formatter.getFormattedWithPoints(
INFO_REPLICATION_ENABLE_UPDATING_ADS_CONTENTS.get()));
try
{
if (adsCtx1.hasAdminData() && adsCtx2.hasAdminData())
{
Set