001/* 002 * CDDL HEADER START 003 * 004 * The contents of this file are subject to the terms of the 005 * Common Development and Distribution License, Version 1.0 only 006 * (the "License"). You may not use this file except in compliance 007 * with the License. 008 * 009 * You can obtain a copy of the license at legal-notices/CDDLv1_0.txt 010 * or http://forgerock.org/license/CDDLv1.0.html. 011 * See the License for the specific language governing permissions 012 * and limitations under the License. 013 * 014 * When distributing Covered Code, include this CDDL HEADER in each 015 * file and include the License file at legal-notices/CDDLv1_0.txt. 016 * If applicable, add the following below this CDDL HEADER, with the 017 * fields enclosed by brackets "[]" replaced with your own identifying 018 * information: 019 * Portions Copyright [yyyy] [name of copyright owner] 020 * 021 * CDDL HEADER END 022 * 023 * 024 * Copyright 2007-2010 Sun Microsystems, Inc. 025 * Portions Copyright 2012-2015 ForgeRock AS. 026 */ 027package org.opends.server.tools.dsreplication; 028 029import static com.forgerock.opendj.cli.ArgumentConstants.*; 030import static com.forgerock.opendj.cli.Utils.*; 031 032import static org.opends.messages.AdminToolMessages.*; 033import static org.opends.messages.ToolMessages.*; 034 035import java.io.File; 036import java.io.OutputStream; 037import java.util.ArrayList; 038import java.util.Collection; 039import java.util.LinkedList; 040 041import org.forgerock.i18n.LocalizableMessage; 042import org.forgerock.i18n.LocalizableMessageBuilder; 043import org.opends.quicksetup.Constants; 044import org.opends.server.admin.AdministrationConnector; 045import org.opends.server.admin.client.cli.SecureConnectionCliArgs; 046import org.opends.server.admin.client.cli.SecureConnectionCliParser; 047import org.opends.server.admin.client.cli.TaskScheduleArgs; 048import org.opends.server.core.DirectoryServer.DirectoryServerVersionHandler; 049import org.opends.server.extensions.ConfigFileHandler; 050import org.opends.server.tasks.PurgeConflictsHistoricalTask; 051 052import com.forgerock.opendj.cli.Argument; 053import com.forgerock.opendj.cli.ArgumentException; 054import com.forgerock.opendj.cli.ArgumentGroup; 055import com.forgerock.opendj.cli.BooleanArgument; 056import com.forgerock.opendj.cli.ClientException; 057import com.forgerock.opendj.cli.CommonArguments; 058import com.forgerock.opendj.cli.FileBasedArgument; 059import com.forgerock.opendj.cli.IntegerArgument; 060import com.forgerock.opendj.cli.StringArgument; 061import com.forgerock.opendj.cli.SubCommand; 062 063/** 064 * This class is used to parse the arguments passed to the replication CLI. 065 * It also checks the compatibility between the values and that all the 066 * required information has been provided. However it does not do any 067 * verification that require connection to any server. 068 */ 069public class ReplicationCliArgumentParser extends SecureConnectionCliParser 070{ 071 /** Arguments used when enabling replication for a server. */ 072 static class ServerArgs 073 { 074 /** The 'hostName' argument for the first server. */ 075 StringArgument hostNameArg; 076 /** The 'port' argument for the first server. */ 077 IntegerArgument portArg; 078 /** The 'bindDN' argument for the first server. */ 079 StringArgument bindDnArg; 080 /** The 'bindPasswordFile' argument for the first server. */ 081 FileBasedArgument bindPasswordFileArg; 082 /** The 'bindPassword' argument for the first server. */ 083 StringArgument bindPasswordArg; 084 /** The 'replicationPort' argument for the first server. */ 085 IntegerArgument replicationPortArg; 086 /** The 'noReplicationServer' argument for the first server. */ 087 BooleanArgument noReplicationServerArg; 088 /** The 'onlyReplicationServer' argument for the first server. */ 089 BooleanArgument onlyReplicationServerArg; 090 /** The 'secureReplication' argument for the first server. */ 091 BooleanArgument secureReplicationArg; 092 093 094 /** 095 * Get the password which has to be used for the command to connect to this server without 096 * prompting the user in the enable replication subcommand. If no password was specified return 097 * null. 098 * 099 * @return the password which has to be used for the command to connect to this server without 100 * prompting the user in the enable replication subcommand. If no password was specified 101 * return null. 102 */ 103 String getBindPassword() 104 { 105 return ReplicationCliArgumentParser.getBindPassword(bindPasswordArg, bindPasswordFileArg); 106 } 107 108 boolean configureReplicationDomain() 109 { 110 return !onlyReplicationServerArg.isPresent(); 111 } 112 113 boolean configureReplicationServer() 114 { 115 return !noReplicationServerArg.isPresent(); 116 } 117 } 118 119 private SubCommand enableReplicationSubCmd; 120 private SubCommand disableReplicationSubCmd; 121 private SubCommand initializeReplicationSubCmd; 122 private SubCommand initializeAllReplicationSubCmd; 123 private SubCommand postExternalInitializationSubCmd; 124 private SubCommand preExternalInitializationSubCmd; 125 private SubCommand resetChangelogNumber; 126 private SubCommand statusReplicationSubCmd; 127 private SubCommand purgeHistoricalSubCmd; 128 129 private int defaultAdminPort = 130 AdministrationConnector.DEFAULT_ADMINISTRATION_CONNECTOR_PORT; 131 132 /** No-prompt argument. */ 133 BooleanArgument noPromptArg; 134 private String defaultLocalHostValue; 135 136 /** Arguments for the first server. */ 137 ServerArgs server1 = new ServerArgs(); 138 /** Arguments for the second server. */ 139 ServerArgs server2 = new ServerArgs(); 140 141 /** The 'skipPortCheckArg' argument to not check replication ports. */ 142 private BooleanArgument skipPortCheckArg; 143 /** The 'noSchemaReplication' argument to not replicate schema. */ 144 BooleanArgument noSchemaReplicationArg; 145 /** The 'useSecondServerAsSchemaSource' argument to not replicate schema. */ 146 private BooleanArgument useSecondServerAsSchemaSourceArg; 147 /** The 'disableAll' argument to disable all the replication configuration of server. */ 148 BooleanArgument disableAllArg; 149 /** The 'disableReplicationServer' argument to disable the replication server. */ 150 BooleanArgument disableReplicationServerArg; 151 /** The 'hostName' argument for the source server. */ 152 private StringArgument hostNameSourceArg; 153 /** The 'port' argument for the source server. */ 154 private IntegerArgument portSourceArg; 155 /** The 'hostName' argument for the destination server. */ 156 private StringArgument hostNameDestinationArg; 157 /** The 'port' argument for the destination server. */ 158 private IntegerArgument portDestinationArg; 159 /** The 'suffixes' global argument. */ 160 StringArgument baseDNsArg; 161 /**The 'quiet' argument. */ 162 private BooleanArgument quietArg; 163 /**The 'scriptFriendly' argument. */ 164 BooleanArgument scriptFriendlyArg; 165 /**Properties file argument. */ 166 StringArgument propertiesFileArgument; 167 /**No-properties file argument. */ 168 BooleanArgument noPropertiesFileArgument; 169 /** 170 * The argument that the user must set to display the equivalent 171 * non-interactive mode argument. 172 */ 173 BooleanArgument displayEquivalentArgument; 174 /** 175 * The argument that allows the user to dump the equivalent non-interactive 176 * command to a file. 177 */ 178 StringArgument equivalentCommandFileArgument; 179 /** The argument that the user must set to have advanced options in interactive mode. */ 180 BooleanArgument advancedArg; 181 182 /** 183 * The argument set by the user to specify the configuration class 184 * (useful when dsreplication purge-historical runs locally). 185 */ 186 private StringArgument configClassArg; 187 188 /** 189 * The argument set by the user to specify the configuration file 190 * (useful when dsreplication purge-historical runs locally). 191 */ 192 private StringArgument configFileArg; 193 194 TaskScheduleArgs taskArgs; 195 196 /** The 'maximumDuration' argument for the purge of historical. */ 197 IntegerArgument maximumDurationArg; 198 199 /** the 'change-number' argument for task reset-changenumber. */ 200 IntegerArgument resetChangeNumber; 201 202 /** The text of the enable replication subcommand. */ 203 static final String ENABLE_REPLICATION_SUBCMD_NAME = "enable"; 204 /** The text of the disable replication subcommand. */ 205 static final String DISABLE_REPLICATION_SUBCMD_NAME = "disable"; 206 /** The text of the initialize replication subcommand. */ 207 static final String INITIALIZE_REPLICATION_SUBCMD_NAME = "initialize"; 208 /** The text of the initialize all replication subcommand. */ 209 public static final String INITIALIZE_ALL_REPLICATION_SUBCMD_NAME = "initialize-all"; 210 /** The text of the pre external initialization subcommand. */ 211 static final String PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME = "pre-external-initialization"; 212 /** The text of the initialize all replication subcommand. */ 213 static final String POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME = "post-external-initialization"; 214 /** The text of the reset changenumber subcommand. */ 215 static final String RESET_CHANGE_NUMBER_SUBCMD_NAME = "reset-change-number"; 216 217 /** The text of the status replication subcommand. */ 218 static final String STATUS_REPLICATION_SUBCMD_NAME = "status"; 219 /** The text of the purge historical subcommand. */ 220 static final String PURGE_HISTORICAL_SUBCMD_NAME = "purge-historical"; 221 /** This CLI is always using the administration connector with SSL. */ 222 private static final boolean alwaysSSL = true; 223 224 /** 225 * Creates a new instance of this argument parser with no arguments. 226 * 227 * @param mainClassName 228 * The fully-qualified name of the Java class that should 229 * be invoked to launch the program with which this 230 * argument parser is associated. 231 */ 232 ReplicationCliArgumentParser(String mainClassName) 233 { 234 super(mainClassName, 235 INFO_REPLICATION_TOOL_DESCRIPTION.get(ENABLE_REPLICATION_SUBCMD_NAME, INITIALIZE_REPLICATION_SUBCMD_NAME), 236 false); 237 setShortToolDescription(REF_SHORT_DESC_DSREPLICATION.get()); 238 setVersionHandler(new DirectoryServerVersionHandler()); 239 } 240 241 /** 242 * Initialize the parser with the Global options and subcommands. 243 * 244 * @param outStream 245 * The output stream to use for standard output, or {@code null} 246 * if standard output is not needed. 247 * @throws ArgumentException 248 * If there is a problem with any of the parameters used to create this argument. 249 */ 250 void initializeParser(OutputStream outStream) 251 throws ArgumentException 252 { 253 taskArgs = new TaskScheduleArgs(); 254 initializeGlobalArguments(outStream); 255 try 256 { 257 defaultAdminPort = secureArgsList.getAdminPortFromConfig(); 258 } 259 catch (Throwable t) 260 { 261 // Ignore 262 } 263 createEnableReplicationSubCommand(); 264 createDisableReplicationSubCommand(); 265 createRelatedServersOptions(); 266 createInitializeReplicationSubCommand(); 267 createInitializeAllReplicationSubCommand(); 268 createPreExternalInitializationSubCommand(); 269 createPostExternalInitializationSubCommand(); 270 createResetChangeNumberSubCommand(); 271 createStatusReplicationSubCommand(); 272 createPurgeHistoricalSubCommand(); 273 } 274 275 /** 276 * Checks all the options parameters and updates the provided LocalizableMessageBuilder 277 * with the errors that where encountered. 278 * 279 * This method assumes that the method parseArguments for the parser has 280 * already been called. 281 * @param buf the LocalizableMessageBuilder object where we add the error messages 282 * describing the errors encountered. 283 */ 284 void validateOptions(LocalizableMessageBuilder buf) 285 { 286 validateGlobalOptions(buf); 287 validateSubcommandOptions(buf); 288 } 289 290 /** {@inheritDoc} */ 291 @Override 292 public int validateGlobalOptions(LocalizableMessageBuilder buf) 293 { 294 int returnValue; 295 super.validateGlobalOptions(buf); 296 ArrayList<LocalizableMessage> errors = new ArrayList<>(); 297 if (secureArgsList.bindPasswordArg.isPresent() && 298 secureArgsList.bindPasswordFileArg.isPresent()) { 299 LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get( 300 secureArgsList.bindPasswordArg.getLongIdentifier(), 301 secureArgsList.bindPasswordFileArg.getLongIdentifier()); 302 errors.add(message); 303 } 304 305 // Check that we can write on the provided path where we write the 306 // equivalent non-interactive commands. 307 if (equivalentCommandFileArgument.isPresent()) 308 { 309 String file = equivalentCommandFileArgument.getValue(); 310 if (!canWrite(file)) 311 { 312 errors.add(ERR_REPLICATION_CANNOT_WRITE_EQUIVALENT_COMMAND_LINE_FILE.get(file)); 313 } 314 else 315 { 316 File f = new File(file); 317 if (f.isDirectory()) 318 { 319 errors.add( 320 ERR_REPLICATION_EQUIVALENT_COMMAND_LINE_FILE_DIRECTORY.get(file)); 321 } 322 } 323 } 324 325 if (noPromptArg.isPresent() && advancedArg.isPresent()) 326 { 327 LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get( 328 noPromptArg.getLongIdentifier(), 329 advancedArg.getLongIdentifier()); 330 errors.add(message); 331 } 332 333 if (!isInteractive()) 334 { 335 // Check that we have the required data 336 if (!baseDNsArg.isPresent() && 337 !isStatusReplicationSubcommand() && 338 !isResetChangeNumber() && 339 !disableAllArg.isPresent() && 340 !disableReplicationServerArg.isPresent()) 341 { 342 errors.add(ERR_REPLICATION_NO_BASE_DN_PROVIDED.get()); 343 } 344 if (getBindPasswordAdmin() == null && 345 !isPurgeHistoricalSubcommand()) 346 { 347 errors.add(ERR_REPLICATION_NO_ADMINISTRATOR_PASSWORD_PROVIDED.get( 348 "--"+secureArgsList.bindPasswordArg.getLongIdentifier(), 349 "--"+secureArgsList.bindPasswordFileArg.getLongIdentifier())); 350 } 351 } 352 353 if (baseDNsArg.isPresent()) 354 { 355 LinkedList<String> baseDNs = baseDNsArg.getValues(); 356 for (String dn : baseDNs) 357 { 358 if (!isDN(dn)) 359 { 360 errors.add(ERR_REPLICATION_NOT_A_VALID_BASEDN.get(dn)); 361 } 362 if (dn.equalsIgnoreCase(Constants.REPLICATION_CHANGES_DN)) 363 { 364 errors.add(ERR_REPLICATION_NOT_A_USER_SUFFIX.get(Constants.REPLICATION_CHANGES_DN)); 365 } 366 } 367 } 368 if (!errors.isEmpty()) 369 { 370 for (LocalizableMessage error : errors) 371 { 372 addMessage(buf, error); 373 } 374 } 375 376 if (buf.length() > 0) 377 { 378 returnValue = ReplicationCliReturnCode.CONFLICTING_ARGS.getReturnCode(); 379 } 380 else 381 { 382 returnValue = ReplicationCliReturnCode.SUCCESSFUL_NOP.getReturnCode(); 383 } 384 return returnValue; 385 } 386 387 /** 388 * Initialize Global option. 389 * 390 * @param outStream 391 * The output stream used for the usage. 392 * @throws ArgumentException 393 * If there is a problem with any of the parameters used 394 * to create this argument. 395 */ 396 private void initializeGlobalArguments(OutputStream outStream) 397 throws ArgumentException 398 { 399 ArrayList<Argument> defaultArgs = new ArrayList<>(createGlobalArguments(outStream, alwaysSSL)); 400 401 Argument[] argsToRemove = { 402 secureArgsList.hostNameArg, 403 secureArgsList.portArg, 404 secureArgsList.bindDnArg, 405 secureArgsList.bindPasswordFileArg, 406 secureArgsList.bindPasswordArg 407 }; 408 409 for (Argument arg : argsToRemove) 410 { 411 defaultArgs.remove(arg); 412 } 413 defaultArgs.remove(super.noPropertiesFileArg); 414 defaultArgs.remove(super.propertiesFileArg); 415 // Remove it from the default location and redefine it. 416 defaultArgs.remove(getAdminUidArg()); 417 418 int index = 0; 419 420 baseDNsArg = new StringArgument("baseDNs", OPTION_SHORT_BASEDN, 421 OPTION_LONG_BASEDN, false, true, true, INFO_BASEDN_PLACEHOLDER.get(), 422 null, 423 null, INFO_DESCRIPTION_REPLICATION_BASEDNS.get()); 424 baseDNsArg.setPropertyName(OPTION_LONG_BASEDN); 425 defaultArgs.add(index++, baseDNsArg); 426 427 secureArgsList.adminUidArg = new StringArgument("adminUID", 'I', 428 OPTION_LONG_ADMIN_UID, false, false, true, 429 INFO_ADMINUID_PLACEHOLDER.get(), 430 Constants.GLOBAL_ADMIN_UID, null, 431 INFO_DESCRIPTION_REPLICATION_ADMIN_UID.get( 432 ENABLE_REPLICATION_SUBCMD_NAME)); 433 getAdminUidArg().setPropertyName(OPTION_LONG_ADMIN_UID); 434 getAdminUidArg().setHidden(false); 435 defaultArgs.add(index++, getAdminUidArg()); 436 437 secureArgsList.bindPasswordArg = new StringArgument( 438 OPTION_LONG_ADMIN_PWD.toLowerCase(), 439 OPTION_SHORT_BINDPWD, OPTION_LONG_ADMIN_PWD, false, false, true, 440 INFO_BINDPWD_PLACEHOLDER.get(), null, null, 441 INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORD.get()); 442 defaultArgs.add(index++, secureArgsList.bindPasswordArg); 443 444 secureArgsList.bindPasswordFileArg = new FileBasedArgument( 445 OPTION_LONG_ADMIN_PWD_FILE.toLowerCase(), 446 OPTION_SHORT_BINDPWD_FILE, OPTION_LONG_ADMIN_PWD_FILE, false, false, 447 INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null, 448 INFO_DESCRIPTION_REPLICATION_ADMIN_BINDPASSWORDFILE.get()); 449 defaultArgs.add(index++, secureArgsList.bindPasswordFileArg); 450 451 defaultArgs.remove(verboseArg); 452 453 quietArg = CommonArguments.getQuiet(); 454 defaultArgs.add(index++, quietArg); 455 456 noPromptArg = CommonArguments.getNoPrompt(); 457 defaultArgs.add(index++, noPromptArg); 458 459 displayEquivalentArgument = CommonArguments.getDisplayEquivalentCommand(); 460 461 defaultArgs.add(index++, displayEquivalentArgument); 462 463 equivalentCommandFileArgument = 464 CommonArguments 465 .getEquivalentCommandFile( 466 INFO_REPLICATION_DESCRIPTION_EQUIVALENT_COMMAND_FILE_PATH.get()); 467 defaultArgs.add(index++, equivalentCommandFileArgument); 468 469 advancedArg = CommonArguments.getAdvancedMode(); 470 defaultArgs.add(index++, advancedArg); 471 472 configClassArg = 473 CommonArguments.getConfigClass(ConfigFileHandler.class.getName()); 474 defaultArgs.add(index++, configClassArg); 475 476 configFileArg = CommonArguments.getConfigFile(); 477 defaultArgs.add(index++, configFileArg); 478 479 for (int i=0; i<index; i++) 480 { 481 Argument arg = defaultArgs.get(i); 482 arg.setPropertyName(arg.getLongIdentifier()); 483 } 484 485 this.propertiesFileArgument = CommonArguments.getPropertiesFile(); 486 defaultArgs.add(this.propertiesFileArgument); 487 setFilePropertiesArgument(this.propertiesFileArgument); 488 489 this.noPropertiesFileArgument = CommonArguments.getNoPropertiesFile(); 490 defaultArgs.add(this.noPropertiesFileArgument); 491 setNoPropertiesFileArgument(this.noPropertiesFileArgument); 492 493 initializeGlobalArguments(defaultArgs, null); 494 } 495 496 /** 497 * Initialize the global options with the provided set of arguments. 498 * @param args the arguments to use to initialize the global options. 499 * @param argGroup the group to which args will be added. 500 * @throws ArgumentException if there is a conflict with the provided 501 * arguments. 502 */ 503 @Override 504 protected void initializeGlobalArguments( 505 Collection<Argument> args, 506 ArgumentGroup argGroup) 507 throws ArgumentException 508 { 509 510 for (Argument arg : args) 511 { 512 if (arg == advancedArg) 513 { 514 ArgumentGroup toolOptionsGroup = new ArgumentGroup( 515 INFO_DESCRIPTION_CONFIG_OPTIONS_ARGS.get(), 2); 516 addGlobalArgument(advancedArg, toolOptionsGroup); 517 } 518 else 519 { 520 addGlobalArgument(arg, argGroup); 521 } 522 } 523 524 // Set the propertiesFile argument 525 setFilePropertiesArgument(propertiesFileArg); 526 } 527 528 /** 529 * Creates the enable replication subcommand and all the specific options 530 * for the subcommand. 531 */ 532 private void createEnableReplicationSubCommand() throws ArgumentException 533 { 534 createServerArgs1(); 535 createServerArgs2(); 536 537 skipPortCheckArg = new BooleanArgument( 538 "skipportcheck", 'S', "skipPortCheck", 539 INFO_DESCRIPTION_ENABLE_REPLICATION_SKIPPORT.get()); 540 541 noSchemaReplicationArg = new BooleanArgument( 542 "noschemareplication", null, "noSchemaReplication", 543 INFO_DESCRIPTION_ENABLE_REPLICATION_NO_SCHEMA_REPLICATION.get()); 544 545 useSecondServerAsSchemaSourceArg = new BooleanArgument( 546 "usesecondserverasschemasource", null, "useSecondServerAsSchemaSource", 547 INFO_DESCRIPTION_ENABLE_REPLICATION_USE_SECOND_AS_SCHEMA_SOURCE.get( 548 "--"+noSchemaReplicationArg.getLongIdentifier())); 549 550 enableReplicationSubCmd = new SubCommand(this, 551 ENABLE_REPLICATION_SUBCMD_NAME, 552 INFO_DESCRIPTION_SUBCMD_ENABLE_REPLICATION.get()); 553 554 Argument[] argsToAdd = { 555 server1.hostNameArg, server1.portArg, server1.bindDnArg, server1.bindPasswordArg, 556 server1.bindPasswordFileArg, server1.replicationPortArg, server1.secureReplicationArg, 557 server1.noReplicationServerArg, server1.onlyReplicationServerArg, 558 server2.hostNameArg, server2.portArg, server2.bindDnArg, server2.bindPasswordArg, 559 server2.bindPasswordFileArg, server2.replicationPortArg, server2.secureReplicationArg, 560 server2.noReplicationServerArg, server2.onlyReplicationServerArg, 561 skipPortCheckArg, noSchemaReplicationArg, useSecondServerAsSchemaSourceArg 562 }; 563 for (Argument arg : argsToAdd) 564 { 565 arg.setPropertyName(arg.getLongIdentifier()); 566 enableReplicationSubCmd.addArgument(arg); 567 } 568 } 569 570 private void createServerArgs1() throws ArgumentException 571 { 572 ServerArgs server = server1; 573 server.hostNameArg = new StringArgument("host1", OPTION_SHORT_HOST, 574 "host1", false, false, true, INFO_HOST_PLACEHOLDER.get(), 575 getDefaultHostValue(), 576 null, INFO_DESCRIPTION_ENABLE_REPLICATION_HOST1.get()); 577 578 server.portArg = new IntegerArgument("port1", OPTION_SHORT_PORT, "port1", 579 false, false, true, INFO_PORT_PLACEHOLDER.get(), 580 defaultAdminPort, null, 581 true, 1, 582 true, 65336, 583 INFO_DESCRIPTION_ENABLE_REPLICATION_SERVER_PORT1.get()); 584 585 server.bindDnArg = new StringArgument("bindDN1", OPTION_SHORT_BINDDN, 586 "bindDN1", false, false, true, INFO_BINDDN_PLACEHOLDER.get(), 587 "cn=Directory Manager", null, 588 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDDN1.get()); 589 590 server.bindPasswordArg = new StringArgument("bindPassword1", 591 null, "bindPassword1", false, false, true, 592 INFO_BINDPWD_PLACEHOLDER.get(), null, null, 593 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORD1.get()); 594 595 server.bindPasswordFileArg = new FileBasedArgument("bindPasswordFile1", 596 null, "bindPasswordFile1", false, false, 597 INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null, 598 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORDFILE1.get()); 599 600 server.replicationPortArg = new IntegerArgument("replicationPort1", 'r', 601 "replicationPort1", false, false, true, INFO_PORT_PLACEHOLDER.get(), 602 8989, null, 603 true, 1, 604 true, 65336, 605 INFO_DESCRIPTION_ENABLE_REPLICATION_PORT1.get()); 606 607 server.secureReplicationArg = new BooleanArgument("secureReplication1", null, 608 "secureReplication1", 609 INFO_DESCRIPTION_ENABLE_SECURE_REPLICATION1.get()); 610 611 server.noReplicationServerArg = new BooleanArgument( 612 "noreplicationserver1", null, "noReplicationServer1", 613 INFO_DESCRIPTION_ENABLE_REPLICATION_NO_REPLICATION_SERVER1.get()); 614 615 server.onlyReplicationServerArg = new BooleanArgument( 616 "onlyreplicationserver1", null, "onlyReplicationServer1", 617 INFO_DESCRIPTION_ENABLE_REPLICATION_ONLY_REPLICATION_SERVER1.get()); 618 } 619 620 private void createServerArgs2() throws ArgumentException 621 { 622 ServerArgs server = server2; 623 server.hostNameArg = new StringArgument("host2", 'O', 624 "host2", false, false, true, INFO_HOST_PLACEHOLDER.get(), 625 getDefaultHostValue(), 626 null, INFO_DESCRIPTION_ENABLE_REPLICATION_HOST2.get()); 627 628 server.portArg = new IntegerArgument("port2", null, "port2", 629 false, false, true, INFO_PORT_PLACEHOLDER.get(), defaultAdminPort, null, 630 true, 1, 631 true, 65336, 632 INFO_DESCRIPTION_ENABLE_REPLICATION_SERVER_PORT2.get()); 633 634 server.bindDnArg = new StringArgument("bindDN2", null, 635 "bindDN2", false, false, true, INFO_BINDDN_PLACEHOLDER.get(), 636 "cn=Directory Manager", null, 637 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDDN2.get()); 638 639 server.bindPasswordArg = new StringArgument("bindPassword2", 640 null, "bindPassword2", false, false, true, 641 INFO_BINDPWD_PLACEHOLDER.get(), null, null, 642 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORD2.get()); 643 644 server.bindPasswordFileArg = new FileBasedArgument("bindPasswordFile2", 645 'F', "bindPasswordFile2", false, false, 646 INFO_BINDPWD_FILE_PLACEHOLDER.get(), null, null, 647 INFO_DESCRIPTION_ENABLE_REPLICATION_BINDPASSWORDFILE2.get()); 648 649 server.replicationPortArg = new IntegerArgument("replicationPort2", 'R', 650 "replicationPort2", false, false, true, INFO_PORT_PLACEHOLDER.get(), 651 8989, null, 652 true, 1, 653 true, 65336, 654 INFO_DESCRIPTION_ENABLE_REPLICATION_PORT2.get()); 655 656 server.secureReplicationArg = new BooleanArgument("secureReplication2", null, 657 "secureReplication2", 658 INFO_DESCRIPTION_ENABLE_SECURE_REPLICATION2.get()); 659 660 server.noReplicationServerArg = new BooleanArgument( 661 "noreplicationserver2", null, "noReplicationServer2", 662 INFO_DESCRIPTION_ENABLE_REPLICATION_NO_REPLICATION_SERVER2.get()); 663 664 server.onlyReplicationServerArg = new BooleanArgument( 665 "onlyreplicationserver2", null, "onlyReplicationServer2", 666 INFO_DESCRIPTION_ENABLE_REPLICATION_ONLY_REPLICATION_SERVER2.get()); 667 } 668 669 /** 670 * Creates the disable replication subcommand and all the specific options 671 * for the subcommand. Note: this method assumes that 672 * initializeGlobalArguments has already been called and that hostNameArg and 673 * portArg have been created. 674 */ 675 private void createDisableReplicationSubCommand() 676 throws ArgumentException 677 { 678 disableReplicationSubCmd = new SubCommand(this, 679 DISABLE_REPLICATION_SUBCMD_NAME, 680 INFO_DESCRIPTION_SUBCMD_DISABLE_REPLICATION.get()); 681 secureArgsList.hostNameArg.setDefaultValue(getDefaultHostValue()); 682 secureArgsList.bindDnArg = new StringArgument("bindDN", OPTION_SHORT_BINDDN, 683 OPTION_LONG_BINDDN, false, false, true, INFO_BINDDN_PLACEHOLDER.get(), 684 "cn=Directory Manager", OPTION_LONG_BINDDN, 685 INFO_DESCRIPTION_DISABLE_REPLICATION_BINDDN.get()); 686 disableReplicationServerArg = new BooleanArgument( 687 "disablereplicationserver", null, "disableReplicationServer", 688 INFO_DESCRIPTION_DISABLE_REPLICATION_SERVER.get()); 689 disableAllArg = new BooleanArgument( 690 "disableall", 'a', "disableAll", 691 INFO_DESCRIPTION_DISABLE_ALL.get()); 692 693 694 Argument[] argsToAdd = { secureArgsList.hostNameArg, 695 secureArgsList.portArg, secureArgsList.bindDnArg, 696 disableReplicationServerArg, disableAllArg}; 697 for (Argument arg : argsToAdd) 698 { 699 disableReplicationSubCmd.addArgument(arg); 700 } 701 } 702 703 /** 704 * Creates the initialize replication subcommand and all the specific options 705 * for the subcommand. 706 */ 707 private void createInitializeReplicationSubCommand() throws ArgumentException 708 { 709 initializeReplicationSubCmd = new SubCommand(this, INITIALIZE_REPLICATION_SUBCMD_NAME, 710 INFO_DESCRIPTION_SUBCMD_INITIALIZE_REPLICATION.get(INITIALIZE_ALL_REPLICATION_SUBCMD_NAME)); 711 712 Argument[] argsToAdd = { 713 hostNameSourceArg, portSourceArg, hostNameDestinationArg, portDestinationArg 714 }; 715 setSubCommandArguments(initializeReplicationSubCmd, argsToAdd); 716 } 717 718 private void createRelatedServersOptions() throws ArgumentException 719 { 720 hostNameSourceArg = new StringArgument("hostSource", OPTION_SHORT_HOST, 721 "hostSource", false, false, true, INFO_HOST_PLACEHOLDER.get(), 722 getDefaultHostValue(), null, 723 INFO_DESCRIPTION_INITIALIZE_REPLICATION_HOST_SOURCE.get()); 724 725 portSourceArg = new IntegerArgument("portSource", OPTION_SHORT_PORT, 726 "portSource", false, false, true, INFO_PORT_PLACEHOLDER.get(), 727 defaultAdminPort, null, 728 true, 1, 729 true, 65336, 730 INFO_DESCRIPTION_INITIALIZE_REPLICATION_SERVER_PORT_SOURCE.get()); 731 732 hostNameDestinationArg = new StringArgument("hostDestination", 'O', 733 "hostDestination", false, false, true, INFO_HOST_PLACEHOLDER.get(), 734 getDefaultHostValue(), null, 735 INFO_DESCRIPTION_INITIALIZE_REPLICATION_HOST_DESTINATION.get()); 736 737 portDestinationArg = new IntegerArgument("portDestination", null, 738 "portDestination", false, false, true, INFO_PORT_PLACEHOLDER.get(), 739 defaultAdminPort, 740 null, 741 true, 1, 742 true, 65336, 743 INFO_DESCRIPTION_INITIALIZE_REPLICATION_SERVER_PORT_DESTINATION.get()); 744 } 745 746 /** 747 * Creates the initialize all replication subcommand and all the specific 748 * options for the subcommand. Note: this method assumes that 749 * initializeGlobalArguments has already been called and that hostNameArg and 750 * portArg have been created. 751 */ 752 private void createInitializeAllReplicationSubCommand() 753 throws ArgumentException 754 { 755 initializeAllReplicationSubCmd = new SubCommand(this, 756 INITIALIZE_ALL_REPLICATION_SUBCMD_NAME, 757 INFO_DESCRIPTION_SUBCMD_INITIALIZE_ALL_REPLICATION.get( 758 INITIALIZE_REPLICATION_SUBCMD_NAME)); 759 secureArgsList.hostNameArg.setDefaultValue(getDefaultHostValue()); 760 Argument[] argsToAdd = { secureArgsList.hostNameArg, 761 secureArgsList.portArg }; 762 for (Argument arg : argsToAdd) 763 { 764 initializeAllReplicationSubCmd.addArgument(arg); 765 } 766 } 767 768 /** 769 * Creates the subcommand that the user must launch before doing an external 770 * initialization of the topology ( and all the specific 771 * options for the subcommand. Note: this method assumes that 772 * initializeGlobalArguments has already been called and that hostNameArg and 773 * portArg have been created. 774 */ 775 private void createPreExternalInitializationSubCommand() 776 throws ArgumentException 777 { 778 preExternalInitializationSubCmd = new SubCommand(this, 779 PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME, 780 INFO_DESCRIPTION_SUBCMD_PRE_EXTERNAL_INITIALIZATION.get( 781 POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME)); 782 secureArgsList.hostNameArg.setDefaultValue(getDefaultHostValue()); 783 BooleanArgument externalInitializationLocalOnlyArg = new BooleanArgument( 784 "local-only", 785 'l', 786 "local-only", 787 LocalizableMessage.EMPTY); 788 externalInitializationLocalOnlyArg.setHidden(true); 789 790 Argument[] argsToAdd = { secureArgsList.hostNameArg, 791 secureArgsList.portArg, 792 externalInitializationLocalOnlyArg}; 793 794 for (Argument arg : argsToAdd) 795 { 796 preExternalInitializationSubCmd.addArgument(arg); 797 } 798 } 799 800 /** 801 * Creates the subcommand that the user must launch after doing an external 802 * initialization of the topology ( and all the specific 803 * options for the subcommand. Note: this method assumes that 804 * initializeGlobalArguments has already been called and that hostNameArg and 805 * portArg have been created. 806 */ 807 private void createPostExternalInitializationSubCommand() 808 throws ArgumentException 809 { 810 postExternalInitializationSubCmd = new SubCommand(this, 811 POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME, 812 INFO_DESCRIPTION_SUBCMD_POST_EXTERNAL_INITIALIZATION.get( 813 PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME)); 814 secureArgsList.hostNameArg.setDefaultValue(getDefaultHostValue()); 815 Argument[] argsToAdd = { secureArgsList.hostNameArg, 816 secureArgsList.portArg }; 817 for (Argument arg : argsToAdd) 818 { 819 postExternalInitializationSubCmd.addArgument(arg); 820 } 821 } 822 823 private void createResetChangeNumberSubCommand() throws ArgumentException 824 { 825 resetChangelogNumber = new SubCommand(this, RESET_CHANGE_NUMBER_SUBCMD_NAME, 826 INFO_DESCRIPTION_RESET_CHANGE_NUMBER.get()); 827 828 resetChangeNumber = newChangeNumberArgument(); 829 Argument[] argsToAdd = { 830 hostNameSourceArg, portSourceArg, hostNameDestinationArg, portDestinationArg, resetChangeNumber 831 }; 832 setSubCommandArguments(resetChangelogNumber, argsToAdd); 833 } 834 835 private void setSubCommandArguments(SubCommand subCommand, Argument[] argsToAdd) throws ArgumentException 836 { 837 for (Argument arg : argsToAdd) 838 { 839 arg.setPropertyName(arg.getLongIdentifier()); 840 subCommand.addArgument(arg); 841 } 842 } 843 844 IntegerArgument newChangeNumberArgument() throws ArgumentException 845 { 846 return new IntegerArgument("change-number", null, "change-number", 847 false, true, INFO_CHANGE_NUMBER_PLACEHOLDER.get(), INFO_DESCRIPTION_START_CHANGE_NUMBER.get()); 848 } 849 850 /** 851 * Creates the status replication subcommand and all the specific options 852 * for the subcommand. Note: this method assumes that 853 * initializeGlobalArguments has already been called and that hostNameArg and 854 * portArg have been created. 855 */ 856 private void createStatusReplicationSubCommand() throws ArgumentException 857 { 858 statusReplicationSubCmd = new SubCommand(this, 859 STATUS_REPLICATION_SUBCMD_NAME, 860 INFO_DESCRIPTION_SUBCMD_STATUS_REPLICATION.get()); 861 scriptFriendlyArg = new BooleanArgument( 862 "script-friendly", 863 's', 864 "script-friendly", 865 INFO_DESCRIPTION_SCRIPT_FRIENDLY.get()); 866 scriptFriendlyArg.setPropertyName(scriptFriendlyArg.getLongIdentifier()); 867 secureArgsList.hostNameArg.setDefaultValue(getDefaultHostValue()); 868 Argument[] argsToAdd = { secureArgsList.hostNameArg, 869 secureArgsList.portArg, scriptFriendlyArg }; 870 for (Argument arg : argsToAdd) 871 { 872 statusReplicationSubCmd.addArgument(arg); 873 } 874 } 875 876 /** 877 * Creates the purge historical subcommand and all the specific options 878 * for the subcommand. Note: this method assumes that 879 * initializeGlobalArguments has already been called and that hostNameArg and 880 * portArg have been created. 881 */ 882 private void createPurgeHistoricalSubCommand() 883 throws ArgumentException 884 { 885 maximumDurationArg = new IntegerArgument( 886 "maximumDuration", 887 null, // shortId 888 "maximumDuration", 889 true, // isRequired 890 false, // isMultivalued 891 true, // needsValue 892 INFO_MAXIMUM_DURATION_PLACEHOLDER.get(), 893 PurgeConflictsHistoricalTask.DEFAULT_MAX_DURATION, 894 null, 895 true, 0, 896 false, Integer.MAX_VALUE, 897 INFO_DESCRIPTION_PURGE_HISTORICAL_MAXIMUM_DURATION.get()); 898 899 purgeHistoricalSubCmd = new SubCommand( 900 this, 901 PURGE_HISTORICAL_SUBCMD_NAME, 902 INFO_DESCRIPTION_SUBCMD_PURGE_HISTORICAL.get()); 903 904 Argument[] argsToAdd = { 905 secureArgsList.hostNameArg, 906 secureArgsList.portArg, 907 maximumDurationArg}; 908 909 for (Argument arg : argsToAdd) 910 { 911 arg.setPropertyName(arg.getLongIdentifier()); 912 purgeHistoricalSubCmd.addArgument(arg); 913 } 914 for (Argument arg : taskArgs.getArguments()) 915 { 916 purgeHistoricalSubCmd.addArgument(arg); 917 } 918 } 919 920 /** 921 * Tells whether the user specified to have an interactive operation or not. 922 * This method must be called after calling parseArguments. 923 * @return {@code true} if the user specified to have an interactive 924 * operation and {@code false} otherwise. 925 */ 926 public boolean isInteractive() 927 { 928 return !noPromptArg.isPresent(); 929 } 930 931 /** 932 * Tells whether the user specified to have a quite operation or not. 933 * This method must be called after calling parseArguments. 934 * @return {@code true} if the user specified to have a quite operation 935 * and {@code false} otherwise. 936 */ 937 public boolean isQuiet() 938 { 939 return quietArg.isPresent(); 940 } 941 942 /** 943 * Tells whether the user specified to have a script-friendly output or not. 944 * This method must be called after calling parseArguments. 945 * @return {@code true} if the user specified to have a script-friendly 946 * output and {@code false} otherwise. 947 */ 948 public boolean isScriptFriendly() 949 { 950 return scriptFriendlyArg.isPresent(); 951 } 952 953 /** 954 * Get the global administrator password which has to be used for the command 955 * to connect to the server(s) without prompting the user. If no password was 956 * specified, return null. 957 * 958 * @return the global administrator password which has to be used for the 959 * command to connect to the server(s) without prompting the user. If no 960 * password was specified, return null. 961 */ 962 public String getBindPasswordAdmin() 963 { 964 return getBindPassword(secureArgsList.bindPasswordArg, secureArgsList.bindPasswordFileArg); 965 } 966 967 /** 968 * Returns the Administrator UID explicitly provided in the command-line. 969 * @return the Administrator UID explicitly provided in the command-line. 970 */ 971 @Override 972 public String getAdministratorUID() 973 { 974 return getValue(getAdminUidArg()); 975 } 976 977 /** 978 * Returns the default Administrator UID value. 979 * @return the default Administrator UID value. 980 */ 981 public String getAdministratorUIDOrDefault() 982 { 983 return getValueOrDefault(getAdminUidArg()); 984 } 985 986 /** 987 * Returns the Administrator UID argument. 988 * @return the Administrator UID argument. 989 */ 990 StringArgument getAdminUidArg() 991 { 992 return secureArgsList.adminUidArg; 993 } 994 995 /** 996 * Returns the first server replication port explicitly provided in the enable 997 * replication subcommand. 998 * @return the first server replication port explicitly provided in the enable 999 * replication subcommand. Returns -1 if no port was explicitly provided. 1000 */ 1001 public int getReplicationPort1() 1002 { 1003 return getValue(server1.replicationPortArg); 1004 } 1005 1006 /** 1007 * Returns the second server replication port explicitly provided in the 1008 * enable replication subcommand. 1009 * @return the second server replication port explicitly provided in the 1010 * enable replication subcommand. Returns -1 if no port was explicitly 1011 * provided. 1012 */ 1013 public int getReplicationPort2() 1014 { 1015 return getValue(server2.replicationPortArg); 1016 } 1017 1018 /** 1019 * Returns whether the user asked to skip the replication port checks (if the 1020 * ports are free) or not. 1021 * @return {@code true} the user asked to skip the replication port 1022 * checks (if the ports are free) and {@code false} otherwise. 1023 */ 1024 boolean skipReplicationPortCheck() 1025 { 1026 return skipPortCheckArg.isPresent(); 1027 } 1028 1029 /** 1030 * Returns whether the user asked to not replicate the schema between servers. 1031 * @return {@code true} if the user asked to not replicate schema and 1032 * {@code false} otherwise. 1033 */ 1034 boolean noSchemaReplication() 1035 { 1036 return noSchemaReplicationArg.isPresent(); 1037 } 1038 1039 /** 1040 * Returns whether the user asked to use the second server to initialize the 1041 * schema of the first server. 1042 * @return {@code true} if the user asked to use the second server to 1043 * initialize the schema of the first server and {@code false} otherwise. 1044 */ 1045 boolean useSecondServerAsSchemaSource() 1046 { 1047 return useSecondServerAsSchemaSourceArg.isPresent(); 1048 } 1049 1050 /** 1051 * Returns the host name explicitly provided in the disable replication 1052 * subcommand. 1053 * @return the host name explicitly provided in the disable replication 1054 * subcommand. 1055 */ 1056 public String getHostNameToDisable() 1057 { 1058 return getValue(secureArgsList.hostNameArg); 1059 } 1060 1061 /** 1062 * Returns the host name default value in the disable replication 1063 * subcommand. 1064 * @return the host name default value in the disable replication 1065 * subcommand. 1066 */ 1067 public String getHostNameToDisableOrDefault() 1068 { 1069 return getValueOrDefault(secureArgsList.hostNameArg); 1070 } 1071 1072 /** 1073 * Returns the server bind dn explicitly provided in the disable replication 1074 * subcommand. 1075 * @return the server bind dn explicitly provided in the disable replication 1076 * subcommand. 1077 */ 1078 public String getBindDNToDisable() 1079 { 1080 return getValue(secureArgsList.bindDnArg); 1081 } 1082 1083 /** 1084 * Returns the server bind dn default value in the disable replication 1085 * subcommand. 1086 * @return the server bind dn default value in the enable replication 1087 * subcommand. 1088 */ 1089 public String getDefaultBindDnToDisable() 1090 { 1091 return getDefaultValue(secureArgsList.bindDnArg); 1092 } 1093 1094 /** 1095 * Returns the host name explicitly provided in the status replication 1096 * subcommand. 1097 * @return the host name explicitly provided in the status replication 1098 * subcommand. 1099 */ 1100 public String getHostNameToStatus() 1101 { 1102 return getValue(secureArgsList.hostNameArg); 1103 } 1104 1105 /** 1106 * Returns the host name default value in the status replication subcommand. 1107 * @return the host name default value in the status replication subcommand. 1108 */ 1109 public String getHostNameToStatusOrDefault() 1110 { 1111 return getValueOrDefault(secureArgsList.hostNameArg); 1112 } 1113 1114 /** 1115 * Returns the host name explicitly provided in the initialize all replication 1116 * subcommand. 1117 * @return the host name explicitly provided in the initialize all replication 1118 * subcommand. 1119 */ 1120 public String getHostNameToInitializeAll() 1121 { 1122 return getValue(secureArgsList.hostNameArg); 1123 } 1124 1125 /** 1126 * Returns the host name default value in the initialize all replication 1127 * subcommand. 1128 * @return the host name default value in the initialize all replication 1129 * subcommand. 1130 */ 1131 public String getHostNameToInitializeAllOrDefault() 1132 { 1133 return getValueOrDefault(secureArgsList.hostNameArg); 1134 } 1135 1136 /** 1137 * Returns the host name explicitly provided in the pre external 1138 * initialization subcommand. 1139 * @return the host name explicitly provided in the pre external 1140 * initialization subcommand. 1141 */ 1142 public String getHostNameToPreExternalInitialization() 1143 { 1144 return getValue(secureArgsList.hostNameArg); 1145 } 1146 1147 /** 1148 * Returns the host name default value in the pre external initialization 1149 * subcommand. 1150 * @return the host name default value in the pre external initialization 1151 * subcommand. 1152 */ 1153 public String getDefaultHostNameToPreExternalInitialization() 1154 { 1155 return getDefaultValue(secureArgsList.hostNameArg); 1156 } 1157 1158 /** 1159 * Returns the host name explicitly provided in the post external 1160 * initialization subcommand. 1161 * @return the host name explicitly provided in the post external 1162 * initialization subcommand. 1163 */ 1164 public String getHostNameToPostExternalInitialization() 1165 { 1166 return getValue(secureArgsList.hostNameArg); 1167 } 1168 1169 /** 1170 * Returns the host name default value in the post external initialization 1171 * subcommand. 1172 * @return the host name default value in the post external initialization 1173 * subcommand. 1174 */ 1175 public String getDefaultHostNameToPostExternalInitialization() 1176 { 1177 return getDefaultValue(secureArgsList.hostNameArg); 1178 } 1179 1180 /** 1181 * Returns the source host name explicitly provided in the initialize 1182 * replication subcommand. 1183 * @return the source host name explicitly provided in the initialize 1184 * replication subcommand. 1185 */ 1186 public String getHostNameSource() 1187 { 1188 return getValue(hostNameSourceArg); 1189 } 1190 1191 /** 1192 * Returns the first host name default value in the initialize replication 1193 * subcommand. 1194 * @return the first host name default value in the initialize replication 1195 * subcommand. 1196 */ 1197 public String getHostNameSourceOrDefault() 1198 { 1199 return getValueOrDefault(hostNameSourceArg); 1200 } 1201 1202 /** 1203 * Returns the destination host name explicitly provided in the initialize 1204 * replication subcommand. 1205 * @return the destination host name explicitly provided in the initialize 1206 * replication subcommand. 1207 */ 1208 public String getHostNameDestination() 1209 { 1210 return getValue(hostNameDestinationArg); 1211 } 1212 1213 /** 1214 * Returns the destination host name default value in the initialize 1215 * replication subcommand. 1216 * @return the destination host name default value in the initialize 1217 * replication subcommand. 1218 */ 1219 public String getHostNameDestinationOrDefault() 1220 { 1221 return getValueOrDefault(hostNameDestinationArg); 1222 } 1223 1224 /** 1225 * Returns the source server port explicitly provided in the initialize 1226 * replication subcommand. 1227 * @return the source server port explicitly provided in the initialize 1228 * replication subcommand. Returns -1 if no port was explicitly provided. 1229 */ 1230 public int getPortSource() 1231 { 1232 return getValue(portSourceArg); 1233 } 1234 1235 /** 1236 * Returns the source server port default value in the initialize replication 1237 * subcommand. 1238 * @return the source server port default value in the initialize replication 1239 * subcommand. 1240 */ 1241 public int getPortSourceOrDefault() 1242 { 1243 return getValueOrDefault(portSourceArg); 1244 } 1245 1246 /** 1247 * Returns the destination server port explicitly provided in the initialize 1248 * replication subcommand. 1249 * @return the destination server port explicitly provided in the initialize 1250 * replication subcommand. Returns -1 if no port was explicitly provided. 1251 */ 1252 public int getPortDestination() 1253 { 1254 return getValue(portDestinationArg); 1255 } 1256 1257 /** 1258 * Returns the destination server port default value in the initialize 1259 * replication subcommand. 1260 * @return the destination server port default value in the initialize 1261 * replication subcommand. 1262 */ 1263 public int getPortDestinationOrDefault() 1264 { 1265 return getValueOrDefault(portDestinationArg); 1266 } 1267 1268 /** 1269 * Returns the server port explicitly provided in the disable replication 1270 * subcommand. 1271 * @return the server port explicitly provided in the disable replication 1272 * subcommand. Returns -1 if no port was explicitly provided. 1273 */ 1274 public int getPortToDisable() 1275 { 1276 return getValue(secureArgsList.portArg); 1277 } 1278 1279 /** 1280 * Returns the server port default value in the disable replication 1281 * subcommand. 1282 * @return the server port default value in the disable replication 1283 * subcommand. 1284 */ 1285 public int getPortToDisableOrDefault() 1286 { 1287 return getValueOrDefault(secureArgsList.portArg); 1288 } 1289 1290 /** 1291 * Returns the server port explicitly provided in the initialize all 1292 * replication subcommand. 1293 * @return the server port explicitly provided in the initialize all 1294 * replication subcommand. Returns -1 if no port was explicitly provided. 1295 */ 1296 public int getPortToInitializeAll() 1297 { 1298 return getValue(secureArgsList.portArg); 1299 } 1300 1301 /** 1302 * Returns the server port default value in the initialize all replication 1303 * subcommand. 1304 * @return the server port default value in the initialize all replication 1305 * subcommand. 1306 */ 1307 public int getPortToInitializeAllOrDefault() 1308 { 1309 return getValueOrDefault(secureArgsList.portArg); 1310 } 1311 1312 /** 1313 * Returns the server port explicitly provided in the pre external 1314 * initialization subcommand. 1315 * @return the server port explicitly provided in the pre external 1316 * initialization subcommand. Returns -1 if no port was explicitly provided. 1317 */ 1318 public int getPortToPreExternalInitialization() 1319 { 1320 return getValue(secureArgsList.portArg); 1321 } 1322 1323 /** 1324 * Returns the server port default value in the pre external initialization 1325 * subcommand. 1326 * @return the server port default value in the pre external initialization 1327 * subcommand. 1328 */ 1329 public int getDefaultPortToPreExternalInitialization() 1330 { 1331 return getDefaultValue(secureArgsList.portArg); 1332 } 1333 1334 /** 1335 * Returns the server port explicitly provided in the post external 1336 * initialization subcommand. 1337 * @return the server port explicitly provided in the post external 1338 * initialization subcommand. Returns -1 if no port was explicitly provided. 1339 */ 1340 public int getPortToPostExternalInitialization() 1341 { 1342 return getValue(secureArgsList.portArg); 1343 } 1344 1345 /** 1346 * Returns the server port default value in the post external initialization 1347 * subcommand. 1348 * @return the server port default value in the post external initialization 1349 * subcommand. 1350 */ 1351 public int getDefaultPortToPostExternalInitialization() 1352 { 1353 return getDefaultValue(secureArgsList.portArg); 1354 } 1355 1356 /** 1357 * Returns the server port explicitly provided in the status replication 1358 * subcommand. 1359 * @return the server port explicitly provided in the status replication 1360 * subcommand. Returns -1 if no port was explicitly provided. 1361 */ 1362 public int getPortToStatus() 1363 { 1364 return getValue(secureArgsList.portArg); 1365 } 1366 1367 /** 1368 * Returns the server port default value in the status replication subcommand. 1369 * @return the server port default value in the status replication subcommand. 1370 */ 1371 public int getPortToStatusOrDefault() 1372 { 1373 return getValueOrDefault(secureArgsList.portArg); 1374 } 1375 1376 /** 1377 * Returns the list of base DNs provided by the user. 1378 * @return the list of base DNs provided by the user. 1379 */ 1380 public LinkedList<String> getBaseDNs() 1381 { 1382 return baseDNsArg.getValues(); 1383 } 1384 1385 /** 1386 * Returns the config class value provided in the hidden argument of the 1387 * command-line. 1388 * @return the config class value provided in the hidden argument of the 1389 * command-line. 1390 */ 1391 public String getConfigClass() 1392 { 1393 return getValue(configClassArg); 1394 } 1395 1396 /** 1397 * Returns the config file value provided in the hidden argument of the 1398 * command-line. 1399 * @return the config file value provided in the hidden argument of the 1400 * command-line. 1401 */ 1402 public String getConfigFile() 1403 { 1404 return getValue(configFileArg); 1405 } 1406 1407 /** 1408 * Returns the argument's value if present or else return the argument's default value. 1409 * 1410 * @param arg the argument 1411 * @return the argument's value if present, the argument's default value if not present 1412 */ 1413 static String getValueOrDefault(StringArgument arg) 1414 { 1415 String v = getValue(arg); 1416 String defaultValue = getDefaultValue(arg); 1417 return v != null ? v : defaultValue; 1418 } 1419 1420 /** 1421 * Returns the argument's value if present or else return the argument's default value. 1422 * 1423 * @param arg the argument 1424 * @return the argument's value if present, the argument's default value if not present 1425 */ 1426 static int getValueOrDefault(IntegerArgument arg) 1427 { 1428 int v = getValue(arg); 1429 int defaultValue = getDefaultValue(arg); 1430 return v != -1 ? v : defaultValue; 1431 } 1432 1433 /** 1434 * Returns the value of the provided argument only if the user provided it 1435 * explicitly. 1436 * @param arg the StringArgument to be handled. 1437 * @return the value of the provided argument only if the user provided it 1438 * explicitly. 1439 */ 1440 static String getValue(StringArgument arg) 1441 { 1442 return arg.isPresent() ? arg.getValue() : null; 1443 } 1444 1445 /** 1446 * Returns the default value of the provided argument. 1447 * @param arg the StringArgument to be handled. 1448 * @return the default value of the provided argument. 1449 */ 1450 static String getDefaultValue(StringArgument arg) 1451 { 1452 return arg.getDefaultValue(); 1453 } 1454 1455 /** 1456 * Returns the value of the provided argument only if the user provided it 1457 * explicitly. 1458 * @param arg the StringArgument to be handled. 1459 * @return the value of the provided argument only if the user provided it 1460 * explicitly. 1461 */ 1462 static int getValue(IntegerArgument arg) 1463 { 1464 if (arg.isPresent()) 1465 { 1466 try 1467 { 1468 return arg.getIntValue(); 1469 } 1470 catch (ArgumentException ae) 1471 { 1472 // This is a bug 1473 throw new IllegalStateException( 1474 "There was an argument exception calling "+ 1475 "ReplicationCliParser.getValue(). This appears to be a bug "+ 1476 "because this method should be called after calling "+ 1477 "parseArguments which should result in an error.", ae); 1478 } 1479 } 1480 return -1; 1481 } 1482 1483 /** 1484 * Returns the default value of the provided argument. 1485 * @param arg the StringArgument to be handled. 1486 * @return the default value of the provided argument. 1487 */ 1488 static int getDefaultValue(IntegerArgument arg) 1489 { 1490 String v = arg.getDefaultValue(); 1491 return v != null ? Integer.parseInt(v) : -1; 1492 } 1493 1494 /** 1495 * Checks the subcommand options and updates the provided LocalizableMessageBuilder 1496 * with the errors that were encountered with the subcommand options. 1497 * 1498 * This method assumes that the method parseArguments for the parser has 1499 * already been called. 1500 * @param buf the LocalizableMessageBuilder object where we add the error messages 1501 * describing the errors encountered. 1502 */ 1503 private void validateSubcommandOptions(LocalizableMessageBuilder buf) 1504 { 1505 if (isEnableReplicationSubcommand()) 1506 { 1507 validateEnableReplicationOptions(buf); 1508 } 1509 else if (isDisableReplicationSubcommand()) 1510 { 1511 validateDisableReplicationOptions(buf); 1512 } 1513 else if (isStatusReplicationSubcommand()) 1514 { 1515 validateStatusReplicationOptions(buf); 1516 } 1517 else if (isInitializeReplicationSubcommand()) 1518 { 1519 validateSourceAndDestinationServersOptions(buf); 1520 } 1521 else if (isPurgeHistoricalSubcommand()) 1522 { 1523 validatePurgeHistoricalOptions(buf); 1524 } 1525 else if (isResetChangeNumber()) 1526 { 1527 validateSourceAndDestinationServersOptions(buf); 1528 } 1529 } 1530 1531 /** 1532 * Checks the purge historical subcommand options and updates the 1533 * provided LocalizableMessageBuilder with the errors that were encountered with the 1534 * subcommand options. 1535 * 1536 * This method assumes that the method parseArguments for the parser has 1537 * already been called. 1538 * @param buf the LocalizableMessageBuilder object where we add the error messages 1539 * describing the errors encountered. 1540 */ 1541 private void validatePurgeHistoricalOptions(LocalizableMessageBuilder buf) 1542 { 1543 try 1544 { 1545 if (!isInteractive() && !connectionArgumentsPresent()) 1546 { 1547 taskArgs.validateArgsIfOffline(); 1548 } 1549 else 1550 { 1551 taskArgs.validateArgs(); 1552 } 1553 } 1554 catch (ClientException | ArgumentException e) 1555 { 1556 addMessage(buf, e.getMessageObject()); 1557 } 1558 } 1559 1560 /** 1561 * Returns whether the user provided subcommand is the enable replication 1562 * or not. 1563 * @return {@code true} if the user provided subcommand is the 1564 * enable replication and {@code false} otherwise. 1565 */ 1566 public boolean isEnableReplicationSubcommand() 1567 { 1568 return isSubcommand(ENABLE_REPLICATION_SUBCMD_NAME); 1569 } 1570 1571 /** 1572 * Returns whether the user provided subcommand is the disable replication 1573 * or not. 1574 * @return {@code true} if the user provided subcommand is the 1575 * disable replication and {@code false} otherwise. 1576 */ 1577 public boolean isDisableReplicationSubcommand() 1578 { 1579 return isSubcommand(DISABLE_REPLICATION_SUBCMD_NAME); 1580 } 1581 1582 /** 1583 * Returns whether the user specified the reset changelog numbering subcommand. 1584 * @return {@code true} if the user wanted to reset change number 1585 */ 1586 public boolean isResetChangeNumber() 1587 { 1588 return isSubcommand(RESET_CHANGE_NUMBER_SUBCMD_NAME); 1589 } 1590 1591 /** 1592 * Returns whether the user provided subcommand is the status replication 1593 * or not. 1594 * @return {@code true} if the user provided subcommand is the 1595 * status replication and {@code false} otherwise. 1596 */ 1597 public boolean isStatusReplicationSubcommand() 1598 { 1599 return isSubcommand(STATUS_REPLICATION_SUBCMD_NAME); 1600 } 1601 1602 /** 1603 * Returns whether the user provided subcommand is the purge historical 1604 * or not. 1605 * @return {@code true} if the user provided subcommand is the 1606 * purge historical and {@code false} otherwise. 1607 */ 1608 public boolean isPurgeHistoricalSubcommand() 1609 { 1610 return isSubcommand(PURGE_HISTORICAL_SUBCMD_NAME); 1611 } 1612 1613 /** 1614 * Returns whether the user provided subcommand is the initialize all 1615 * replication or not. 1616 * @return {@code true} if the user provided subcommand is the 1617 * initialize all replication and {@code false} otherwise. 1618 */ 1619 public boolean isInitializeAllReplicationSubcommand() 1620 { 1621 return isSubcommand(INITIALIZE_ALL_REPLICATION_SUBCMD_NAME); 1622 } 1623 1624 /** 1625 * Returns whether the user provided subcommand is the pre external 1626 * initialization or not. 1627 * @return {@code true} if the user provided subcommand is the 1628 * pre external initialization and {@code false} otherwise. 1629 */ 1630 public boolean isPreExternalInitializationSubcommand() 1631 { 1632 return isSubcommand(PRE_EXTERNAL_INITIALIZATION_SUBCMD_NAME); 1633 } 1634 1635 /** 1636 * Returns whether the user provided subcommand is the post external 1637 * initialization or not. 1638 * @return {@code true} if the user provided subcommand is the 1639 * post external initialization and {@code false} otherwise. 1640 */ 1641 public boolean isPostExternalInitializationSubcommand() 1642 { 1643 return isSubcommand(POST_EXTERNAL_INITIALIZATION_SUBCMD_NAME); 1644 } 1645 1646 /** 1647 * Returns whether the user provided subcommand is the initialize replication 1648 * or not. 1649 * @return {@code true} if the user provided subcommand is the 1650 * initialize replication and {@code false} otherwise. 1651 */ 1652 public boolean isInitializeReplicationSubcommand() 1653 { 1654 return isSubcommand(INITIALIZE_REPLICATION_SUBCMD_NAME); 1655 } 1656 1657 /** 1658 * Returns whether the command-line subcommand has the name provided 1659 * or not. 1660 * @param name the name of the subcommand. 1661 * @return {@code true} if command-line subcommand has the name provided 1662 * and {@code false} otherwise. 1663 */ 1664 private boolean isSubcommand(String name) 1665 { 1666 SubCommand subCommand = getSubCommand(); 1667 return subCommand != null && subCommand.getName().equalsIgnoreCase(name); 1668 } 1669 1670 /** 1671 * Checks the enable replication subcommand options and updates the provided 1672 * LocalizableMessageBuilder with the errors that were encountered with the subcommand 1673 * options. 1674 * 1675 * This method assumes that the method parseArguments for the parser has 1676 * already been called. 1677 * @param buf the LocalizableMessageBuilder object where we add the error messages 1678 * describing the errors encountered. 1679 */ 1680 private void validateEnableReplicationOptions(LocalizableMessageBuilder buf) 1681 { 1682 Argument[][] conflictingPairs = 1683 { 1684 { server1.bindPasswordArg, server1.bindPasswordFileArg }, 1685 { server2.bindPasswordArg, server2.bindPasswordFileArg }, 1686 { server1.replicationPortArg, server1.noReplicationServerArg }, 1687 { server1.noReplicationServerArg, server1.onlyReplicationServerArg }, 1688 { server2.replicationPortArg, server2.noReplicationServerArg }, 1689 { server2.noReplicationServerArg, server2.onlyReplicationServerArg }, 1690 {noSchemaReplicationArg, useSecondServerAsSchemaSourceArg} 1691 }; 1692 1693 for (Argument[] conflictingPair : conflictingPairs) 1694 { 1695 Argument arg1 = conflictingPair[0]; 1696 Argument arg2 = conflictingPair[1]; 1697 if (arg1.isPresent() && arg2.isPresent()) 1698 { 1699 LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get( 1700 arg1.getLongIdentifier(), arg2.getLongIdentifier()); 1701 addMessage(buf, message); 1702 } 1703 } 1704 1705 if (server1.hostNameArg.getValue().equalsIgnoreCase(server2.hostNameArg.getValue()) 1706 && !isInteractive() 1707 && server1.portArg.getValue().equals(server2.portArg.getValue())) 1708 { 1709 LocalizableMessage message = ERR_REPLICATION_ENABLE_SAME_SERVER_PORT.get( 1710 server1.hostNameArg.getValue(), server1.portArg.getValue()); 1711 addMessage(buf, message); 1712 } 1713 } 1714 1715 /** 1716 * Checks the disable replication subcommand options and updates the provided 1717 * LocalizableMessageBuilder with the errors that were encountered with the subcommand 1718 * options. 1719 * 1720 * This method assumes that the method parseArguments for the parser has 1721 * already been called. 1722 * @param buf the LocalizableMessageBuilder object where we add the error messages 1723 * describing the errors encountered. 1724 */ 1725 private void validateDisableReplicationOptions(LocalizableMessageBuilder buf) 1726 { 1727 Argument[][] conflictingPairs = 1728 { 1729 {getAdminUidArg(), secureArgsList.bindDnArg}, 1730 {disableAllArg, disableReplicationServerArg}, 1731 {disableAllArg, baseDNsArg} 1732 }; 1733 1734 for (Argument[] conflictingPair : conflictingPairs) 1735 { 1736 Argument arg1 = conflictingPair[0]; 1737 Argument arg2 = conflictingPair[1]; 1738 if (arg1.isPresent() && arg2.isPresent()) 1739 { 1740 LocalizableMessage message = ERR_TOOL_CONFLICTING_ARGS.get( 1741 arg1.getLongIdentifier(), arg2.getLongIdentifier()); 1742 addMessage(buf, message); 1743 } 1744 } 1745 } 1746 1747 /** 1748 * Checks the status replication subcommand options and updates the provided 1749 * LocalizableMessageBuilder with the errors that were encountered with the subcommand 1750 * options. 1751 * 1752 * This method assumes that the method parseArguments for the parser has 1753 * already been called. 1754 * @param buf the LocalizableMessageBuilder object where we add the error messages 1755 * describing the errors encountered. 1756 */ 1757 private void validateStatusReplicationOptions(LocalizableMessageBuilder buf) 1758 { 1759 if (quietArg.isPresent()) 1760 { 1761 LocalizableMessage message = ERR_REPLICATION_STATUS_QUIET.get( 1762 STATUS_REPLICATION_SUBCMD_NAME, "--"+quietArg.getLongIdentifier()); 1763 addMessage(buf, message); 1764 } 1765 } 1766 1767 /** 1768 * Checks the initialize replication subcommand options and updates the 1769 * provided LocalizableMessageBuilder with the errors that were encountered with the 1770 * subcommand options. 1771 * 1772 * This method assumes that the method parseArguments for the parser has 1773 * already been called. 1774 * @param buf the LocalizableMessageBuilder object where we add the error messages 1775 * describing the errors encountered. 1776 */ 1777 private void validateSourceAndDestinationServersOptions(LocalizableMessageBuilder buf) 1778 { 1779 if (hostNameSourceArg.getValue().equalsIgnoreCase(hostNameDestinationArg.getValue()) 1780 && !isInteractive() 1781 && portSourceArg.getValue().equals(portDestinationArg.getValue())) 1782 { 1783 LocalizableMessage message = ERR_SOURCE_DESTINATION_INITIALIZE_SAME_SERVER_PORT.get( 1784 hostNameSourceArg.getValue(), portSourceArg.getValue()); 1785 addMessage(buf, message); 1786 } 1787 } 1788 1789 /** 1790 * Adds a message to the provided LocalizableMessageBuilder. 1791 * @param buf the LocalizableMessageBuilder. 1792 * @param message the message to be added. 1793 */ 1794 private void addMessage(LocalizableMessageBuilder buf, LocalizableMessage message) 1795 { 1796 if (buf.length() > 0) 1797 { 1798 buf.append(LINE_SEPARATOR); 1799 } 1800 buf.append(message); 1801 } 1802 1803 /** 1804 * Returns the default value to be used for the host. 1805 * @return the default value to be used for the host. 1806 */ 1807 private String getDefaultHostValue() 1808 { 1809 if (defaultLocalHostValue == null) 1810 { 1811 try 1812 { 1813 defaultLocalHostValue = 1814 java.net.InetAddress.getLocalHost().getHostName(); 1815 } 1816 catch (Throwable t) 1817 { 1818 } 1819 if (defaultLocalHostValue == null) 1820 { 1821 defaultLocalHostValue = "localhost"; 1822 } 1823 } 1824 return defaultLocalHostValue; 1825 } 1826 1827 /** 1828 * Returns the SecureConnectionCliArgs object containing the arguments 1829 * of this parser. 1830 * @return the SecureConnectionCliArgs object containing the arguments 1831 * of this parser. 1832 */ 1833 public SecureConnectionCliArgs getSecureArgsList() 1834 { 1835 return secureArgsList; 1836 } 1837 1838 /** 1839 * Returns the TaskScheduleArgs object containing the arguments 1840 * of this parser. 1841 * @return the TaskScheduleArgs object containing the arguments 1842 * of this parser. 1843 */ 1844 public TaskScheduleArgs getTaskArgsList() 1845 { 1846 return taskArgs; 1847 } 1848 1849 /** 1850 * Returns whether the user specified connection arguments or not. 1851 * @return {@code true} if the user specified connection arguments and 1852 * {@code false} otherwise. 1853 */ 1854 boolean connectionArgumentsPresent() 1855 { 1856 if (isPurgeHistoricalSubcommand()) { 1857 boolean secureArgsPresent = getSecureArgsList() != null && 1858 getSecureArgsList().argumentsPresent(); 1859 // This have to be explicitly specified because their original definition 1860 // has been replaced. 1861 boolean adminArgsPresent = getAdminUidArg().isPresent() || 1862 secureArgsList.bindPasswordArg.isPresent() || 1863 secureArgsList.bindPasswordFileArg.isPresent(); 1864 return secureArgsPresent || adminArgsPresent; 1865 } 1866 return true; 1867 } 1868 1869 /** 1870 * Returns the maximum duration explicitly provided in the purge historical 1871 * replication subcommand. 1872 * @return the maximum duration explicitly provided in the purge historical 1873 * replication subcommand. Returns -1 if no port was explicitly provided. 1874 */ 1875 public int getMaximumDuration() 1876 { 1877 return getValue(maximumDurationArg); 1878 } 1879 1880 /** 1881 * Returns the maximum duration default value in the purge historical 1882 * replication subcommand. 1883 * @return the maximum duration default value in the purge historical 1884 * replication subcommand. 1885 */ 1886 public int getMaximumDurationOrDefault() 1887 { 1888 return getValueOrDefault(maximumDurationArg); 1889 } 1890 1891 /** 1892 * Returns the changenumber specified as argument. 1893 * @return the changenumber specified as argument 1894 */ 1895 public int getResetChangeNumber() 1896 { 1897 return getValue(resetChangeNumber); 1898 } 1899 1900 /** 1901 * Sets the start change number value. 1902 * @param changeNumber the new value of the option 1903 */ 1904 public void setResetChangeNumber(String changeNumber) 1905 { 1906 resetChangeNumber.setPresent(true); 1907 resetChangeNumber.addValue(changeNumber); 1908 } 1909}