/*
* 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 legal-notices/CDDLv1_0.txt
* or http://forgerock.org/license/CDDLv1.0.html.
* 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 legal-notices/CDDLv1_0.txt.
* 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-2010 Sun Microsystems, Inc.
* Portions Copyright 2011-2014 ForgeRock AS
* Portions Copyright 2012 profiq s.r.o.
*/
package org.opends.server.tools.dsreplication;
import org.opends.admin.ads.*;
import org.opends.admin.ads.ADSContext.ADSPropertySyntax;
import org.opends.admin.ads.ADSContext.AdministratorProperty;
import org.opends.admin.ads.ADSContext.ServerProperty;
import org.opends.admin.ads.util.ApplicationTrustManager;
import org.opends.admin.ads.util.ConnectionUtils;
import org.opends.admin.ads.util.PreferredConnection;
import org.opends.admin.ads.util.ServerLoader;
import org.opends.guitools.controlpanel.datamodel.BackendDescriptor;
import org.opends.guitools.controlpanel.datamodel.BaseDNDescriptor;
import org.opends.guitools.controlpanel.util.*;
import org.opends.messages.Message;
import org.opends.messages.MessageBuilder;
import org.opends.messages.MessageDescriptor.Arg0;
import org.opends.messages.MessageDescriptor.Arg1;
import org.opends.quicksetup.ApplicationException;
import org.opends.quicksetup.Constants;
import org.opends.quicksetup.Installation;
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.*;
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.ReplicationDomainCfgDefn;
import org.opends.server.admin.std.meta.ReplicationServerCfgDefn;
import org.opends.server.admin.std.meta.
ReplicationSynchronizationProviderCfgDefn;
import org.opends.server.config.ConfigException;
import org.opends.server.core.DirectoryServer;
import org.opends.server.tasks.PurgeConflictsHistoricalTask;
import org.opends.server.tools.ClientException;
import org.opends.server.tools.ToolConstants;
import org.opends.server.tools.tasks.TaskEntry;
import org.opends.server.tools.tasks.TaskScheduleInteraction;
import org.opends.server.tools.tasks.TaskScheduleUserData;
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.BuildVersion;
import org.opends.server.util.ServerConstants;
import org.opends.server.util.SetupUtils;
import org.opends.server.util.StaticUtils;
import org.opends.server.util.args.*;
import org.opends.server.util.cli.*;
import org.opends.server.util.table.TabSeparatedTablePrinter;
import org.opends.server.util.table.TableBuilder;
import org.opends.server.util.table.TablePrinter;
import org.opends.server.util.table.TextTablePrinter;
import javax.naming.NameAlreadyBoundException;
import javax.naming.NameNotFoundException;
import javax.naming.NamingEnumeration;
import javax.naming.NamingException;
import javax.naming.directory.*;
import javax.naming.ldap.InitialLdapContext;
import java.io.*;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import static org.opends.admin.ads.ServerDescriptor.*;
import static org.opends.messages.AdminToolMessages.*;
import static org.opends.messages.QuickSetupMessages.*;
import static org.opends.messages.ToolMessages.*;
import static org.opends.messages.UtilityMessages.*;
import static org.opends.quicksetup.util.Utils.*;
import static org.opends.server.tools.ToolConstants.*;
import static org.opends.server.tools.dsreplication.ReplicationCliReturnCode.*;
import static org.opends.server.util.StaticUtils.*;
/**
* 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 = "opendj-replication-";
/** Suffix for log files. */
static public final String LOG_FILE_SUFFIX = ".log";
/**
* Property used to call the dsreplication script and ReplicationCliMain to
* know which are the java properties to be used (those of dsreplication or
* those of dsreplication.offline).
*/
private static final String SCRIPT_CALL_STATUS =
"org.opends.server.dsreplicationcallstatus";
/**
* The value set by the dsreplication script if it is called the first time.
*/
private static final String FIRST_SCRIPT_CALL =
"firstcall";
private boolean forceNonInteractive;
private static final Logger LOG =
Logger.getLogger(ReplicationCliMain.class.getName());
// Always use SSL with the administration connector
private final boolean useSSL = true;
private final 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()),
/**
* Replication purge historical.
*/
PURGE_HISTORICAL(INFO_REPLICATION_PURGE_HISTORICAL_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 FileBasedArgument userProvidedAdminPwdFile;
private LDAPConnectionConsoleInteraction ci = null;
private CommandBuilder firstServerCommandBuilder;
/** 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 = NullOutputStream.wrapOrNullStream(outStream);
PrintStream err = NullOutputStream.wrapOrNullStream(errStream);
try
{
ControlPanelLog.initLogFileHandler(
File.createTempFile(LOG_FILE_PREFIX, LOG_FILE_SUFFIX));
} 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
{
createArgumenParser();
}
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)
{
try
{
argParser.getSecureArgsList().initArgumentsWithConfiguration();
}
catch (ConfigException ce)
{
// Ignore.
}
// 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 we should just display usage or version information,
// then print it and exit.
if (argParser.usageOrVersionDisplayed()) {
return 0;
}
// Checks the version - if upgrade required, the tool is unusable
try
{
BuildVersion.checkVersionMismatch();
}
catch (InitializationException e)
{
println(e.getMessageObject());
return 1;
}
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 && returnValue == SUCCESSFUL_NOP)
{
DirectoryServer.bootstrapClient();
// Bootstrap definition classes.
try
{
if (!ClassLoaderProvider.getInstance().isEnabled())
{
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)
{
if (argParser.getSecureArgsList().
bindPasswordFileArg.isPresent())
{
try
{
userProvidedAdminPwdFile = new FileBasedArgument(
"adminPasswordFile",
OPTION_SHORT_BINDPWD_FILE, "adminPasswordFile", false, false,
INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null,
INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORDFILE.get());
userProvidedAdminPwdFile.getNameToValueMap().putAll(
argParser.getSecureArgsList().
bindPasswordFileArg.getNameToValueMap());
}
catch (Throwable t)
{
throw new IllegalStateException("Unexpected error: "+t, t);
}
}
ci = new LDAPConnectionConsoleInteraction(this,
argParser.getSecureArgsList());
ci.setDisplayLdapIfSecureParameters(false);
}
if (returnValue == SUCCESSFUL_NOP)
{
boolean subcommandLaunched = true;
String subCommand = null;
if (argParser.isEnableReplicationSubcommand())
{
returnValue = enableReplication();
subCommand =
ReplicationCliArgumentParser.ENABLE_REPLICATION_SUBCMD_NAME;
}
else if (argParser.isDisableReplicationSubcommand())
{
returnValue = disableReplication();
subCommand =
ReplicationCliArgumentParser.DISABLE_REPLICATION_SUBCMD_NAME;
}
else if (argParser.isInitializeReplicationSubcommand())
{
returnValue = initializeReplication();
subCommand =
ReplicationCliArgumentParser.INITIALIZE_REPLICATION_SUBCMD_NAME;
}
else if (argParser.isInitializeAllReplicationSubcommand())
{
returnValue = initializeAllReplication();
subCommand =
ReplicationCliArgumentParser.INITIALIZE_ALL_REPLICATION_SUBCMD_NAME;
}
else if (argParser.isPreExternalInitializationSubcommand())
{
returnValue = preExternalInitialization();
subCommand =
ReplicationCliArgumentParser.PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME;
}
else if (argParser.isPostExternalInitializationSubcommand())
{
returnValue = postExternalInitialization();
subCommand =
ReplicationCliArgumentParser.POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME;
}
else if (argParser.isStatusReplicationSubcommand())
{
returnValue = statusReplication();
subCommand =
ReplicationCliArgumentParser.STATUS_REPLICATION_SUBCMD_NAME;
}
else if (argParser.isPurgeHistoricalSubcommand())
{
returnValue = purgeHistorical();
subCommand =
ReplicationCliArgumentParser.PURGE_HISTORICAL_SUBCMD_NAME;
}
else
{
if (argParser.isInteractive())
{
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;
case PURGE_HISTORICAL:
subCommand =
ReplicationCliArgumentParser.PURGE_HISTORICAL_SUBCMD_NAME;
break;
default:
// User canceled
returnValue = USER_CANCELLED;
}
if (subCommand != null)
{
String[] newArgs = new String[args.length + 1];
newArgs[0] = subCommand;
System.arraycopy(args, 0, newArgs, 1, args.length);
// The server (if requested) has already been initialized.
return execute(newArgs, false);
}
}
else
{
println(ERR_REPLICATION_VALID_SUBCOMMAND_NOT_FOUND.get(
"--"+ToolConstants.OPTION_LONG_NO_PROMPT));
println(Message.raw(argParser.getUsage()));
returnValue = ERROR_USER_DATA;
subcommandLaunched = false;
}
}
// Display the log file only if the operation is successful (when there
// is a critical error this is already displayed).
if (subcommandLaunched && (returnValue == SUCCESSFUL) &&
displayLogFileAtEnd(subCommand))
{
File logFile = ControlPanelLog.getLogFile();
if (logFile != null)
{
println();
println(INFO_GENERAL_SEE_FOR_DETAILS.get(logFile.getPath()));
println();
}
}
}
}
return returnValue.getReturnCode();
}
private boolean isFirstCallFromScript()
{
return FIRST_SCRIPT_CALL.equals(System.getProperty(SCRIPT_CALL_STATUS));
}
private void createArgumenParser() throws ArgumentException
{
argParser = new ReplicationCliArgumentParser(CLASS_NAME);
argParser.initializeParser(getOutputStream());
}
/**
* 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;
EnableReplicationUserData uData = new EnableReplicationUserData();
if (argParser.isInteractive())
{
try
{
if (promptIfRequired(uData))
{
returnValue = enableReplication(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
catch (ReplicationCliException rce)
{
returnValue = rce.getErrorCode();
println();
println(getCriticalExceptionMessage(rce));
}
}
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;
DisableReplicationUserData uData = new DisableReplicationUserData();
if (argParser.isInteractive())
{
try
{
if (promptIfRequired(uData))
{
returnValue = disableReplication(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
catch (ReplicationCliException rce)
{
returnValue = rce.getErrorCode();
println();
println(getCriticalExceptionMessage(rce));
}
}
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;
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 execute the pre external
* initialization operation.
* @return the error code if the operation failed and SUCCESSFUL if it was
* successful.
*/
private ReplicationCliReturnCode preExternalInitialization()
{
ReplicationCliReturnCode returnValue;
PreExternalInitializationUserData uData =
new PreExternalInitializationUserData();
if (argParser.isInteractive())
{
if (promptIfRequired(uData))
{
returnValue = preExternalInitialization(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
else
{
initializeWithArgParser(uData);
returnValue = preExternalInitialization(uData);
}
return returnValue;
}
/**
* Based on the data provided in the command-line execute the post external
* initialization operation.
* @return the error code if the operation failed and SUCCESSFUL if it was
* successful.
*/
private ReplicationCliReturnCode postExternalInitialization()
{
ReplicationCliReturnCode returnValue;
PostExternalInitializationUserData uData =
new PostExternalInitializationUserData();
if (argParser.isInteractive())
{
if (promptIfRequired(uData))
{
returnValue = postExternalInitialization(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
else
{
initializeWithArgParser(uData);
returnValue = postExternalInitialization(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;
StatusReplicationUserData uData = new StatusReplicationUserData();
if (argParser.isInteractive())
{
try
{
if (promptIfRequired(uData))
{
returnValue = statusReplication(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
catch (ReplicationCliException rce)
{
returnValue = rce.getErrorCode();
println();
println(getCriticalExceptionMessage(rce));
}
}
else
{
initializeWithArgParser(uData);
returnValue = statusReplication(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 purgeHistorical()
{
ReplicationCliReturnCode returnValue;
PurgeHistoricalUserData uData = new PurgeHistoricalUserData();
if (argParser.isInteractive())
{
uData = new PurgeHistoricalUserData();
if (promptIfRequired(uData))
{
returnValue = purgeHistorical(uData);
}
else
{
returnValue = USER_CANCELLED;
}
}
else
{
initializeWithArgParser(uData);
returnValue = purgeHistorical(uData);
}
return returnValue;
}
/**
* Initializes the contents of the provided purge historical replication user
* data object with what was provided in the command-line without prompting to
* the user.
* @param uData the purge historical replication user data object to be
* initialized.
*/
private void initializeWithArgParser(PurgeHistoricalUserData uData)
{
PurgeHistoricalUserData.initializeWithArgParser(uData, argParser);
}
private ReplicationCliReturnCode purgeHistorical(
PurgeHistoricalUserData uData)
{
ReplicationCliReturnCode returnValue;
if (uData.isOnline())
{
returnValue = purgeHistoricalRemotely(uData);
}
else
{
returnValue = purgeHistoricalLocally(uData);
}
return returnValue;
}
private ReplicationCliReturnCode purgeHistoricalLocally(
PurgeHistoricalUserData uData)
{
ReplicationCliReturnCode returnValue;
List baseDNs = uData.getBaseDNs();
checkSuffixesForLocalPurgeHistorical(baseDNs, false);
if (!baseDNs.isEmpty())
{
uData.setBaseDNs(baseDNs);
printPurgeHistoricalEquivalentIfRequired(uData);
try
{
returnValue = purgeHistoricalLocallyTask(uData);
}
catch (ReplicationCliException rce)
{
println();
println(getCriticalExceptionMessage(rce));
returnValue = rce.getErrorCode();
LOG.log(Level.SEVERE, "Complete error stack:", rce);
}
}
else
{
returnValue = HISTORICAL_CANNOT_BE_PURGED_ON_BASEDN;
}
return returnValue;
}
private void printPurgeProgressMessage(PurgeHistoricalUserData uData)
{
String separator = formatter.getLineBreak().toString() +
formatter.getTab().toString();
printlnProgress();
Message msg = formatter.getFormattedProgress(
INFO_PROGRESS_PURGE_HISTORICAL.get(separator,
Utils.getStringFromCollection(uData.getBaseDNs(), separator)));
printProgress(msg);
printlnProgress();
}
private ReplicationCliReturnCode purgeHistoricalLocallyTask(
PurgeHistoricalUserData uData)
throws ReplicationCliException
{
ReplicationCliReturnCode returnCode = ReplicationCliReturnCode.SUCCESSFUL;
if (isFirstCallFromScript())
{
// Launch the process: launch dsreplication in non-interactive mode with
// the recursive property set.
ArrayList args = new ArrayList();
args.add(getCommandLinePath(getCommandName()));
args.add(ReplicationCliArgumentParser.PURGE_HISTORICAL_SUBCMD_NAME);
args.add("--"+argParser.noPromptArg.getLongIdentifier());
args.add("--"+argParser.maximumDurationArg.getLongIdentifier());
args.add(String.valueOf(uData.getMaximumDuration()));
for (String baseDN : uData.getBaseDNs())
{
args.add("--"+argParser.baseDNsArg.getLongIdentifier());
args.add(baseDN);
}
ProcessBuilder pb = new ProcessBuilder(args);
// Use the java args in the script.
Map env = pb.environment();
env.put("RECURSIVE_LOCAL_CALL", "true");
try
{
Process process = pb.start();
ProcessReader outReader =
new ProcessReader(process, getOutputStream(), false);
ProcessReader errReader =
new ProcessReader(process, getErrorStream(), true);
outReader.startReading();
errReader.startReading();
int code = process.waitFor();
for (ReplicationCliReturnCode c : ReplicationCliReturnCode.values())
{
if (c.getReturnCode() == code)
{
returnCode = c;
break;
}
}
}
catch (Exception e)
{
Message msg = ERR_LAUNCHING_PURGE_HISTORICAL.get();
ReplicationCliReturnCode code = ERROR_LAUNCHING_PURGE_HISTORICAL;
throw new ReplicationCliException(
getThrowableMsg(msg, e), code, e);
}
}
else
{
printPurgeProgressMessage(uData);
LocalPurgeHistorical localPurgeHistorical =
new LocalPurgeHistorical(uData, this, formatter,
argParser.getConfigFile(),
argParser.getConfigClass());
returnCode = localPurgeHistorical.execute();
if (returnCode == ReplicationCliReturnCode.SUCCESSFUL)
{
printSuccessMessage(uData, null);
}
}
return returnCode;
}
private void printPurgeHistoricalEquivalentIfRequired(
PurgeHistoricalUserData uData)
{
if (mustPrintCommandBuilder())
{
try
{
CommandBuilder commandBuilder = createCommandBuilder(
ReplicationCliArgumentParser.PURGE_HISTORICAL_SUBCMD_NAME,
uData);
printCommandBuilder(commandBuilder);
}
catch (Throwable t)
{
LOG.log(Level.SEVERE, "Error printing equivalent command-line: "+t,
t);
}
}
}
private ReplicationCliReturnCode purgeHistoricalRemotely(
PurgeHistoricalUserData uData)
{
ReplicationCliReturnCode returnValue;
InitialLdapContext ctx = null;
// Connect to the provided server
try
{
ctx = createAdministrativeContext(uData.getHostName(), uData.getPort(),
useSSL, useStartTLS,
ADSContext.getAdministratorDN(uData.getAdminUid()),
uData.getAdminPwd(), getConnectTimeout(), getTrustManager());
}
catch (NamingException ne)
{
String hostPort =
getServerRepresentation(uData.getHostName(), uData.getPort());
println();
println(getMessageForException(ne, hostPort));
LOG.log(Level.SEVERE, "Complete error stack:", ne);
}
if (ctx != null)
{
List baseDNs = uData.getBaseDNs();
checkSuffixesForPurgeHistorical(baseDNs, ctx, false);
if (!baseDNs.isEmpty())
{
uData.setBaseDNs(baseDNs);
printPurgeHistoricalEquivalentIfRequired(uData);
try
{
returnValue = purgeHistoricalRemoteTask(ctx, uData);
}
catch (ReplicationCliException rce)
{
println();
println(getCriticalExceptionMessage(rce));
returnValue = rce.getErrorCode();
LOG.log(Level.SEVERE, "Complete error stack:", rce);
}
}
else
{
returnValue = HISTORICAL_CANNOT_BE_PURGED_ON_BASEDN;
}
}
else
{
returnValue = ERROR_CONNECTING;
}
close(ctx);
return returnValue;
}
private void printSuccessMessage(PurgeHistoricalUserData uData, String taskID)
{
printlnProgress();
if (!uData.isOnline())
{
printProgress(
INFO_PROGRESS_PURGE_HISTORICAL_FINISHED_PROCEDURE.get());
}
else if (uData.getTaskSchedule().isStartNow())
{
printProgress(INFO_TASK_TOOL_TASK_SUCESSFULL.get(
INFO_PURGE_HISTORICAL_TASK_NAME.get(),
taskID));
}
else if (uData.getTaskSchedule().getStartDate() != null)
{
printProgress(INFO_TASK_TOOL_TASK_SCHEDULED_FUTURE.get(
INFO_PURGE_HISTORICAL_TASK_NAME.get(),
taskID,
StaticUtils.formatDateTimeString(
uData.getTaskSchedule().getStartDate())));
}
else
{
printProgress(INFO_TASK_TOOL_RECURRING_TASK_SCHEDULED.get(
INFO_PURGE_HISTORICAL_TASK_NAME.get(),
taskID));
}
printlnProgress();
}
/**
* Launches the purge historical operation using the
* provided connection.
* @param ctx the connection to the server.
* @throws ReplicationCliException if there is an error performing the
* operation.
*/
private ReplicationCliReturnCode purgeHistoricalRemoteTask(
InitialLdapContext ctx,
PurgeHistoricalUserData uData)
throws ReplicationCliException
{
printPurgeProgressMessage(uData);
ReplicationCliReturnCode returnCode = ReplicationCliReturnCode.SUCCESSFUL;
boolean taskCreated = false;
boolean isOver = false;
String dn = null;
String taskID = null;
while (!taskCreated)
{
BasicAttributes attrs = PurgeHistoricalUserData.getTaskAttributes(uData);
dn = PurgeHistoricalUserData.getTaskDN(attrs);
taskID = PurgeHistoricalUserData.getTaskID(attrs);
try
{
DirContext dirCtx = ctx.createSubcontext(dn, attrs);
taskCreated = true;
LOG.log(Level.INFO, "created task entry: "+attrs);
dirCtx.close();
}
catch (NameAlreadyBoundException ex)
{
LOG.log(Level.SEVERE, "Error creating task "+attrs, ex);
Message msg = ERR_LAUNCHING_PURGE_HISTORICAL.get();
ReplicationCliReturnCode code = ERROR_LAUNCHING_PURGE_HISTORICAL;
throw new ReplicationCliException(
getThrowableMsg(msg, ex), code, ex);
}
catch (NamingException ne)
{
LOG.log(Level.SEVERE, "Error creating task "+attrs, ne);
Message msg = ERR_LAUNCHING_PURGE_HISTORICAL.get();
ReplicationCliReturnCode code = ERROR_LAUNCHING_PURGE_HISTORICAL;
throw new ReplicationCliException(
getThrowableMsg(msg, ne), code, ne);
}
}
// Wait until it is over
SearchControls searchControls = new SearchControls();
searchControls.setCountLimit(1);
searchControls.setSearchScope(
SearchControls. OBJECT_SCOPE);
String filter = "objectclass=*";
searchControls.setReturningAttributes(
new String[] {
"ds-task-log-message",
"ds-task-state",
"ds-task-purge-conflicts-historical-purged-values-count",
"ds-task-purge-conflicts-historical-purge-completed-in-time",
"ds-task-purge-conflicts-historical-purge-completed-in-time",
"ds-task-purge-conflicts-historical-last-purged-changenumber"
});
String lastLogMsg = null;
// Polling only makes sense when we are recurrently scheduling a task
// or the task is being executed now.
while (!isOver && (uData.getTaskSchedule().getStartDate() == null))
{
try
{
Thread.sleep(500);
}
catch (Throwable t)
{
}
try
{
NamingEnumeration res =
ctx.search(dn, filter, searchControls);
SearchResult sr = null;
try
{
sr = res.next();
}
finally
{
res.close();
}
String logMsg = getFirstValue(sr, "ds-task-log-message");
if (logMsg != null)
{
if (!logMsg.equals(lastLogMsg))
{
LOG.log(Level.INFO, logMsg);
lastLogMsg = logMsg;
}
}
InstallerHelper helper = new InstallerHelper();
String state = getFirstValue(sr, "ds-task-state");
if (helper.isDone(state) || helper.isStoppedByError(state))
{
isOver = true;
Message errorMsg;
String server = ConnectionUtils.getHostPort(ctx);
if (lastLogMsg == null)
{
errorMsg = INFO_ERROR_DURING_PURGE_HISTORICAL_NO_LOG.get(
state, server);
}
else
{
errorMsg = INFO_ERROR_DURING_PURGE_HISTORICAL_LOG.get(
lastLogMsg, state, server);
}
if (helper.isCompletedWithErrors(state))
{
LOG.log(Level.WARNING, "Completed with error: "+errorMsg);
println(errorMsg);
}
else if (!helper.isSuccessful(state) ||
helper.isStoppedByError(state))
{
LOG.log(Level.WARNING, "Error: "+errorMsg);
ReplicationCliReturnCode code = ERROR_LAUNCHING_PURGE_HISTORICAL;
throw new ReplicationCliException(errorMsg, code, null);
}
}
}
catch (NameNotFoundException x)
{
isOver = true;
}
catch (NamingException ne)
{
Message msg = ERR_POOLING_PURGE_HISTORICAL.get();
throw new ReplicationCliException(
getThrowableMsg(msg, ne), ERROR_CONNECTING, ne);
}
}
if (returnCode == ReplicationCliReturnCode.SUCCESSFUL)
{
printSuccessMessage(uData, taskID);
}
return returnCode;
}
/**
* Checks that historical can actually be purged in the provided baseDNs
* for the server.
* @param suffixes the suffixes provided by the user. This Collection is
* updated 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 purged.
*/
private void checkSuffixesForPurgeHistorical(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);
}
}
checkSuffixesForPurgeHistorical(suffixes, availableSuffixes,
notReplicatedSuffixes, interactive);
}
/**
* Checks that historical can actually be purged in the provided baseDNs
* for the local server.
* @param suffixes the suffixes provided by the user. This Collection is
* updated with the base DNs that the user provided interactively.
* @param interactive whether to ask the user to provide interactively
* base DNs if none of the provided base DNs can be purged.
*/
private void checkSuffixesForLocalPurgeHistorical(Collection suffixes,
boolean interactive)
{
TreeSet availableSuffixes = new TreeSet();
TreeSet notReplicatedSuffixes = new TreeSet();
Collection replicas = getLocalReplicas();
for (ReplicaDescriptor rep : replicas)
{
String dn = rep.getSuffix().getDN();
if (rep.isReplicated())
{
availableSuffixes.add(dn);
}
else
{
notReplicatedSuffixes.add(dn);
}
}
checkSuffixesForPurgeHistorical(suffixes, availableSuffixes,
notReplicatedSuffixes, interactive);
}
private Collection getLocalReplicas()
{
Collection replicas = new ArrayList();
ConfigFromFile configFromFile = new ConfigFromFile();
configFromFile.readConfiguration();
Collection backends = configFromFile.getBackends();
for (BackendDescriptor backend : backends)
{
for (BaseDNDescriptor baseDN : backend.getBaseDns())
{
SuffixDescriptor suffix = new SuffixDescriptor();
suffix.setDN(baseDN.getDn().toString());
ReplicaDescriptor replica = new ReplicaDescriptor();
if (baseDN.getType() == BaseDNDescriptor.Type.REPLICATED)
{
replica.setReplicationId(baseDN.getReplicaID());
}
else
{
replica.setReplicationId(-1);
}
replica.setBackendName(backend.getBackendID());
replica.setSuffix(suffix);
suffix.setReplicas(Collections.singleton(replica));
replicas.add(replica);
}
}
return replicas;
}
private void checkSuffixesForPurgeHistorical(Collection suffixes,
Collection availableSuffixes,
Collection notReplicatedSuffixes,
boolean interactive)
{
if (availableSuffixes.isEmpty())
{
println();
println(ERR_NO_SUFFIXES_AVAILABLE_TO_PURGE_HISTORICAL.get());
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)
{
println();
println(ERR_REPLICATION_PURGE_SUFFIXES_NOT_FOUND.get(
Utils.getStringFromCollection(notFound,
Constants.LINE_SEPARATOR)));
}
if (interactive)
{
askConfirmations(suffixes, availableSuffixes,
ERR_NO_SUFFIXES_AVAILABLE_TO_PURGE_HISTORICAL,
ERR_NO_SUFFIXES_SELECTED_TO_PURGE_HISTORICAL,
INFO_REPLICATION_PURGE_HISTORICAL_PROMPT);
}
}
}
private void askConfirmations(Collection suffixes,
Collection availableSuffixes, Arg0 noSuffixAvailableMsg,
Arg0 noSuffixSelectedMsg, Arg1 confirmationMsgPromt)
{
boolean confirmationLimitReached = false;
while (suffixes.isEmpty())
{
if (!noSchemaOrAds(availableSuffixes))
{
// In interactive mode we do not propose to manage the
// administration suffix.
println();
println(noSuffixAvailableMsg.get());
break;
}
println();
println(noSuffixSelectedMsg.get());
confirmationLimitReached =
askConfirmations(confirmationMsgPromt, availableSuffixes, suffixes,
confirmationLimitReached);
if (confirmationLimitReached)
{
suffixes.clear();
break;
}
}
}
private boolean noSchemaOrAds(Collection suffixes)
{
for (String suffix : suffixes)
{
if (isNotSchemaOrAds(suffix))
{
return true;
}
}
return false;
}
private boolean isNotSchemaOrAds(String suffix)
{
return !Utils.areDnsEqual(suffix, ADSContext.getAdministrationSuffixDN())
&& !Utils.areDnsEqual(suffix, Constants.SCHEMA_DN);
}
/**
* 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;
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 PurgeHistoricalUserData
* 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 canceled the operation.
*/
private boolean promptIfRequired(PurgeHistoricalUserData uData)
{
boolean cancelled = false;
boolean onlineSet = false;
boolean firstTry = true;
Boolean serverRunning = null;
InitialLdapContext ctx = null;
while (!cancelled && !onlineSet)
{
boolean promptForConnection = false;
if (argParser.connectionArgumentsPresent() && firstTry)
{
promptForConnection = true;
}
else
{
if (serverRunning == null)
{
serverRunning = Utilities.isServerRunning(
Installation.getLocal().getInstanceDirectory());
}
if (!serverRunning)
{
try
{
printlnProgress();
promptForConnection =
!askConfirmation(
INFO_REPLICATION_PURGE_HISTORICAL_LOCAL_PROMPT.get(),
true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
else
{
promptForConnection = true;
}
}
if (promptForConnection)
{
try
{
ci.run();
String host = ci.getHostName();
int port = ci.getPortNumber();
String adminUid = ci.getAdministratorUID();
String adminPwd = ci.getBindPassword();
ctx = createInitialLdapContextInteracting(ci);
if (ctx == null)
{
cancelled = true;
}
else
{
uData.setOnline(true);
uData.setAdminUid(adminUid);
uData.setAdminPwd(adminPwd);
uData.setHostName(host);
uData.setPort(port);
onlineSet = true;
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
ci.resetConnectionArguments();
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
}
else
{
uData.setOnline(false);
onlineSet = true;
}
firstTry = false;
}
if (!cancelled)
{
int maximumDuration = argParser.getMaximumDuration();
/* Prompt for maximum duration */
if (!argParser.maximumDurationArg.isPresent())
{
printlnProgress();
maximumDuration = askInteger(
INFO_REPLICATION_PURGE_HISTORICAL_MAXIMUM_DURATION_PROMPT.get(),
argParser.getDefaultMaximumDuration(), LOG);
}
uData.setMaximumDuration(maximumDuration);
}
if (!cancelled)
{
LinkedList suffixes = argParser.getBaseDNs();
if (uData.isOnline())
{
checkSuffixesForPurgeHistorical(suffixes, ctx, true);
}
else
{
checkSuffixesForLocalPurgeHistorical(suffixes, true);
}
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
if (uData.isOnline() && !cancelled)
{
List extends TaskEntry> taskEntries = getAvailableTaskEntries(ctx);
TaskScheduleInteraction interaction =
new TaskScheduleInteraction(uData.getTaskSchedule(), argParser.taskArgs,
this, INFO_PURGE_HISTORICAL_TASK_NAME.get());
interaction.setFormatter(formatter);
interaction.setTaskEntries(taskEntries);
try
{
interaction.run();
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
close(ctx);
return !cancelled;
}
private List extends TaskEntry> getAvailableTaskEntries(
InitialLdapContext ctx)
{
List taskEntries = new ArrayList();
List exceptions = new ArrayList();
ConfigFromDirContext cfg = new ConfigFromDirContext();
cfg.updateTaskInformation(ctx, exceptions, taskEntries);
for (OpenDsException ode : exceptions)
{
LOG.log(Level.WARNING, "Error retrieving task entries: "+ode, ode);
}
return taskEntries;
}
/**
* 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.
* @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;
Map pwdFile = null;
if (argParser.bindPassword1Arg.isPresent())
{
pwd = argParser.bindPassword1Arg.getValue();
}
else if (argParser.bindPasswordFile1Arg.isPresent())
{
pwdFile = argParser.bindPasswordFile1Arg.getNameToValueMap();
}
else if (bindDn1 == null)
{
pwd = adminPwd;
if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
{
pwdFile = argParser.getSecureArgsList().bindPasswordFileArg.
getNameToValueMap();
}
}
/*
* Use a copy of the argument properties since the map might be cleared
* in initializeGlobalArguments.
*/
ci.initializeGlobalArguments(host1, port1, adminUid,
bindDn1, pwd,
pwdFile == null ? null : new LinkedHashMap(pwdFile));
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();
ci.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();
boolean configureReplicationServer1 =
!argParser.noReplicationServer1Arg.isPresent();
boolean configureReplicationDomain1 =
!argParser.onlyReplicationServer1Arg.isPresent();
if (ctx1 != null)
{
int repPort1 = getReplicationPort(ctx1);
boolean replicationServer1Configured = repPort1 > 0;
if (replicationServer1Configured && !configureReplicationServer1)
{
try
{
if (!askConfirmation(
INFO_REPLICATION_SERVER_CONFIGURED_WARNING_PROMPT.
get(ConnectionUtils.getHostPort(ctx1), repPort1), false, LOG))
{
cancelled = true;
}
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
// Try to get the replication port for server 1 only if it is required.
if (!replicationServer1Configured && configureReplicationServer1 &&
!cancelled)
{
if (argParser.advancedArg.isPresent() &&
configureReplicationDomain1)
{
// Only ask if the replication domain will be configured (if not
// the replication server MUST be configured).
try
{
configureReplicationServer1 = askConfirmation(
INFO_REPLICATION_ENABLE_REPLICATION_SERVER1_PROMPT.get(),
true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
}
if (!cancelled &&
!replicationServer1Configured && configureReplicationServer1)
{
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(), LOG);
println();
}
if (!argParser.skipReplicationPortCheck() && Utils.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 (!cancelled &&
configureReplicationDomain1 &&
configureReplicationServer1 &&
argParser.advancedArg.isPresent())
{
// Only necessary to ask if the replication server will be configured
try
{
configureReplicationDomain1 = askConfirmation(
INFO_REPLICATION_ENABLE_REPLICATION_DOMAIN1_PROMPT.get(),
true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
// 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.
if (!cancelled)
{
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);
uData.setConfigureReplicationServer1(configureReplicationServer1);
uData.setConfigureReplicationDomain1(configureReplicationDomain1);
firstServerCommandBuilder = new CommandBuilder(null);
if (mustPrintCommandBuilder())
{
firstServerCommandBuilder.append(ci.getCommandBuilder());
}
/*
* Prompt for information on the second server.
*/
String host2 = null;
int port2 = -1;
String bindDn2 = null;
String pwd2 = null;
ci.resetHeadingDisplayed();
boolean doNotDisplayFirstError = false;
if (!cancelled)
{
host2 = argParser.getHostName2();
port2 = argParser.getPort2();
bindDn2 = argParser.getBindDn2();
pwd2 = argParser.getBindPassword2();
pwdFile = null;
pwd = null;
if (argParser.bindPassword2Arg.isPresent())
{
pwd = argParser.bindPassword2Arg.getValue();
}
else if (argParser.bindPasswordFile2Arg.isPresent())
{
pwdFile = argParser.bindPasswordFile2Arg.getNameToValueMap();
}
else if (bindDn2 == null)
{
doNotDisplayFirstError = true;
pwd = adminPwd;
if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
{
pwdFile = argParser.getSecureArgsList().bindPasswordFileArg.
getNameToValueMap();
}
}
/*
* Use a copy of the argument properties since the map might be cleared
* in initializeGlobalArguments.
*/
ci.initializeGlobalArguments(host2, port2, adminUid,
bindDn2, pwd,
pwdFile == null ? null : new LinkedHashMap(pwdFile));
}
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, true);
if (ctx2 == null)
{
cancelled = true;
}
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
if (!doNotDisplayFirstError)
{
println();
println(ce.getMessageObject());
println();
ci.resetConnectionArguments();
}
else
{
// Reset only the credential parameters.
ci.resetConnectionArguments();
ci.initializeGlobalArguments(host2, port2, null, null, null, null);
}
}
catch (ArgumentException ae)
{
LOG.log(Level.WARNING, "Argument exception "+ae);
println();
println(ae.getMessageObject());
println();
cancelled = true;
}
finally
{
doNotDisplayFirstError = false;
}
}
if (!cancelled)
{
uData.setHostName2(host2);
uData.setPort2(port2);
uData.setBindDn2(bindDn2);
uData.setPwd2(pwd2);
}
int replicationPort2 = -1;
boolean secureReplication2 = argParser.isSecureReplication2();
boolean configureReplicationServer2 =
!argParser.noReplicationServer2Arg.isPresent();
boolean configureReplicationDomain2 =
!argParser.onlyReplicationServer2Arg.isPresent();
if (ctx2 != null)
{
int repPort2 = getReplicationPort(ctx2);
boolean replicationServer2Configured = repPort2 > 0;
if (replicationServer2Configured && !configureReplicationServer2)
{
try
{
if (!askConfirmation(
INFO_REPLICATION_SERVER_CONFIGURED_WARNING_PROMPT.
get(ConnectionUtils.getHostPort(ctx2), repPort2), false, LOG))
{
cancelled = true;
}
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
// Try to get the replication port for server 2 only if it is required.
if (!replicationServer2Configured && configureReplicationServer2 &&
!cancelled)
{
// Only ask if the replication domain will be configured (if not the
// replication server MUST be configured).
if (argParser.advancedArg.isPresent() &&
configureReplicationDomain2)
{
try
{
configureReplicationServer2 = askConfirmation(
INFO_REPLICATION_ENABLE_REPLICATION_SERVER2_PROMPT.get(),
true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
if (!cancelled &&
!replicationServer2Configured && configureReplicationServer2)
{
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(), LOG);
println();
}
if (!argParser.skipReplicationPortCheck() &&
Utils.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 (!cancelled &&
configureReplicationDomain2 &&
configureReplicationServer2 &&
argParser.advancedArg.isPresent())
{
// Only necessary to ask if the replication server will be configured
try
{
configureReplicationDomain2 = askConfirmation(
INFO_REPLICATION_ENABLE_REPLICATION_DOMAIN2_PROMPT.get(),
true, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
// 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.
if (!cancelled)
{
InitialLdapContext[] aux = new InitialLdapContext[] {ctx2};
cancelled = !loadADSAndAcceptCertificates(aux, uData, false);
ctx2 = aux[0];
}
if (!cancelled)
{
administratorDefined |= hasAdministrator(ctx2);
}
}
uData.setReplicationPort2(replicationPort2);
uData.setSecureReplication2(secureReplication2);
uData.setConfigureReplicationServer2(configureReplicationServer2);
uData.setConfigureReplicationDomain2(configureReplicationDomain2);
// 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(), LOG);
println();
}
uData.setAdminUid(adminUid);
}
if (uData.getAdminPwd() == null)
{
uData.setAdminPwd(adminPwd);
}
if (!cancelled && (uData.getAdminPwd() == null) && !administratorDefined)
{
adminPwd = null;
int nPasswordPrompts = 0;
while (adminPwd == null)
{
if (nPasswordPrompts > CONFIRMATION_MAX_TRIES)
{
println(ERR_CONFIRMATION_TRIES_LIMIT_REACHED.get(
CONFIRMATION_MAX_TRIES));
cancelled = true;
break;
}
nPasswordPrompts ++;
if (!promptedForAdmin)
{
println();
println(INFO_REPLICATION_ENABLE_ADMINISTRATOR_MUST_BE_CREATED.get());
println();
}
while (adminPwd == null)
{
adminPwd = askForAdministratorPwd(LOG);
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, uData);
cancelled = suffixes.isEmpty();
uData.setBaseDNs(suffixes);
}
close(ctx1, ctx2);
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();
ci.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];
}
boolean disableAll = argParser.disableAllArg.isPresent();
boolean disableReplicationServer =
argParser.disableReplicationServerArg.isPresent();
if (disableAll ||
(argParser.advancedArg.isPresent() &&
argParser.getBaseDNs().isEmpty() &&
!disableReplicationServer))
{
try
{
disableAll = askConfirmation(INFO_REPLICATION_PROMPT_DISABLE_ALL.get(),
disableAll, LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
int repPort = getReplicationPort(ctx);
if (!disableAll &&
(argParser.advancedArg.isPresent() ||
disableReplicationServer))
{
if (repPort > 0)
{
try
{
disableReplicationServer = askConfirmation(
INFO_REPLICATION_PROMPT_DISABLE_REPLICATION_SERVER.get(repPort),
disableReplicationServer,
LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
}
if (disableReplicationServer && repPort < 0)
{
disableReplicationServer = false;
try
{
cancelled = askConfirmation(
INFO_REPLICATION_PROMPT_NO_REPLICATION_SERVER_TO_DISABLE.get(
ConnectionUtils.getHostPort(ctx)),
false,
LOG);
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
if (repPort > 0 && disableAll)
{
disableReplicationServer = true;
}
uData.setDisableAll(disableAll);
uData.setDisableReplicationServer(disableReplicationServer);
if (!cancelled && !disableAll)
{
LinkedList suffixes = argParser.getBaseDNs();
checkSuffixesForDisableReplication(suffixes, ctx, true,
!disableReplicationServer, !disableReplicationServer);
cancelled = suffixes.isEmpty() && !disableReplicationServer;
uData.setBaseDNs(suffixes);
if (!uData.disableReplicationServer() && repPort > 0 &&
disableAllBaseDns(ctx, uData) && !argParser.advancedArg.isPresent())
{
try
{
uData.setDisableReplicationServer(askConfirmation(
INFO_REPLICATION_DISABLE_ALL_SUFFIXES_DISABLE_REPLICATION_SERVER.get(
ConnectionUtils.getHostPort(ctx), repPort), true, LOG));
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
}
}
if (!cancelled)
{
// Ask for confirmation to disable if not already done.
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 (!uData.disableAll() &&
!uData.getBaseDNs().isEmpty())
{
cancelled = !askConfirmation(
INFO_REPLICATION_CONFIRM_DISABLE_GENERIC.get(), true,
LOG);
}
}
catch (CLIException ce)
{
println(ce.getMessageObject());
cancelled = true;
}
println();
}
}
close(ctx);
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();
ci.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();
}
}
close(ctx);
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();
ci.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);
}
close(ctx);
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();
ci.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);
}
close(ctx);
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();
ci.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);
}
close(ctx);
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();
Map pwdFile = null;
if (argParser.getSecureArgsList().bindPasswordFileArg.isPresent())
{
pwdFile =
argParser.getSecureArgsList().bindPasswordFileArg.
getNameToValueMap();
}
/*
* Use a copy of the argument properties since the map might be cleared
* in initializeGlobalArguments.
*/
ci.initializeGlobalArguments(hostSource, portSource, adminUid, null,
adminPwd,
pwdFile == null ? null : new LinkedHashMap(pwdFile));
/*
* 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();
ci.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);
}
firstServerCommandBuilder = new CommandBuilder(null);
if (mustPrintCommandBuilder())
{
firstServerCommandBuilder.append(ci.getCommandBuilder());
}
/* Prompt for destination server credentials */
String hostDestination = argParser.getHostNameDestination();
int portDestination = argParser.getPortDestination();
/*
* Use a copy of the argument properties since the map might be cleared
* in initializeGlobalArguments.
*/
ci.initializeGlobalArguments(hostDestination, portDestination,
adminUid, null, adminPwd,
pwdFile == null ? null : new LinkedHashMap(pwdFile));
/*
* 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();
boolean error = false;
if (hostSource.equalsIgnoreCase(hostDestination))
{
if (portSource == portDestination)
{
portDestination = -1;
Message message = ERR_REPLICATION_INITIALIZE_SAME_SERVER_PORT.get(
hostSource, String.valueOf(portSource));
println();
println(message);
println();
error = true;
}
}
if (!error)
{
ctxDestination = createInitialLdapContextInteracting(ci, true);
if (ctxDestination == null)
{
cancelled = true;
}
}
}
catch (ClientException ce)
{
LOG.log(Level.WARNING, "Client exception "+ce);
println();
println(ce.getMessageObject());
println();
ci.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();
}
}
close(ctxSource, ctxDestination);
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())
{
trust = ci.getTrustManager();
}
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, getConnectTimeout(), 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);
}
}
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, getConnectTimeout(), 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);
}
}
uData.setSecureReplication2(argParser.isSecureReplication2());
uData.setReplicateSchema(!argParser.noSchemaReplication());
uData.setConfigureReplicationDomain1(
!argParser.onlyReplicationServer1Arg.isPresent());
uData.setConfigureReplicationDomain2(
!argParser.onlyReplicationServer2Arg.isPresent());
uData.setConfigureReplicationServer1(
!argParser.noReplicationServer1Arg.isPresent());
uData.setConfigureReplicationServer2(
!argParser.noReplicationServer2Arg.isPresent());
int replicationPort1 = getValue(argParser.getReplicationPort1(),
argParser.getDefaultReplicationPort1());
if (uData.configureReplicationServer1())
{
uData.setReplicationPort1(replicationPort1);
}
int replicationPort2 = getValue(argParser.getReplicationPort2(),
argParser.getDefaultReplicationPort2());
if (uData.configureReplicationServer2())
{
uData.setReplicationPort2(replicationPort2);
}
}
/**
* 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.getBindDNToDisable();
if ((bindDn == null) && (adminUid == null))
{
adminUid = argParser.getDefaultAdministratorUID();
bindDn = ADSContext.getAdministratorDN(adminUid);
}
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.setDisableAll(argParser.disableAllArg.isPresent());
uData.setDisableReplicationServer(
argParser.disableReplicationServerArg.isPresent());
}
/**
* 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);
}
/**
* 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 status 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 =
(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 LDAPConnectionConsoleInteraction.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(), getConnectTimeout());
cache.getFilter().setSearchMonitoringInformation(false);
cache.getFilter().setSearchBaseDNInformation(false);
cache.setPreferredConnections(
PreferredConnection.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(), LOG);
println();
adminPwd = askForAdministratorPwd(LOG);
println();
}
close(ctx[0]);
try
{
ctx[0] = createAdministrativeContext(host, port, isSSL,
isStartTLS, ADSContext.getAdministratorDN(adminUid),
adminPwd, getConnectTimeout(), getTrustManager());
adsContext = new ADSContext(ctx[0]);
cache = new TopologyCache(adsContext, getTrustManager(),
getConnectTimeout());
cache.getFilter().setSearchMonitoringInformation(false);
cache.getFilter().setSearchBaseDNInformation(false);
cache.setPreferredConnections(
PreferredConnection.getPreferredConnections(ctx[0]));
connected = true;
}
catch (Throwable t)
{
println();
println(
ERR_ERROR_CONNECTING_TO_SERVER_PROMPT_AGAIN.get(
getServerRepresentation(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