/*
* 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
*
*
* Copyright 2007-2008 Sun Microsystems, Inc.
*/
package org.opends.server.tools.dsreplication;
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.tools.dsreplication.ReplicationCliReturnCode.*;
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.Date;
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 javax.net.ssl.TrustManager;
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.TopologyCacheFilter;
import org.opends.admin.ads.ADSContext.ADSPropertySyntax;
import org.opends.admin.ads.ADSContext.AdministratorProperty;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionUtils;
import org.opends.admin.ads.util.PreferredConnection;
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.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.Installer;
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.tools.ClientException;
import org.opends.server.tools.ToolConstants;
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;
import org.opends.server.util.cli.CLIException;
import org.opends.server.util.cli.ConsoleApplication;
import org.opends.server.util.cli.LDAPConnectionConsoleInteraction;
import org.opends.server.util.cli.MenuBuilder;
import org.opends.server.util.cli.MenuResult;
import org.opends.server.util.table.TableBuilder;
import org.opends.server.util.table.TextTablePrinter;
/**
* 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 ConsoleApplication
{
/**
* 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 boolean forceNonInteractive;
private static final Logger LOG =
Logger.getLogger(ReplicationCliMain.class.getName());
// Always use SSL with the administration connector
private boolean useSSL = true;
private boolean useStartTLS = false;
/**
* The enumeration containing the different options we display when we ask
* the user to provide the subcommand interactively.
*/
private enum SubcommandChoice
{
/**
* Enable replication.
*/
ENABLE(INFO_REPLICATION_ENABLE_MENU_PROMPT.get()),
/**
* Disable replication.
*/
DISABLE(INFO_REPLICATION_DISABLE_MENU_PROMPT.get()),
/**
* Initialize replication.
*/
INITIALIZE(INFO_REPLICATION_INITIALIZE_MENU_PROMPT.get()),
/**
* Initialize All.
*/
INITIALIZE_ALL(INFO_REPLICATION_INITIALIZE_ALL_MENU_PROMPT.get()),
/**
* Pre external initialization.
*/
PRE_EXTERNAL_INITIALIZATION(
INFO_REPLICATION_PRE_EXTERNAL_INITIALIZATION_MENU_PROMPT.get()),
/**
* Post external initialization.
*/
POST_EXTERNAL_INITIALIZATION(
INFO_REPLICATION_POST_EXTERNAL_INITIALIZATION_MENU_PROMPT.get()),
/**
* Replication status.
*/
STATUS(INFO_REPLICATION_STATUS_MENU_PROMPT.get()),
/**
* Cancel operation.
*/
CANCEL(null);
private Message prompt;
private SubcommandChoice(Message prompt)
{
this.prompt = prompt;
}
Message getPrompt()
{
return prompt;
}
};
// The argument parser to be used.
private ReplicationCliArgumentParser argParser;
private LDAPConnectionConsoleInteraction ci = null;
// 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(in, out, err);
}
/**
* The main method for the replication tool.
*
* @param args the command-line arguments provided to this program.
*/
public static void main(String[] args)
{
int retCode = mainCLI(args, true, System.out, System.err, 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(getOutputStream());
}
catch (ArgumentException ae)
{
Message message =
ERR_CANNOT_INITIALIZE_ARGS.get(ae.getMessage());
println(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());
println(message);
println();
println(Message.raw(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)
{
println(buf.toMessage());
println(Message.raw(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)
{
println(ie.getMessageObject());
returnValue = ERROR_INITIALIZING_ADMINISTRATION_FRAMEWORK;
}
}
if (returnValue == SUCCESSFUL_NOP)
{
ci = new LDAPConnectionConsoleInteraction(this,
argParser.getSecureArgsList());
ci.setDisplayLdapIfSecureParameters(
!argParser.isInitializeAllReplicationSubcommand() &&
!argParser.isPreExternalInitializationSubcommand() ||
!argParser.isPostExternalInitializationSubcommand());
}
if (returnValue == SUCCESSFUL_NOP)
{
boolean subcommandLaunched = true;
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.isPreExternalInitializationSubcommand())
{
returnValue = preExternalInitialization();
}
else if (argParser.isPostExternalInitializationSubcommand())
{
returnValue = postExternalInitialization();
}
else if (argParser.isStatusReplicationSubcommand())
{
returnValue = statusReplication();
}
else
{
if (argParser.isInteractive())
{
String subCommand = null;
switch (promptForSubcommand())
{
case ENABLE:
subCommand =
ReplicationCliArgumentParser.ENABLE_REPLICATION_SUBCMD_NAME;
break;
case DISABLE:
subCommand =
ReplicationCliArgumentParser.DISABLE_REPLICATION_SUBCMD_NAME;
break;
case INITIALIZE:
subCommand =
ReplicationCliArgumentParser.INITIALIZE_REPLICATION_SUBCMD_NAME;
break;
case INITIALIZE_ALL:
subCommand =
ReplicationCliArgumentParser.
INITIALIZE_ALL_REPLICATION_SUBCMD_NAME;
break;
case PRE_EXTERNAL_INITIALIZATION:
subCommand = ReplicationCliArgumentParser.
PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME;
break;
case POST_EXTERNAL_INITIALIZATION:
subCommand = ReplicationCliArgumentParser.
POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME;
break;
case STATUS:
subCommand =
ReplicationCliArgumentParser.STATUS_REPLICATION_SUBCMD_NAME;
break;
default:
// User cancelled
returnValue = USER_CANCELLED;
}
if (subCommand != null)
{
String[] newArgs = new String[args.length + 1];
newArgs[0] = subCommand;
for (int i=0; itrue if the object was successfully updated and
* false if the user cancelled the operation.
* @throws ReplicationCliException if a critical error occurs reading the
* ADS.
*/
private boolean promptIfRequired(EnableReplicationUserData uData)
throws ReplicationCliException
{
boolean cancelled = false;
boolean administratorDefined = false;
ci.setUseAdminOrBindDn(true);
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
/*
* Try to connect to the first server.
*/
String host1 = argParser.getHostName1();
int port1 = argParser.getPort1();
String bindDn1 = argParser.getBindDn1();
String pwd1 = argParser.getBindPassword1();
String pwd = null;
if (pwd1 != null)
{
pwd = pwd1;
}
else if (bindDn1 != null)
{
pwd = null;
}
else
{
pwd = adminPwd;
}
initializeGlobalArguments(host1, port1, adminUid,
bindDn1, pwd);
InitialLdapContext ctx1 = null;
while ((ctx1 == null) && !cancelled)
{
try
{
ci.setHeadingMessage(
INFO_REPLICATION_ENABLE_HOST1_CONNECTION_PARAMETERS.get());
ci.run();
host1 = ci.getHostName();
port1 = ci.getPortNumber();
if (ci.getProvidedAdminUID() != null)
{
adminUid = ci.getProvidedAdminUID();
if (ci.getProvidedBindDN() == null)
{
// If the explicit bind DN is not null, the password corresponds
// to that bind DN. We are in the case where the user provides
// bind DN on first server and admin UID globally.
adminPwd = ci.getBindPassword();
}
}
bindDn1 = ci.getBindDN();
pwd1 = ci.getBindPassword();
ctx1 = createInitialLdapContextInteracting(ci);
if (ctx1 == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName1(host1);
uData.setPort1(port1);
uData.setBindDn1(bindDn1);
uData.setPwd1(pwd1);
}
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 = askPort(
INFO_REPLICATION_ENABLE_REPLICATIONPORT1_PROMPT.get(),
argParser.getDefaultReplicationPort1());
println();
}
if (!argParser.skipReplicationPortCheck() && isLocalHost(host1))
{
if (!SetupUtils.canUseAsPort(replicationPort1))
{
println();
println(getCannotBindToPortError(replicationPort1));
println();
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)
{
println();
println(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host1, String.valueOf(replicationPort1)));
println();
replicationPort1 = -1;
}
}
}
if (!secureReplication1)
{
try
{
secureReplication1 =
askConfirmation(INFO_REPLICATION_ENABLE_SECURE1_PROMPT.get(
String.valueOf(replicationPort1)), false, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
// 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);
if (uData.getAdminPwd() != null)
{
adminPwd = uData.getAdminPwd();
}
}
}
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;
ci.resetHeadingDisplayed();
if (!cancelled)
{
host2 = argParser.getHostName2();
port2 = argParser.getPort2();
bindDn2 = argParser.getBindDn2();
pwd2 = argParser.getBindPassword2();
if (pwd2 != null)
{
pwd = pwd2;
}
else if (bindDn2 != null)
{
pwd = null;
}
else
{
pwd = adminPwd;
}
initializeGlobalArguments(host2, port2, adminUid,
bindDn2, pwd);
}
InitialLdapContext ctx2 = null;
while ((ctx2 == null) && !cancelled)
{
try
{
ci.setHeadingMessage(
INFO_REPLICATION_ENABLE_HOST2_CONNECTION_PARAMETERS.get());
ci.run();
host2 = ci.getHostName();
port2 = ci.getPortNumber();
if (ci.getProvidedAdminUID() != null)
{
adminUid = ci.getProvidedAdminUID();
if (ci.getProvidedBindDN() == null)
{
// If the explicit bind DN is not null, the password corresponds
// to that bind DN. We are in the case where the user provides
// bind DN on first server and admin UID globally.
adminPwd = ci.getBindPassword();
}
}
bindDn2 = ci.getBindDN();
pwd2 = ci.getBindPassword();
boolean error = false;
if (host1.equalsIgnoreCase(host2))
{
if (port1 == port2)
{
port2 = -1;
Message message = ERR_REPLICATION_ENABLE_SAME_SERVER_PORT.get(
host1, String.valueOf(port1));
println();
println(message);
println();
error = true;
}
}
if (!error)
{
ctx2 = createInitialLdapContextInteracting(ci);
if (ctx2 == null)
{
cancelled = true;
}
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName2(host2);
uData.setPort2(port2);
uData.setBindDn2(bindDn2);
uData.setPwd2(pwd2);
}
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 = askPort(
INFO_REPLICATION_ENABLE_REPLICATIONPORT2_PROMPT.get(),
argParser.getDefaultReplicationPort2());
println();
}
if (!argParser.skipReplicationPortCheck() && isLocalHost(host2))
{
if (!SetupUtils.canUseAsPort(replicationPort2))
{
println();
println(getCannotBindToPortError(replicationPort2));
println();
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)
{
println();
println(
ERR_REPLICATION_PORT_AND_REPLICATION_PORT_EQUAL.get(
host2, String.valueOf(replicationPort2)));
replicationPort2 = -1;
}
}
if (host1.equalsIgnoreCase(host2))
{
if ((replicationPort1 > 0) &&
(replicationPort1 == replicationPort2))
{
println();
println(ERR_REPLICATION_SAME_REPLICATION_PORT.get(
String.valueOf(replicationPort2), host1));
println();
replicationPort2 = -1;
}
}
}
if (!secureReplication2)
{
try
{
secureReplication2 =
askConfirmation(INFO_REPLICATION_ENABLE_SECURE2_PROMPT.get(
String.valueOf(replicationPort2)), false, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
// 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)
{
println(INFO_REPLICATION_ENABLE_ADMINISTRATOR_MUST_BE_CREATED.get());
promptedForAdmin = true;
adminUid= askForAdministratorUID(
argParser.getDefaultAdministratorUID());
println();
}
uData.setAdminUid(adminUid);
}
if (uData.getAdminPwd() == null)
{
uData.setAdminPwd(adminPwd);
}
if (!cancelled && (uData.getAdminPwd() == null) && !administratorDefined)
{
adminPwd = null;
while (adminPwd == null)
{
if (!promptedForAdmin)
{
println();
println(INFO_REPLICATION_ENABLE_ADMINISTRATOR_MUST_BE_CREATED.get());
println();
}
while (adminPwd == null)
{
adminPwd = askForAdministratorPwd();
println();
}
String adminPwdConfirm = null;
while (adminPwdConfirm == null)
{
adminPwdConfirm =
readPassword(INFO_ADMINISTRATOR_PWD_CONFIRM_PROMPT.get(), LOG);
println();
}
if (!adminPwd.equals(adminPwdConfirm))
{
println();
println(ERR_ADMINISTRATOR_PWD_DO_NOT_MATCH.get());
println();
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.
* @throws ReplicationCliException if there is a critical error reading the
* ADS.
*/
private boolean promptIfRequired(DisableReplicationUserData uData)
throws ReplicationCliException
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String bindDn = argParser.getBindDNToDisable();
// This is done because we want to ask explicitly for this
String host = argParser.getHostNameToDisable();
int port = argParser.getPortToDisable();
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ci.setUseAdminOrBindDn(true);
ci.run();
host = ci.getHostName();
port = ci.getPortNumber();
bindDn = ci.getProvidedBindDN();
adminUid = ci.getProvidedAdminUID();
adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
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)
{
println();
try
{
cancelled = !askConfirmation(INFO_REPLICATION_CONFIRM_DISABLE_ADS.get(
ADSContext.getAdministrationSuffixDN()), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
if (disableSchema)
{
println();
try
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_DISABLE_SCHEMA.get(), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
if (!disableSchema && !disableADS)
{
println();
try
{
if (disableAllBaseDns(ctx, uData))
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_DISABLE_LAST_SUFFIXES.get(), true,
LOG);
}
else
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_DISABLE_GENERIC.get(), true, LOG);
}
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
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();
int port = argParser.getPortToInitializeAll();
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ci.setHeadingMessage(
INFO_REPLICATION_INITIALIZE_SOURCE_CONNECTION_PARAMETERS.get());
ci.run();
host = ci.getHostName();
port = ci.getPortNumber();
adminUid = ci.getAdministratorUID();
adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForInitializeReplication(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)
{
println();
try
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_INITIALIZE_ALL_ADS.get(
ADSContext.getAdministrationSuffixDN(), hostPortSource), true,
LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
else
{
println();
try
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_INITIALIZE_ALL_GENERIC.get(
hostPortSource), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
if (ctx != null)
{
try
{
ctx.close();
}
catch (Throwable t)
{
}
}
return !cancelled;
}
/**
* Updates the contents of the provided PreExternalInitializationUserData
* 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(PreExternalInitializationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String host = argParser.getHostNameToInitializeAll();
int port = argParser.getPortToInitializeAll();
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ci.run();
host = ci.getHostName();
port = ci.getPortNumber();
adminUid = ci.getAdministratorUID();
adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
boolean localOnly = false;
if (!argParser.isExternalInitializationLocalOnly())
{
println();
try
{
localOnly = askConfirmation(
INFO_REPLICATION_PRE_EXTERNAL_INITIALIZATION_LOCAL_PROMPT.get(
ConnectionUtils.getHostPort(ctx)), false, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
else
{
localOnly = true;
}
uData.setLocalOnly(localOnly);
uData.setHostName(host);
uData.setPort(port);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForInitializeReplication(suffixes, ctx, true);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
if (ctx != null)
{
try
{
ctx.close();
}
catch (Throwable t)
{
}
}
return !cancelled;
}
/**
* Updates the contents of the provided PostExternalInitializationUserData
* 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(PostExternalInitializationUserData uData)
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String host = argParser.getHostNameToInitializeAll();
int port = argParser.getPortToInitializeAll();
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ci.run();
host = ci.getHostName();
port = ci.getPortNumber();
adminUid = ci.getAdministratorUID();
adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForInitializeReplication(suffixes, ctx, true);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
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.
* @throws ReplicationCliException if a critical error occurs reading the
* ADS.
*/
private boolean promptIfRequired(StatusReplicationUserData uData)
throws ReplicationCliException
{
boolean cancelled = false;
String adminPwd = argParser.getBindPasswordAdmin();
String adminUid = argParser.getAdministratorUID();
String host = argParser.getHostNameToStatus();
int port = argParser.getPortToStatus();
/*
* Try to connect to the server.
*/
InitialLdapContext ctx = null;
while ((ctx == null) && !cancelled)
{
try
{
ci.run();
host = ci.getHostName();
port = ci.getPortNumber();
adminUid = ci.getAdministratorUID();
adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostName(host);
uData.setPort(port);
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();
String hostSource = argParser.getHostNameSource();
int portSource = argParser.getPortSource();
initializeGlobalArguments(hostSource, portSource, adminUid, null, adminPwd);
/*
* Try to connect to the source server.
*/
InitialLdapContext ctxSource = null;
while ((ctxSource == null) && !cancelled)
{
try
{
ci.setHeadingMessage(
INFO_REPLICATION_INITIALIZE_SOURCE_CONNECTION_PARAMETERS.get());
ci.run();
hostSource = ci.getHostName();
portSource = ci.getPortNumber();
adminUid = ci.getAdministratorUID();
adminPwd = ci.getBindPassword();
ctxSource = createInitialLdapContextInteracting(ci);
if (ctxSource == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
if (!cancelled)
{
uData.setHostNameSource(hostSource);
uData.setPortSource(portSource);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
}
/* Prompt for destination server credentials */
String hostDestination = argParser.getHostNameDestination();
int portDestination = argParser.getPortDestination();
initializeGlobalArguments(hostDestination, portDestination,
adminUid, null, adminPwd);
/*
* Try to connect to the destination server.
*/
InitialLdapContext ctxDestination = null;
ci.resetHeadingDisplayed();
while ((ctxDestination == null) && !cancelled)
{
try
{
ci.setHeadingMessage(
INFO_REPLICATION_INITIALIZE_DESTINATION_CONNECTION_PARAMETERS.get());
ci.run();
hostDestination = ci.getHostName();
portDestination = ci.getPortNumber();
ctxDestination = createInitialLdapContextInteracting(ci);
if (ctxDestination == null)
{
cancelled = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
} if (!cancelled)
{
uData.setHostNameDestination(hostDestination);
uData.setPortDestination(portDestination);
}
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)
{
println();
try
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_INITIALIZE_ADS.get(
ADSContext.getAdministrationSuffixDN(), hostPortDestination,
hostPortSource), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
else
{
println();
try
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_INITIALIZE_GENERIC.get(
hostPortDestination, hostPortSource), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
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()
{
ApplicationTrustManager trust;
if (isInteractive())
{
TrustManager t = ci.getTrustManager();
if (t == null)
{
trust = null;
}
else if (t instanceof ApplicationTrustManager)
{
trust = (ApplicationTrustManager)t;
}
else
{
trust = new ApplicationTrustManager(ci.getKeyStore());
}
}
else
{
trust = argParser.getTrustManager();
}
return trust;
}
/**
* 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);
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 = createAdministrativeContext(
uData.getHostName1(), uData.getPort1(), useSSL,
useStartTLS, 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);
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 = createAdministrativeContext(
uData.getHostName2(), uData.getPort2(), useSSL,
useStartTLS, 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);
String hostNameDestination = getValue(
argParser.getHostNameDestination(),
argParser.getDefaultHostNameDestination());
uData.setHostNameDestination(hostNameDestination);
int portDestination = getValue(argParser.getPortDestination(),
argParser.getDefaultPortDestination());
uData.setPortDestination(portDestination);
}
/**
* 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);
}
/**
* 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 initialize all 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);
}
/**
* Initializes the contents of the provided pre external replication user
* data object with what was provided in the command-line without prompting to
* the user.
* @param uData the pre external replication user data object to be
* initialized.
*/
private void initializeWithArgParser(PreExternalInitializationUserData 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.setLocalOnly(argParser.isExternalInitializationLocalOnly());
}
/**
* Initializes the contents of the provided post external replication user
* data object with what was provided in the command-line without prompting to
* the user.
* @param uData the pre external replication user data object to be
* initialized.
*/
private void initializeWithArgParser(PostExternalInitializationUserData 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);
}
/**
* 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.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.
* @throws ReplicationCliException if a critical error occurred.
* @return true if everything went fine and the user accepted
* all the certificates and confirmed everything. Returns false
* if the user did not accept a certificate or any of the confirmation
* messages.
*/
private boolean loadADSAndAcceptCertificates(InitialLdapContext[] ctx,
ReplicationUserData uData, boolean isFirstOrSourceServer)
throws ReplicationCliException
{
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]);
if (getTrustManager() == null)
{
// This is required when the user did connect to the server using SSL or
// Start TLS. In this case LDAPConnectionInteraction.run does not
// initialize the keystore and the trust manager is null.
forceTrustManagerInitialization();
}
try
{
ADSContext adsContext = new ADSContext(ctx[0]);
if (adsContext.hasAdminData())
{
boolean reloadTopology = true;
LinkedList exceptionMsgs = new LinkedList();
while (reloadTopology && !cancelled)
{
// We must recreate the cache because the trust manager in the
// LDAPConnectionConsoleInteraction object might have changed.
TopologyCache cache = new TopologyCache(adsContext,
getTrustManager());
cache.getFilter().setSearchMonitoringInformation(false);
cache.getFilter().setSearchBaseDNInformation(false);
cache.setPreferredConnections(getPreferredConnections(ctx[0]));
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)
{
println();
println(
INFO_NOT_GLOBAL_ADMINISTRATOR_PROVIDED.get());
errorDisplayed = true;
}
adminUid = askForAdministratorUID(
argParser.getDefaultAdministratorUID());
println();
adminPwd = askForAdministratorPwd();
println();
}
try
{
ctx[0].close();
}
catch (Throwable t)
{
}
try
{
ctx[0] = createAdministrativeContext(host, port, isSSL,
isStartTLS, ADSContext.getAdministratorDN(adminUid),
adminPwd, getTrustManager());
adsContext = new ADSContext(ctx[0]);
cache = new TopologyCache(adsContext, getTrustManager());
cache.getFilter().setSearchMonitoringInformation(false);
cache.getFilter().setSearchBaseDNInformation(false);
cache.setPreferredConnections(
getPreferredConnections(ctx[0]));
connected = true;
}
catch (Throwable t)
{
println();
println(
ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
host+":"+port, t.getMessage()));
LOG.log(Level.WARNING, "Complete error stack:", t);
println();
}
}
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 = !ci.promptForCertificateConfirmation(e.getCause(),
e.getTrustManager(), e.getLdapUrl(), true, LOG);
}
else
{
exceptionMsgs.add(Utils.getMessage(e));
}
break;
default:
exceptionMsgs.add(Utils.getMessage(e));
}
}
}
if ((exceptionMsgs.size() > 0) && !cancelled)
{
if (uData instanceof StatusReplicationUserData)
{
println(
ERR_REPLICATION_STATUS_READING_REGISTERED_SERVERS.get(
Utils.getMessageFromCollection(exceptionMsgs,
Constants.LINE_SEPARATOR).toString()));
println();
}
else
{
try
{
cancelled = !askConfirmation(
ERR_REPLICATION_READING_REGISTERED_SERVERS_CONFIRM_UPDATE_REMOTE.
get(Utils.getMessageFromCollection(exceptionMsgs,
Constants.LINE_SEPARATOR).toString()), true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
}
}
}
catch (ADSContextException ace)
{
LOG.log(Level.SEVERE, "Complete error stack:", ace);
throw new ReplicationCliException(
ERR_REPLICATION_READING_ADS.get(ace.getMessage()),
ERROR_READING_ADS, ace);
}
catch (TopologyCacheException tce)
{
LOG.log(Level.SEVERE, "Complete error stack:", tce);
throw new ReplicationCliException(
ERR_REPLICATION_READING_ADS.get(tce.getMessage()),
ERROR_READING_TOPOLOGY_CACHE, tce);
}
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;
}
/**
* Tells whether there is a Global Administrator corresponding to the provided
* ReplicationUserData defined in the server to which the InitialLdapContext
* is connected.
* @param ctx the InitialLdapContext.
* @param uData the user data
* @return true if we could find an administrator and
* false otherwise.
*/
private boolean hasAdministrator(InitialLdapContext ctx,
ReplicationUserData uData)
{
boolean isAdminDefined = false;
String adminUid = uData.getAdminUid();
try
{
ADSContext adsContext = new ADSContext(ctx);
Set