001/* 002 * Copyright 2016-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2016-2018 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.sdk.unboundidds.tools; 022 023 024 025import java.io.BufferedReader; 026import java.io.File; 027import java.io.FileOutputStream; 028import java.io.FileReader; 029import java.io.OutputStream; 030import java.util.ArrayList; 031import java.util.Arrays; 032import java.util.LinkedHashMap; 033import java.util.concurrent.atomic.AtomicBoolean; 034 035import com.unboundid.ldap.sdk.DN; 036import com.unboundid.ldap.sdk.ExtendedResult; 037import com.unboundid.ldap.sdk.Filter; 038import com.unboundid.ldap.sdk.LDAPConnection; 039import com.unboundid.ldap.sdk.LDAPConnectionOptions; 040import com.unboundid.ldap.sdk.LDAPConnectionPool; 041import com.unboundid.ldap.sdk.LDAPException; 042import com.unboundid.ldap.sdk.ResultCode; 043import com.unboundid.ldap.sdk.UnsolicitedNotificationHandler; 044import com.unboundid.ldap.sdk.Version; 045import com.unboundid.ldif.LDIFWriter; 046import com.unboundid.util.Debug; 047import com.unboundid.util.DNFileReader; 048import com.unboundid.util.LDAPCommandLineTool; 049import com.unboundid.util.FilterFileReader; 050import com.unboundid.util.FixedRateBarrier; 051import com.unboundid.util.RateAdjustor; 052import com.unboundid.util.StaticUtils; 053import com.unboundid.util.ThreadSafety; 054import com.unboundid.util.ThreadSafetyLevel; 055import com.unboundid.util.args.ArgumentException; 056import com.unboundid.util.args.ArgumentParser; 057import com.unboundid.util.args.BooleanArgument; 058import com.unboundid.util.args.BooleanValueArgument; 059import com.unboundid.util.args.DNArgument; 060import com.unboundid.util.args.FileArgument; 061import com.unboundid.util.args.FilterArgument; 062import com.unboundid.util.args.IPAddressArgumentValueValidator; 063import com.unboundid.util.args.IntegerArgument; 064import com.unboundid.util.args.StringArgument; 065import com.unboundid.util.args.TimestampArgument; 066import com.unboundid.util.args.SubCommand; 067 068import static com.unboundid.ldap.sdk.unboundidds.tools. 069 ManageAccountSubCommandType.*; 070import static com.unboundid.ldap.sdk.unboundidds.tools.ToolMessages.*; 071 072 073 074/** 075 * This class provides a tool that can be used to perform a variety of account 076 * management functions against user entries in the Ping Identity, UnboundID, 077 * or Alcatel-Lucent 8661 Directory Server. It primarily uses the password 078 * policy state extended operation for its processing. 079 * <BR> 080 * <BLOCKQUOTE> 081 * <B>NOTE:</B> This class, and other classes within the 082 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 083 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 084 * server products. These classes provide support for proprietary 085 * functionality or for external specifications that are not considered stable 086 * or mature enough to be guaranteed to work in an interoperable way with 087 * other types of LDAP servers. 088 * </BLOCKQUOTE> 089 */ 090@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 091public final class ManageAccount 092 extends LDAPCommandLineTool 093 implements UnsolicitedNotificationHandler 094{ 095 /** 096 * The column at which to wrap long lines. 097 */ 098 static final int WRAP_COLUMN = StaticUtils.TERMINAL_WIDTH_COLUMNS - 1; 099 100 101 102 /** 103 * The primary name of the argument used to indicate that the tool should 104 * append to the reject file rather than overwrite it. 105 */ 106 static final String ARG_APPEND_TO_REJECT_FILE = "appendToRejectFile"; 107 108 109 110 /** 111 * The primary name of the argument used to specify a base DN to use for 112 * searches. 113 */ 114 static final String ARG_BASE_DN = "baseDN"; 115 116 117 118 /** 119 * The primary name of the argument used to specify the path to a file to a 120 * sample variable rate data file to create. 121 */ 122 static final String ARG_GENERATE_SAMPLE_RATE_FILE = "generateSampleRateFile"; 123 124 125 126 /** 127 * The primary name of the argument used to specify the path to a file 128 * containing the DNs of the users on which to operate. 129 */ 130 static final String ARG_DN_INPUT_FILE = "dnInputFile"; 131 132 133 134 /** 135 * The primary name of the argument used to specify the path to a file 136 * containing search filters to use to identify users. 137 */ 138 static final String ARG_FILTER_INPUT_FILE = "filterInputFile"; 139 140 141 142 /** 143 * The primary name of the argument used to specify the number of threads to 144 * use to process search operations to identify which users to target. 145 */ 146 static final String ARG_NUM_SEARCH_THREADS = "numSearchThreads"; 147 148 149 150 /** 151 * The primary name of the argument used to specify the number of threads to 152 * use to perform manage-account processing. 153 */ 154 static final String ARG_NUM_THREADS = "numThreads"; 155 156 157 158 /** 159 * The primary name of the argument used to specify the target rate of 160 * operations per second. 161 */ 162 static final String ARG_RATE_PER_SECOND = "ratePerSecond"; 163 164 165 166 /** 167 * The primary name of the argument used to specify the path to a reject file 168 * to create. 169 */ 170 static final String ARG_REJECT_FILE = "rejectFile"; 171 172 173 174 /** 175 * The primary name of the argument used to specify the simple page size to 176 * use when performing searches. 177 */ 178 static final String ARG_SIMPLE_PAGE_SIZE = "simplePageSize"; 179 180 181 182 /** 183 * The primary name of the argument used to suppress result operation types 184 * without values. 185 */ 186 static final String ARG_SUPPRESS_EMPTY_RESULT_OPERATIONS = 187 "suppressEmptyResultOperations"; 188 189 190 191 /** 192 * The primary name of the argument used to specify the DN of the user on 193 * which to operate. 194 */ 195 static final String ARG_TARGET_DN = "targetDN"; 196 197 198 199 /** 200 * The primary name of the argument used to specify a search filter to use to 201 * identify users. 202 */ 203 static final String ARG_TARGET_FILTER = "targetFilter"; 204 205 206 207 /** 208 * The primary name of the argument used to specify the user IDs of target 209 * users. 210 */ 211 static final String ARG_TARGET_USER_ID = "targetUserID"; 212 213 214 215 /** 216 * The primary name of the argument used to specify the name of the attribute 217 * to identify which user has a given user ID. 218 */ 219 static final String ARG_USER_ID_ATTRIBUTE = "userIDAttribute"; 220 221 222 223 /** 224 * The primary name of the argument used to specify the path to a file 225 * containing the user IDs of the target users. 226 */ 227 static final String ARG_USER_ID_INPUT_FILE = "userIDInputFile"; 228 229 230 231 /** 232 * The primary name of the argument used to specify the path to a variable 233 * rate data file. 234 */ 235 static final String ARG_VARIABLE_RATE_DATA = "variableRateData"; 236 237 238 239 /** 240 * The default search base DN. 241 */ 242 static final DN DEFAULT_BASE_DN = DN.NULL_DN; 243 244 245 246 /** 247 * The default user ID attribute. 248 */ 249 static final String DEFAULT_USER_ID_ATTRIBUTE = "uid"; 250 251 252 253 /** 254 * A target user DN to use in examples. 255 */ 256 static final String EXAMPLE_TARGET_USER_DN = 257 "uid=jdoe,ou=People,dc=example,dc=com"; 258 259 260 261 // The argument parser for this tool. 262 private volatile ArgumentParser parser; 263 264 // Indicates whether all DNs have been provided to the manage-account 265 // processor. 266 private final AtomicBoolean allDNsProvided; 267 268 // Indicates whether all filters have been provided to the manage-account 269 // search processor. 270 private final AtomicBoolean allFiltersProvided; 271 272 // Indicates whether a request has been made to cancel processing. 273 private final AtomicBoolean cancelRequested; 274 275 // The rate limiter to use for this tool. 276 private volatile FixedRateBarrier rateLimiter; 277 278 // The LDAP connection options to use for connections created by this tool. 279 private final LDAPConnectionOptions connectionOptions; 280 281 // The LDIF writer to use to write information about successful and failed 282 // operations. 283 private volatile LDIFWriter outputWriter; 284 285 // The LDIF writer to use to write information about failed operations. 286 private volatile LDIFWriter rejectWriter; 287 288 // The search processor for this tool. 289 private volatile ManageAccountSearchProcessor searchProcessor; 290 291 // The rate adjustor to use to vary the load over time. 292 private volatile RateAdjustor rateAdjustor; 293 294 295 296 /** 297 * Invokes the tool with the provided set of arguments. 298 * 299 * @param args The command-line arguments provided to this tool. 300 */ 301 public static void main(final String... args) 302 { 303 final ResultCode resultCode = main(System.out, System.err, args); 304 if (resultCode != ResultCode.SUCCESS) 305 { 306 System.exit(resultCode.intValue()); 307 } 308 } 309 310 311 312 /** 313 * Invokes the tool with the provided set of arguments. 314 * 315 * @param out The output stream to use for standard out. It may be 316 * {@code null} if standard out should be suppressed. 317 * @param err The output stream to use for standard error. It may be 318 * {@code null} if standard error should be suppressed. 319 * @param args The command-line arguments provided to this tool. 320 * 321 * @return A result code with the status of the tool processing. Any result 322 * code other than {@link ResultCode#SUCCESS} should be considered a 323 * failure. 324 */ 325 public static ResultCode main(final OutputStream out, final OutputStream err, 326 final String... args) 327 { 328 final ManageAccount tool = new ManageAccount(out, err); 329 330 final boolean origCommentAboutBase64EncodedValues = 331 LDIFWriter.commentAboutBase64EncodedValues(); 332 LDIFWriter.setCommentAboutBase64EncodedValues(true); 333 try 334 { 335 return tool.runTool(args); 336 } 337 finally 338 { 339 LDIFWriter.setCommentAboutBase64EncodedValues( 340 origCommentAboutBase64EncodedValues); 341 } 342 } 343 344 345 346 /** 347 * Creates a new instance of this tool with the provided arguments. 348 * 349 * @param out The output stream to use for standard out. It may be 350 * {@code null} if standard out should be suppressed. 351 * @param err The output stream to use for standard error. It may be 352 * {@code null} if standard error should be suppressed. 353 */ 354 public ManageAccount(final OutputStream out, final OutputStream err) 355 { 356 super(out, err); 357 358 connectionOptions = new LDAPConnectionOptions(); 359 connectionOptions.setUnsolicitedNotificationHandler(this); 360 361 allDNsProvided = new AtomicBoolean(false); 362 allFiltersProvided = new AtomicBoolean(false); 363 cancelRequested = new AtomicBoolean(false); 364 365 parser = null; 366 rateLimiter = null; 367 rateAdjustor = null; 368 outputWriter = null; 369 rejectWriter = null; 370 searchProcessor = null; 371 } 372 373 374 375 /** 376 * {@inheritDoc} 377 */ 378 @Override() 379 public String getToolName() 380 { 381 return "manage-account"; 382 } 383 384 385 386 /** 387 * {@inheritDoc} 388 */ 389 @Override() 390 public String getToolDescription() 391 { 392 return INFO_MANAGE_ACCT_TOOL_DESC.get(); 393 } 394 395 396 397 /** 398 * {@inheritDoc} 399 */ 400 @Override() 401 public String getToolVersion() 402 { 403 return Version.NUMERIC_VERSION_STRING; 404 } 405 406 407 408 /** 409 * {@inheritDoc} 410 */ 411 @Override() 412 public boolean supportsInteractiveMode() 413 { 414 return true; 415 } 416 417 418 419 /** 420 * {@inheritDoc} 421 */ 422 @Override() 423 public boolean defaultsToInteractiveMode() 424 { 425 return true; 426 } 427 428 429 430 /** 431 * {@inheritDoc} 432 */ 433 @Override() 434 public boolean supportsPropertiesFile() 435 { 436 return true; 437 } 438 439 440 441 /** 442 * {@inheritDoc} 443 */ 444 @Override() 445 protected boolean supportsOutputFile() 446 { 447 return true; 448 } 449 450 451 452 /** 453 * {@inheritDoc} 454 */ 455 @Override() 456 protected boolean supportsAuthentication() 457 { 458 return true; 459 } 460 461 462 463 /** 464 * {@inheritDoc} 465 */ 466 @Override() 467 protected boolean defaultToPromptForBindPassword() 468 { 469 return true; 470 } 471 472 473 474 /** 475 * {@inheritDoc} 476 */ 477 @Override() 478 protected boolean supportsSASLHelp() 479 { 480 return true; 481 } 482 483 484 485 /** 486 * {@inheritDoc} 487 */ 488 @Override() 489 protected boolean includeAlternateLongIdentifiers() 490 { 491 return true; 492 } 493 494 495 496 /** 497 * {@inheritDoc} 498 */ 499 @Override() 500 protected boolean supportsMultipleServers() 501 { 502 return true; 503 } 504 505 506 507 /** 508 * {@inheritDoc} 509 */ 510 @Override() 511 protected boolean logToolInvocationByDefault() 512 { 513 return true; 514 } 515 516 517 518 /** 519 * {@inheritDoc} 520 */ 521 @Override() 522 public void addNonLDAPArguments(final ArgumentParser parser) 523 throws ArgumentException 524 { 525 // Get a copy of the argument parser for later use. 526 this.parser = parser; 527 528 529 // Get the current time formatted as a generalized time. 530 final String currentGeneralizedTime = 531 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis()); 532 final String olderGeneralizedTime = 533 StaticUtils.encodeGeneralizedTime(System.currentTimeMillis() - 12345L); 534 535 536 // Define the global arguments used to indicate which users to target. 537 final DNArgument targetDN = new DNArgument('b', ARG_TARGET_DN, false, 0, 538 null, INFO_MANAGE_ACCT_ARG_DESC_TARGET_DN.get()); 539 targetDN.addLongIdentifier("userDN", true); 540 targetDN.addLongIdentifier("target-dn", true); 541 targetDN.addLongIdentifier("user-dn", true); 542 targetDN.setArgumentGroupName( 543 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 544 parser.addArgument(targetDN); 545 546 final FileArgument dnInputFile = new FileArgument(null, ARG_DN_INPUT_FILE, 547 false, 0, null, INFO_MANAGE_ACCT_ARG_DESC_DN_FILE.get(), true, 548 true, true, false); 549 dnInputFile.addLongIdentifier("targetDNFile", true); 550 dnInputFile.addLongIdentifier("userDNFile", true); 551 dnInputFile.addLongIdentifier("dn-input-file", true); 552 dnInputFile.addLongIdentifier("target-dn-file", true); 553 dnInputFile.addLongIdentifier("user-dn-file", true); 554 dnInputFile.setArgumentGroupName( 555 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 556 parser.addArgument(dnInputFile); 557 558 final FilterArgument targetFilter = new FilterArgument(null, 559 ARG_TARGET_FILTER, false, 0, null, 560 INFO_MANAGE_ACCT_ARG_DESC_TARGET_FILTER.get(ARG_BASE_DN)); 561 targetFilter.addLongIdentifier("target-filter", true); 562 targetFilter.setArgumentGroupName( 563 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 564 parser.addArgument(targetFilter); 565 566 final FileArgument filterInputFile = new FileArgument(null, 567 ARG_FILTER_INPUT_FILE, false, 0, null, 568 INFO_MANAGE_ACCT_ARG_DESC_FILTER_INPUT_FILE.get(ARG_BASE_DN), 569 true, true, true, false); 570 filterInputFile.addLongIdentifier("targetFilterFile", true); 571 filterInputFile.addLongIdentifier("filter-input-file", true); 572 filterInputFile.addLongIdentifier("target-filter-file", true); 573 filterInputFile.setArgumentGroupName( 574 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 575 parser.addArgument(filterInputFile); 576 577 final StringArgument targetUserID = new StringArgument(null, 578 ARG_TARGET_USER_ID, false, 0, null, 579 INFO_MANAGE_ACCT_ARG_DESC_TARGET_USER_ID.get(ARG_BASE_DN, 580 ARG_USER_ID_ATTRIBUTE)); 581 targetUserID.addLongIdentifier("userID", true); 582 targetUserID.addLongIdentifier("target-user-id", true); 583 targetUserID.addLongIdentifier("user-id", true); 584 targetUserID.setArgumentGroupName( 585 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 586 parser.addArgument(targetUserID); 587 588 final FileArgument userIDInputFile = new FileArgument(null, 589 ARG_USER_ID_INPUT_FILE, false, 0, null, 590 INFO_MANAGE_ACCT_ARG_DESC_USER_ID_INPUT_FILE.get(ARG_BASE_DN, 591 ARG_USER_ID_ATTRIBUTE), 592 true, true, true, false); 593 userIDInputFile.addLongIdentifier("targetUserIDFile", true); 594 userIDInputFile.addLongIdentifier("user-id-input-file", true); 595 userIDInputFile.addLongIdentifier("target-user-id-file", true); 596 userIDInputFile.setArgumentGroupName( 597 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 598 parser.addArgument(userIDInputFile); 599 600 final StringArgument userIDAttribute = new StringArgument(null, 601 ARG_USER_ID_ATTRIBUTE, false, 1, null, 602 INFO_MANAGE_ACCT_ARG_DESC_USER_ID_ATTR.get( 603 ARG_TARGET_USER_ID, ARG_USER_ID_INPUT_FILE, 604 DEFAULT_USER_ID_ATTRIBUTE), 605 DEFAULT_USER_ID_ATTRIBUTE); 606 userIDAttribute.addLongIdentifier("user-id-attribute", true); 607 userIDAttribute.setArgumentGroupName( 608 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 609 parser.addArgument(userIDAttribute); 610 611 final DNArgument baseDN = new DNArgument(null, ARG_BASE_DN, false, 1, null, 612 INFO_MANAGE_ACCT_ARG_DESC_BASE_DN.get(ARG_TARGET_FILTER, 613 ARG_FILTER_INPUT_FILE, ARG_TARGET_USER_ID, 614 ARG_USER_ID_INPUT_FILE), 615 DEFAULT_BASE_DN); 616 baseDN.addLongIdentifier("base-dn", true); 617 baseDN.setArgumentGroupName( 618 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get()); 619 parser.addArgument(baseDN); 620 621 final IntegerArgument simplePageSize = new IntegerArgument('z', 622 ARG_SIMPLE_PAGE_SIZE, false, 1, null, 623 INFO_MANAGE_ACCT_ARG_DESC_SIMPLE_PAGE_SIZE.get(getToolName()), 1, 624 Integer.MAX_VALUE); 625 simplePageSize.addLongIdentifier("simple-page-size", true); 626 simplePageSize.setArgumentGroupName( 627 INFO_MANAGE_ACCT_ARG_GROUP_TARGET_USER_ARGS.get(getToolName())); 628 parser.addArgument(simplePageSize); 629 630 631 // Ensure that the user will be required ot provide at least one of the 632 // arguments to specify which users to target. 633 parser.addRequiredArgumentSet(targetDN, dnInputFile, targetFilter, 634 filterInputFile, targetUserID, userIDInputFile); 635 636 637 // Define the global arguments used to control the amount of load the tool 638 // should be permitted to generate. 639 final IntegerArgument numThreads = new IntegerArgument('t', ARG_NUM_THREADS, 640 false, 1, null, 641 INFO_MANAGE_ACCT_ARG_DESC_NUM_THREADS.get(getToolName()), 1, 642 Integer.MAX_VALUE, 1); 643 numThreads.addLongIdentifier("num-threads", true); 644 numThreads.setArgumentGroupName( 645 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 646 parser.addArgument(numThreads); 647 648 final IntegerArgument numSearchThreads = new IntegerArgument(null, 649 ARG_NUM_SEARCH_THREADS, false, 1, null, 650 INFO_MANAGE_ACCT_ARG_DESC_NUM_SEARCH_THREADS.get(getToolName()), 1, 651 Integer.MAX_VALUE, 1); 652 numSearchThreads.addLongIdentifier("num-search-threads", true); 653 numSearchThreads.setArgumentGroupName( 654 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 655 parser.addArgument(numSearchThreads); 656 657 final IntegerArgument ratePerSecond = new IntegerArgument('r', 658 ARG_RATE_PER_SECOND, false, 1, null, 659 INFO_MANAGE_ACCT_ARG_DESC_RATE_PER_SECOND.get( 660 ARG_VARIABLE_RATE_DATA), 661 1, Integer.MAX_VALUE); 662 ratePerSecond.addLongIdentifier("rate-per-second", true); 663 ratePerSecond.setArgumentGroupName( 664 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 665 parser.addArgument(ratePerSecond); 666 667 final FileArgument variableRateData = new FileArgument(null, 668 ARG_VARIABLE_RATE_DATA, false, 1, null, 669 INFO_MANAGE_ACCT_ARG_DESC_VARIABLE_RATE_DATA.get( 670 ARG_RATE_PER_SECOND), 671 true, true, true, false); 672 variableRateData.addLongIdentifier("variable-rate-data", true); 673 variableRateData.setArgumentGroupName( 674 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 675 parser.addArgument(variableRateData); 676 677 final FileArgument generateSampleRateFile = new FileArgument(null, 678 ARG_GENERATE_SAMPLE_RATE_FILE, false, 1, null, 679 INFO_MANAGE_ACCT_ARG_DESC_GENERATE_SAMPLE_RATE_FILE.get( 680 ARG_VARIABLE_RATE_DATA), 681 false, true, true, false); 682 generateSampleRateFile.addLongIdentifier("generate-sample-rate-file", true); 683 generateSampleRateFile.setArgumentGroupName( 684 INFO_MANAGE_ACCT_ARG_GROUP_PERFORMANCE.get()); 685 generateSampleRateFile.setUsageArgument(true); 686 parser.addArgument(generateSampleRateFile); 687 688 689 // Define the global arguments tht pertain to the reject file. 690 final FileArgument rejectFile = new FileArgument('R', ARG_REJECT_FILE, 691 false, 1, null, INFO_MANAGE_ACCT_ARG_DESC_REJECT_FILE.get(), 692 false, true, true, false); 693 rejectFile.addLongIdentifier("reject-file", true); 694 parser.addArgument(rejectFile); 695 696 final BooleanArgument appendToRejectFile = new BooleanArgument(null, 697 ARG_APPEND_TO_REJECT_FILE, 1, 698 INFO_MANAGE_ACCT_ARG_DESC_APPEND_TO_REJECT_FILE.get( 699 rejectFile.getIdentifierString())); 700 appendToRejectFile.addLongIdentifier("append-to-reject-file", true); 701 parser.addArgument(appendToRejectFile); 702 703 parser.addDependentArgumentSet(appendToRejectFile, rejectFile); 704 705 706 // Define the argument used to suppress result operations without values. 707 final BooleanArgument suppressEmptyResultOperations = 708 new BooleanArgument(null, ARG_SUPPRESS_EMPTY_RESULT_OPERATIONS, 709 1, 710 INFO_MANAGE_ACCT_ARG_DESC_SUPPRESS_EMPTY_RESULT_OPERATIONS.get( 711 getToolName())); 712 parser.addArgument(suppressEmptyResultOperations); 713 714 715 // Define the subcommand used to retrieve all state information for a user. 716 createSubCommand(GET_ALL, 717 INFO_MANAGE_ACCT_SC_GET_ALL_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 718 719 720 // Define the subcommand used to retrieve the password policy DN for a user. 721 createSubCommand(GET_PASSWORD_POLICY_DN, 722 INFO_MANAGE_ACCT_SC_GET_POLICY_DN_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 723 724 725 // Define the subcommand to determine whether the account is usable. 726 createSubCommand(GET_ACCOUNT_IS_USABLE, 727 INFO_MANAGE_ACCT_SC_GET_IS_USABLE_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 728 729 730 // Define the subcommand to retrieve the set of password policy state 731 // account usability notice messages. 732 createSubCommand(GET_ACCOUNT_USABILITY_NOTICES, 733 INFO_MANAGE_ACCT_SC_GET_USABILITY_NOTICES_EXAMPLE.get( 734 EXAMPLE_TARGET_USER_DN)); 735 736 737 // Define the subcommand to retrieve the set of password policy state 738 // account usability warning messages. 739 createSubCommand(GET_ACCOUNT_USABILITY_WARNINGS, 740 INFO_MANAGE_ACCT_SC_GET_USABILITY_WARNINGS_EXAMPLE.get( 741 EXAMPLE_TARGET_USER_DN)); 742 743 744 // Define the subcommand to retrieve the set of password policy state 745 // account usability error messages. 746 createSubCommand(GET_ACCOUNT_USABILITY_ERRORS, 747 INFO_MANAGE_ACCT_SC_GET_USABILITY_ERRORS_EXAMPLE.get( 748 EXAMPLE_TARGET_USER_DN)); 749 750 751 // Define the subcommand to retrieve the password changed time for a user. 752 createSubCommand(GET_PASSWORD_CHANGED_TIME, 753 INFO_MANAGE_ACCT_SC_GET_PW_CHANGED_TIME_EXAMPLE.get( 754 EXAMPLE_TARGET_USER_DN)); 755 756 757 // Define the subcommand to set the password changed time for a user. 758 final ArgumentParser setPWChangedTimeParser = 759 createSubCommandParser(SET_PASSWORD_CHANGED_TIME); 760 761 final TimestampArgument setPWChangedTimeValueArg = new TimestampArgument( 762 'O', "passwordChangedTime", false, 1, null, 763 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_TIME_ARG_VALUE.get()); 764 setPWChangedTimeValueArg.addLongIdentifier("operationValue", true); 765 setPWChangedTimeValueArg.addLongIdentifier("password-changed-time", true); 766 setPWChangedTimeValueArg.addLongIdentifier("operation-value", true); 767 setPWChangedTimeParser.addArgument(setPWChangedTimeValueArg); 768 769 createSubCommand(SET_PASSWORD_CHANGED_TIME, setPWChangedTimeParser, 770 createSubCommandExample(SET_PASSWORD_CHANGED_TIME, 771 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_TIME_EXAMPLE.get( 772 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 773 "--passwordChangedTime", currentGeneralizedTime)); 774 775 776 // Define the subcommand to clear the password changed time for a user. 777 createSubCommand(CLEAR_PASSWORD_CHANGED_TIME, 778 INFO_MANAGE_ACCT_SC_CLEAR_PW_CHANGED_TIME_EXAMPLE.get( 779 EXAMPLE_TARGET_USER_DN)); 780 781 782 // Define the subcommand to determine whether a user account is disabled. 783 createSubCommand(GET_ACCOUNT_IS_DISABLED, 784 INFO_MANAGE_ACCT_SC_GET_IS_DISABLED_EXAMPLE.get( 785 EXAMPLE_TARGET_USER_DN)); 786 787 788 // Define the subcommand to specify whether a user's account is disabled. 789 final ArgumentParser setAcctDisabledParser = 790 createSubCommandParser(SET_ACCOUNT_IS_DISABLED); 791 792 final BooleanValueArgument setAcctDisabledValueArg = 793 new BooleanValueArgument('O', "accountIsDisabled", true, null, 794 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_ARG_VALUE.get()); 795 setAcctDisabledValueArg.addLongIdentifier("operationValue", true); 796 setAcctDisabledValueArg.addLongIdentifier("account-is-disabled", true); 797 setAcctDisabledValueArg.addLongIdentifier("operation-value", true); 798 setAcctDisabledParser.addArgument(setAcctDisabledValueArg); 799 800 createSubCommand(SET_ACCOUNT_IS_DISABLED, setAcctDisabledParser, 801 createSubCommandExample(SET_ACCOUNT_IS_DISABLED, 802 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_EXAMPLE.get( 803 EXAMPLE_TARGET_USER_DN), 804 "--accountIsDisabled", "true")); 805 806 807 // Define the subcommand to clear the account disabled state. 808 createSubCommand(CLEAR_ACCOUNT_IS_DISABLED, 809 INFO_MANAGE_ACCT_SC_CLEAR_IS_DISABLED_EXAMPLE.get( 810 EXAMPLE_TARGET_USER_DN)); 811 812 813 // Define the subcommand to retrieve the account activation time for a user. 814 createSubCommand(GET_ACCOUNT_ACTIVATION_TIME, 815 INFO_MANAGE_ACCT_SC_GET_ACCT_ACT_TIME_EXAMPLE.get( 816 EXAMPLE_TARGET_USER_DN)); 817 818 819 // Define the subcommand to set the account activation time for a user. 820 final ArgumentParser setAcctActivationTimeParser = 821 createSubCommandParser(SET_ACCOUNT_ACTIVATION_TIME); 822 823 final TimestampArgument setAcctActivationTimeValueArg = 824 new TimestampArgument('O', "accountActivationTime", false, 1, null, 825 INFO_MANAGE_ACCT_SC_SET_ACCT_ACT_TIME_ARG_VALUE.get()); 826 setAcctActivationTimeValueArg.addLongIdentifier("operationValue", true); 827 setAcctActivationTimeValueArg.addLongIdentifier("account-activation-time", 828 true); 829 setAcctActivationTimeValueArg.addLongIdentifier("operation-value", true); 830 setAcctActivationTimeParser.addArgument(setAcctActivationTimeValueArg); 831 832 createSubCommand(SET_ACCOUNT_ACTIVATION_TIME, setAcctActivationTimeParser, 833 createSubCommandExample(SET_ACCOUNT_ACTIVATION_TIME, 834 INFO_MANAGE_ACCT_SC_SET_ACCT_ACT_TIME_EXAMPLE.get( 835 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 836 "--accountActivationTime", currentGeneralizedTime)); 837 838 839 // Define the subcommand to clear the account activation time for a user. 840 createSubCommand(CLEAR_ACCOUNT_ACTIVATION_TIME, 841 INFO_MANAGE_ACCT_SC_CLEAR_ACCT_ACT_TIME_EXAMPLE.get( 842 EXAMPLE_TARGET_USER_DN)); 843 844 845 // Define the subcommand to retrieve the length of time until a user's 846 // account is activated. 847 createSubCommand(GET_SECONDS_UNTIL_ACCOUNT_ACTIVATION, 848 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_ACCT_ACT_EXAMPLE.get( 849 EXAMPLE_TARGET_USER_DN)); 850 851 852 // Define the subcommand to determine whether a user's account is not yet 853 // active. 854 createSubCommand(GET_ACCOUNT_IS_NOT_YET_ACTIVE, 855 INFO_MANAGE_ACCT_SC_GET_ACCT_NOT_YET_ACTIVE_EXAMPLE.get( 856 EXAMPLE_TARGET_USER_DN)); 857 858 859 // Define the subcommand to retrieve the account expiration time for a user. 860 createSubCommand(GET_ACCOUNT_EXPIRATION_TIME, 861 INFO_MANAGE_ACCT_SC_GET_ACCT_EXP_TIME_EXAMPLE.get( 862 EXAMPLE_TARGET_USER_DN)); 863 864 865 // Define the subcommand to set the account expiration time for a user. 866 final ArgumentParser setAcctExpirationTimeParser = 867 createSubCommandParser(SET_ACCOUNT_EXPIRATION_TIME); 868 869 final TimestampArgument setAcctExpirationTimeValueArg = 870 new TimestampArgument('O', "accountExpirationTime", false, 1, null, 871 INFO_MANAGE_ACCT_SC_SET_ACCT_EXP_TIME_ARG_VALUE.get()); 872 setAcctExpirationTimeValueArg.addLongIdentifier("operationValue", true); 873 setAcctExpirationTimeValueArg.addLongIdentifier("account-expiration-time", 874 true); 875 setAcctExpirationTimeValueArg.addLongIdentifier("operation-value", true); 876 setAcctExpirationTimeParser.addArgument(setAcctExpirationTimeValueArg); 877 878 createSubCommand(SET_ACCOUNT_EXPIRATION_TIME, setAcctExpirationTimeParser, 879 createSubCommandExample(SET_ACCOUNT_EXPIRATION_TIME, 880 INFO_MANAGE_ACCT_SC_SET_ACCT_EXP_TIME_EXAMPLE.get( 881 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 882 "--accountExpirationTime", currentGeneralizedTime)); 883 884 885 // Define the subcommand to clear the account expiration time for a user. 886 createSubCommand(CLEAR_ACCOUNT_EXPIRATION_TIME, 887 INFO_MANAGE_ACCT_SC_CLEAR_ACCT_EXP_TIME_EXAMPLE.get( 888 EXAMPLE_TARGET_USER_DN)); 889 890 891 // Define the subcommand to retrieve the length of time until a user's 892 // account is expired. 893 createSubCommand(GET_SECONDS_UNTIL_ACCOUNT_EXPIRATION, 894 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_ACCT_EXP_EXAMPLE.get( 895 EXAMPLE_TARGET_USER_DN)); 896 897 898 // Define the subcommand to determine whether a user's account is expired. 899 createSubCommand(GET_ACCOUNT_IS_EXPIRED, 900 INFO_MANAGE_ACCT_SC_GET_ACCT_IS_EXPIRED_EXAMPLE.get( 901 EXAMPLE_TARGET_USER_DN)); 902 903 904 // Define the subcommand to retrieve a user's password expiration warned 905 // time. 906 createSubCommand(GET_PASSWORD_EXPIRATION_WARNED_TIME, 907 INFO_MANAGE_ACCT_SC_GET_PW_EXP_WARNED_TIME_EXAMPLE.get( 908 EXAMPLE_TARGET_USER_DN)); 909 910 911 // Define the subcommand to set a user's password expiration warned time. 912 final ArgumentParser setPWExpWarnedTimeParser = 913 createSubCommandParser(SET_PASSWORD_EXPIRATION_WARNED_TIME); 914 915 final TimestampArgument setPWExpWarnedTimeValueArg = 916 new TimestampArgument('O', "passwordExpirationWarnedTime", false, 1, 917 null, INFO_MANAGE_ACCT_SC_SET_PW_EXP_WARNED_TIME_ARG_VALUE.get()); 918 setPWExpWarnedTimeValueArg.addLongIdentifier("operationValue", true); 919 setPWExpWarnedTimeValueArg.addLongIdentifier( 920 "password-expiration-warned-time", true); 921 setPWExpWarnedTimeValueArg.addLongIdentifier("operation-value", true); 922 setPWExpWarnedTimeParser.addArgument(setPWExpWarnedTimeValueArg); 923 924 createSubCommand(SET_PASSWORD_EXPIRATION_WARNED_TIME, 925 setPWExpWarnedTimeParser, 926 createSubCommandExample(SET_PASSWORD_EXPIRATION_WARNED_TIME, 927 INFO_MANAGE_ACCT_SC_SET_PW_EXP_WARNED_TIME_EXAMPLE.get( 928 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 929 "--passwordExpirationWarnedTime", currentGeneralizedTime)); 930 931 932 // Define the subcommand to clear a user's password expiration warned time. 933 createSubCommand(CLEAR_PASSWORD_EXPIRATION_WARNED_TIME, 934 INFO_MANAGE_ACCT_SC_CLEAR_PW_EXP_WARNED_TIME_EXAMPLE.get( 935 EXAMPLE_TARGET_USER_DN)); 936 937 938 // Define the subcommand to get the number of seconds until a user is 939 // eligible to receive a password expiration warning. 940 createSubCommand(GET_SECONDS_UNTIL_PASSWORD_EXPIRATION_WARNING, 941 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_PW_EXP_WARNING_EXAMPLE.get( 942 EXAMPLE_TARGET_USER_DN)); 943 944 945 // Define the subcommand to retrieve a user's password expiration time. 946 createSubCommand(GET_PASSWORD_EXPIRATION_TIME, 947 INFO_MANAGE_ACCT_SC_GET_PW_EXP_TIME_EXAMPLE.get( 948 EXAMPLE_TARGET_USER_DN)); 949 950 951 // Define the subcommand to get the number of seconds until a user's 952 // password expires. 953 createSubCommand(GET_SECONDS_UNTIL_PASSWORD_EXPIRATION, 954 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_PW_EXP_EXAMPLE.get( 955 EXAMPLE_TARGET_USER_DN)); 956 957 958 // Define the subcommand to determine whether a user's password is expired. 959 createSubCommand(GET_PASSWORD_IS_EXPIRED, 960 INFO_MANAGE_ACCT_SC_GET_PW_IS_EXPIRED_EXAMPLE.get( 961 EXAMPLE_TARGET_USER_DN)); 962 963 964 // Define the subcommand to determine whether an account is failure locked. 965 createSubCommand(GET_ACCOUNT_IS_FAILURE_LOCKED, 966 INFO_MANAGE_ACCT_SC_GET_ACCT_FAILURE_LOCKED_EXAMPLE.get( 967 EXAMPLE_TARGET_USER_DN)); 968 969 970 // Define the subcommand to specify whether an account is failure locked. 971 final ArgumentParser setIsFailureLockedParser = 972 createSubCommandParser(SET_ACCOUNT_IS_FAILURE_LOCKED); 973 974 final BooleanValueArgument setIsFailureLockedValueArg = 975 new BooleanValueArgument('O', "accountIsFailureLocked", true, null, 976 INFO_MANAGE_ACCT_SC_SET_ACCT_FAILURE_LOCKED_ARG_VALUE.get()); 977 setIsFailureLockedValueArg.addLongIdentifier("operationValue", true); 978 setIsFailureLockedValueArg.addLongIdentifier("account-is-failure-locked", 979 true); 980 setIsFailureLockedValueArg.addLongIdentifier("operation-value", true); 981 setIsFailureLockedParser.addArgument(setIsFailureLockedValueArg); 982 983 createSubCommand(SET_ACCOUNT_IS_FAILURE_LOCKED, setIsFailureLockedParser, 984 createSubCommandExample(SET_ACCOUNT_IS_FAILURE_LOCKED, 985 INFO_MANAGE_ACCT_SC_SET_ACCT_FAILURE_LOCKED_EXAMPLE.get( 986 EXAMPLE_TARGET_USER_DN), 987 "--accountIsFailureLocked", "true")); 988 989 990 // Define the subcommand to get the time an account was failure locked. 991 createSubCommand(GET_FAILURE_LOCKOUT_TIME, 992 INFO_MANAGE_ACCT_SC_GET_FAILURE_LOCKED_TIME_EXAMPLE.get( 993 EXAMPLE_TARGET_USER_DN)); 994 995 996 // Define the subcommand to get the length of time until a failure-locked 997 // account will be automatically unlocked. 998 createSubCommand(GET_SECONDS_UNTIL_AUTHENTICATION_FAILURE_UNLOCK, 999 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_FAILURE_UNLOCK_EXAMPLE.get( 1000 EXAMPLE_TARGET_USER_DN)); 1001 1002 1003 // Define the subcommand to determine the authentication failure times. 1004 createSubCommand(GET_AUTHENTICATION_FAILURE_TIMES, 1005 INFO_MANAGE_ACCT_SC_GET_AUTH_FAILURE_TIMES_EXAMPLE.get( 1006 EXAMPLE_TARGET_USER_DN)); 1007 1008 1009 // Define the subcommand to add values to the set of authentication failure 1010 // times. 1011 final ArgumentParser addAuthFailureTimeParser = 1012 createSubCommandParser(ADD_AUTHENTICATION_FAILURE_TIME); 1013 1014 final TimestampArgument addAuthFailureTimeValueArg = 1015 new TimestampArgument('O', "authenticationFailureTime", false, 0, null, 1016 INFO_MANAGE_ACCT_SC_ADD_AUTH_FAILURE_TIME_ARG_VALUE.get()); 1017 addAuthFailureTimeValueArg.addLongIdentifier("operationValue", true); 1018 addAuthFailureTimeValueArg.addLongIdentifier( 1019 "authentication-failure-time", true); 1020 addAuthFailureTimeValueArg.addLongIdentifier("operation-value", true); 1021 addAuthFailureTimeParser.addArgument(addAuthFailureTimeValueArg); 1022 1023 createSubCommand(ADD_AUTHENTICATION_FAILURE_TIME, addAuthFailureTimeParser, 1024 createSubCommandExample(ADD_AUTHENTICATION_FAILURE_TIME, 1025 INFO_MANAGE_ACCT_SC_ADD_AUTH_FAILURE_TIME_EXAMPLE.get( 1026 EXAMPLE_TARGET_USER_DN))); 1027 1028 1029 // Define the subcommand to replace the authentication failure times. 1030 final ArgumentParser setAuthFailureTimesParser = 1031 createSubCommandParser(SET_AUTHENTICATION_FAILURE_TIMES); 1032 1033 final TimestampArgument setAuthFailureTimesValueArg = 1034 new TimestampArgument('O', "authenticationFailureTime", false, 0, null, 1035 INFO_MANAGE_ACCT_SC_SET_AUTH_FAILURE_TIMES_ARG_VALUE.get()); 1036 setAuthFailureTimesValueArg.addLongIdentifier("operationValue", true); 1037 setAuthFailureTimesValueArg.addLongIdentifier( 1038 "authentication-failure-time", true); 1039 setAuthFailureTimesValueArg.addLongIdentifier("operation-value", true); 1040 setAuthFailureTimesParser.addArgument(setAuthFailureTimesValueArg); 1041 1042 createSubCommand(SET_AUTHENTICATION_FAILURE_TIMES, 1043 setAuthFailureTimesParser, 1044 createSubCommandExample(SET_AUTHENTICATION_FAILURE_TIMES, 1045 INFO_MANAGE_ACCT_SC_SET_AUTH_FAILURE_TIMES_EXAMPLE.get( 1046 EXAMPLE_TARGET_USER_DN, olderGeneralizedTime, 1047 currentGeneralizedTime), 1048 "--authenticationFailureTime", olderGeneralizedTime, 1049 "--authenticationFailureTime", currentGeneralizedTime)); 1050 1051 1052 // Define the subcommand to clear the authentication failure times. 1053 createSubCommand(CLEAR_AUTHENTICATION_FAILURE_TIMES, 1054 INFO_MANAGE_ACCT_SC_CLEAR_AUTH_FAILURE_TIMES_EXAMPLE.get( 1055 EXAMPLE_TARGET_USER_DN)); 1056 1057 1058 // Define the subcommand to get the remaining authentication failure count. 1059 createSubCommand(GET_REMAINING_AUTHENTICATION_FAILURE_COUNT, 1060 INFO_MANAGE_ACCT_SC_GET_REMAINING_FAILURE_COUNT_EXAMPLE.get( 1061 EXAMPLE_TARGET_USER_DN)); 1062 1063 1064 // Define the subcommand to determine whether the account is idle locked. 1065 createSubCommand(GET_ACCOUNT_IS_IDLE_LOCKED, 1066 INFO_MANAGE_ACCT_SC_GET_ACCT_IDLE_LOCKED_EXAMPLE.get( 1067 EXAMPLE_TARGET_USER_DN)); 1068 1069 1070 // Define the subcommand to get the length of time until the account is 1071 // idle locked. 1072 createSubCommand(GET_SECONDS_UNTIL_IDLE_LOCKOUT, 1073 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_IDLE_LOCKOUT_EXAMPLE.get( 1074 EXAMPLE_TARGET_USER_DN)); 1075 1076 1077 // Define the subcommand to get the idle lockout time for an account. 1078 createSubCommand(GET_IDLE_LOCKOUT_TIME, 1079 INFO_MANAGE_ACCT_SC_GET_IDLE_LOCKOUT_TIME_EXAMPLE.get( 1080 EXAMPLE_TARGET_USER_DN)); 1081 1082 1083 // Define the subcommand to determine whether a user's password has been 1084 // reset. 1085 createSubCommand(GET_MUST_CHANGE_PASSWORD, 1086 INFO_MANAGE_ACCT_SC_GET_MUST_CHANGE_PW_EXAMPLE.get( 1087 EXAMPLE_TARGET_USER_DN)); 1088 1089 1090 // Define the subcommand to specify whether a user's password has been 1091 // reset. 1092 final ArgumentParser setPWIsResetParser = 1093 createSubCommandParser(SET_MUST_CHANGE_PASSWORD); 1094 1095 final BooleanValueArgument setPWIsResetValueArg = 1096 new BooleanValueArgument('O', "mustChangePassword", true, null, 1097 INFO_MANAGE_ACCT_SC_SET_MUST_CHANGE_PW_ARG_VALUE.get()); 1098 setPWIsResetValueArg.addLongIdentifier("passwordIsReset", true); 1099 setPWIsResetValueArg.addLongIdentifier("operationValue", true); 1100 setPWIsResetValueArg.addLongIdentifier("must-change-password", true); 1101 setPWIsResetValueArg.addLongIdentifier("password-is-reset", true); 1102 setPWIsResetValueArg.addLongIdentifier("operation-value", true); 1103 setPWIsResetParser.addArgument(setPWIsResetValueArg); 1104 1105 createSubCommand(SET_MUST_CHANGE_PASSWORD, setPWIsResetParser, 1106 createSubCommandExample(SET_MUST_CHANGE_PASSWORD, 1107 INFO_MANAGE_ACCT_SC_SET_MUST_CHANGE_PW_EXAMPLE.get( 1108 EXAMPLE_TARGET_USER_DN), 1109 "--mustChangePassword", "true")); 1110 1111 1112 // Define the subcommand to clear the password reset state information. 1113 createSubCommand(CLEAR_MUST_CHANGE_PASSWORD, 1114 INFO_MANAGE_ACCT_SC_CLEAR_MUST_CHANGE_PW_EXAMPLE.get( 1115 EXAMPLE_TARGET_USER_DN)); 1116 1117 1118 // Define the subcommand to determine whether the account is reset locked. 1119 createSubCommand(GET_ACCOUNT_IS_PASSWORD_RESET_LOCKED, 1120 INFO_MANAGE_ACCT_SC_GET_ACCT_IS_RESET_LOCKED_EXAMPLE.get( 1121 EXAMPLE_TARGET_USER_DN)); 1122 1123 1124 // Define the subcommand to get the length of time until the password is 1125 // reset locked. 1126 createSubCommand(GET_SECONDS_UNTIL_PASSWORD_RESET_LOCKOUT, 1127 INFO_MANAGE_ACCT_SC_GET_SECONDS_UNTIL_RESET_LOCKOUT_EXAMPLE.get( 1128 EXAMPLE_TARGET_USER_DN)); 1129 1130 1131 // Define the subcommand to get the password reset lockout time. 1132 createSubCommand(GET_PASSWORD_RESET_LOCKOUT_TIME, 1133 INFO_MANAGE_ACCT_SC_GET_RESET_LOCKOUT_TIME_EXAMPLE.get( 1134 EXAMPLE_TARGET_USER_DN)); 1135 1136 1137 // Define the subcommand to get the last login time. 1138 createSubCommand(GET_LAST_LOGIN_TIME, 1139 INFO_MANAGE_ACCT_SC_GET_LAST_LOGIN_TIME_EXAMPLE.get( 1140 EXAMPLE_TARGET_USER_DN)); 1141 1142 1143 // Define the subcommand to set the last login time. 1144 final ArgumentParser setLastLoginTimeParser = 1145 createSubCommandParser(SET_LAST_LOGIN_TIME); 1146 1147 final TimestampArgument setLastLoginTimeValueArg = new TimestampArgument( 1148 'O', "lastLoginTime", false, 1, null, 1149 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_TIME_ARG_VALUE.get()); 1150 setLastLoginTimeValueArg.addLongIdentifier("operationValue", true); 1151 setLastLoginTimeValueArg.addLongIdentifier("last-login-time", true); 1152 setLastLoginTimeValueArg.addLongIdentifier("operation-value", true); 1153 setLastLoginTimeParser.addArgument(setLastLoginTimeValueArg); 1154 1155 createSubCommand(SET_LAST_LOGIN_TIME, setLastLoginTimeParser, 1156 createSubCommandExample(SET_LAST_LOGIN_TIME, 1157 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_TIME_EXAMPLE.get( 1158 EXAMPLE_TARGET_USER_DN, currentGeneralizedTime), 1159 "--lastLoginTime", currentGeneralizedTime)); 1160 1161 1162 // Define the subcommand to clear the last login time. 1163 createSubCommand(CLEAR_LAST_LOGIN_TIME, 1164 INFO_MANAGE_ACCT_SC_CLEAR_LAST_LOGIN_TIME_EXAMPLE.get( 1165 EXAMPLE_TARGET_USER_DN)); 1166 1167 1168 // Define the subcommand to get the last login IP address. 1169 createSubCommand(GET_LAST_LOGIN_IP_ADDRESS, 1170 INFO_MANAGE_ACCT_SC_GET_LAST_LOGIN_IP_EXAMPLE.get( 1171 EXAMPLE_TARGET_USER_DN)); 1172 1173 1174 // Define the subcommand to set the last login IP address. 1175 final ArgumentParser setLastLoginIPParser = 1176 createSubCommandParser(SET_LAST_LOGIN_IP_ADDRESS); 1177 1178 final StringArgument setLastLoginIPValueArg = new StringArgument('O', 1179 "lastLoginIPAddress", true, 1, null, 1180 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_IP_ARG_VALUE.get()); 1181 setLastLoginIPValueArg.addLongIdentifier("operationValue", true); 1182 setLastLoginIPValueArg.addLongIdentifier("last-login-ip-address", true); 1183 setLastLoginIPValueArg.addLongIdentifier("operation-value", true); 1184 setLastLoginIPValueArg.addValueValidator( 1185 new IPAddressArgumentValueValidator()); 1186 setLastLoginIPParser.addArgument(setLastLoginIPValueArg); 1187 1188 1189 createSubCommand(SET_LAST_LOGIN_IP_ADDRESS, setLastLoginIPParser, 1190 createSubCommandExample(SET_LAST_LOGIN_IP_ADDRESS, 1191 INFO_MANAGE_ACCT_SC_SET_LAST_LOGIN_IP_EXAMPLE.get( 1192 EXAMPLE_TARGET_USER_DN, "1.2.3.4"), 1193 "--lastLoginIPAddress", "1.2.3.4")); 1194 1195 1196 // Define the subcommand to clear the last login IP address. 1197 createSubCommand(CLEAR_LAST_LOGIN_IP_ADDRESS, 1198 INFO_MANAGE_ACCT_SC_CLEAR_LAST_LOGIN_IP_EXAMPLE.get( 1199 EXAMPLE_TARGET_USER_DN)); 1200 1201 1202 // Define the subcommand to get the grace login use times. 1203 createSubCommand(GET_GRACE_LOGIN_USE_TIMES, 1204 INFO_MANAGE_ACCT_SC_GET_GRACE_LOGIN_TIMES_EXAMPLE.get( 1205 EXAMPLE_TARGET_USER_DN)); 1206 1207 1208 // Define the subcommand to add values to the set of grace login use times. 1209 final ArgumentParser addGraceLoginTimeParser = 1210 createSubCommandParser(ADD_GRACE_LOGIN_USE_TIME); 1211 1212 final TimestampArgument addGraceLoginTimeValueArg = 1213 new TimestampArgument('O', "graceLoginUseTime", false, 0, null, 1214 INFO_MANAGE_ACCT_SC_ADD_GRACE_LOGIN_TIME_ARG_VALUE.get()); 1215 addGraceLoginTimeValueArg.addLongIdentifier("operationValue", true); 1216 addGraceLoginTimeValueArg.addLongIdentifier("grace-login-use-time", true); 1217 addGraceLoginTimeValueArg.addLongIdentifier("operation-value", true); 1218 addGraceLoginTimeParser.addArgument(addGraceLoginTimeValueArg); 1219 1220 createSubCommand(ADD_GRACE_LOGIN_USE_TIME, addGraceLoginTimeParser, 1221 createSubCommandExample(ADD_GRACE_LOGIN_USE_TIME, 1222 INFO_MANAGE_ACCT_SC_ADD_GRACE_LOGIN_TIME_EXAMPLE.get( 1223 EXAMPLE_TARGET_USER_DN))); 1224 1225 1226 // Define the subcommand to replace the set of grace login use times. 1227 final ArgumentParser setGraceLoginTimesParser = 1228 createSubCommandParser(SET_GRACE_LOGIN_USE_TIMES); 1229 1230 final TimestampArgument setGraceLoginTimesValueArg = 1231 new TimestampArgument('O', "graceLoginUseTime", false, 0, null, 1232 INFO_MANAGE_ACCT_SC_SET_GRACE_LOGIN_TIMES_ARG_VALUE.get()); 1233 setGraceLoginTimesValueArg.addLongIdentifier("operationValue", true); 1234 setGraceLoginTimesValueArg.addLongIdentifier("grace-login-use-time", true); 1235 setGraceLoginTimesValueArg.addLongIdentifier("operation-value", true); 1236 setGraceLoginTimesParser.addArgument(setGraceLoginTimesValueArg); 1237 1238 createSubCommand(SET_GRACE_LOGIN_USE_TIMES, setGraceLoginTimesParser, 1239 createSubCommandExample(SET_GRACE_LOGIN_USE_TIMES, 1240 INFO_MANAGE_ACCT_SC_SET_GRACE_LOGIN_TIMES_EXAMPLE.get( 1241 EXAMPLE_TARGET_USER_DN, olderGeneralizedTime, 1242 currentGeneralizedTime), 1243 "--graceLoginUseTime", olderGeneralizedTime, 1244 "--graceLoginUseTime", currentGeneralizedTime)); 1245 1246 1247 // Define the subcommand to clear the grace login use times. 1248 createSubCommand(CLEAR_GRACE_LOGIN_USE_TIMES, 1249 INFO_MANAGE_ACCT_SC_CLEAR_GRACE_LOGIN_TIMES_EXAMPLE.get( 1250 EXAMPLE_TARGET_USER_DN)); 1251 1252 1253 // Define the subcommand to get the remaining grace login count. 1254 createSubCommand(GET_REMAINING_GRACE_LOGIN_COUNT, 1255 INFO_MANAGE_ACCT_SC_GET_REMAINING_GRACE_LOGIN_COUNT_EXAMPLE.get( 1256 EXAMPLE_TARGET_USER_DN)); 1257 1258 1259 // Define the subcommand to get the password changed by required time value. 1260 createSubCommand(GET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1261 INFO_MANAGE_ACCT_SC_GET_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1262 EXAMPLE_TARGET_USER_DN)); 1263 1264 1265 // Define the subcommand to set the password changed by required time value. 1266 final ArgumentParser setPWChangedByReqTimeParser = 1267 createSubCommandParser(SET_PASSWORD_CHANGED_BY_REQUIRED_TIME); 1268 1269 final TimestampArgument setPWChangedByReqTimeValueArg = 1270 new TimestampArgument('O', "passwordChangedByRequiredTime", false, 1, 1271 null, 1272 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_BY_REQ_TIME_ARG_VALUE.get()); 1273 setPWChangedByReqTimeValueArg.addLongIdentifier("operationValue", true); 1274 setPWChangedByReqTimeValueArg.addLongIdentifier( 1275 "password-changed-by-required-time", true); 1276 setPWChangedByReqTimeValueArg.addLongIdentifier("operation-value", true); 1277 setPWChangedByReqTimeParser.addArgument( 1278 setPWChangedByReqTimeValueArg); 1279 1280 createSubCommand(SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1281 setPWChangedByReqTimeParser, 1282 createSubCommandExample(SET_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1283 INFO_MANAGE_ACCT_SC_SET_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1284 EXAMPLE_TARGET_USER_DN))); 1285 1286 1287 // Define the subcommand to clear the password changed by required time 1288 // value. 1289 createSubCommand(CLEAR_PASSWORD_CHANGED_BY_REQUIRED_TIME, 1290 INFO_MANAGE_ACCT_SC_CLEAR_PW_CHANGED_BY_REQ_TIME_EXAMPLE.get( 1291 EXAMPLE_TARGET_USER_DN)); 1292 1293 1294 // Define the subcommand to get the length of time until the required change 1295 // time. 1296 createSubCommand(GET_SECONDS_UNTIL_REQUIRED_PASSWORD_CHANGE_TIME, 1297 INFO_MANAGE_ACCT_SC_GET_SECS_UNTIL_REQ_CHANGE_TIME_EXAMPLE.get( 1298 EXAMPLE_TARGET_USER_DN)); 1299 1300 1301 // Define the subcommand to get the password history count. 1302 createSubCommand(GET_PASSWORD_HISTORY_COUNT, 1303 INFO_MANAGE_ACCT_SC_GET_PW_HISTORY_COUNT_EXAMPLE.get( 1304 EXAMPLE_TARGET_USER_DN)); 1305 1306 1307 // Define the subcommand to clear a user's password history. 1308 createSubCommand(CLEAR_PASSWORD_HISTORY, 1309 INFO_MANAGE_ACCT_SC_CLEAR_PW_HISTORY_EXAMPLE.get( 1310 EXAMPLE_TARGET_USER_DN)); 1311 1312 1313 // Define the subcommand to determine whether a user has a retired password. 1314 createSubCommand(GET_HAS_RETIRED_PASSWORD, 1315 INFO_MANAGE_ACCT_SC_GET_HAS_RETIRED_PW_EXAMPLE.get( 1316 EXAMPLE_TARGET_USER_DN)); 1317 1318 1319 // Define the subcommand to retrieve the time that a user's former password 1320 // was retired. 1321 createSubCommand(GET_PASSWORD_RETIRED_TIME, 1322 INFO_MANAGE_ACCT_SC_GET_PW_RETIRED_TIME_EXAMPLE.get( 1323 EXAMPLE_TARGET_USER_DN)); 1324 1325 1326 // Define the subcommand to retrieve the retired password expiration time. 1327 createSubCommand(GET_RETIRED_PASSWORD_EXPIRATION_TIME, 1328 INFO_MANAGE_ACCT_SC_GET_RETIRED_PW_EXP_TIME_EXAMPLE.get( 1329 EXAMPLE_TARGET_USER_DN)); 1330 1331 1332 // Define the subcommand to purge a retired password. 1333 createSubCommand(CLEAR_RETIRED_PASSWORD, 1334 INFO_MANAGE_ACCT_SC_PURGE_RETIRED_PW_EXAMPLE.get( 1335 EXAMPLE_TARGET_USER_DN)); 1336 1337 1338 // Define the subcommand to get the available SASL mechanisms for a user. 1339 createSubCommand(GET_AVAILABLE_SASL_MECHANISMS, 1340 INFO_MANAGE_ACCT_SC_GET_AVAILABLE_SASL_MECHS_EXAMPLE.get( 1341 EXAMPLE_TARGET_USER_DN)); 1342 1343 1344 // Define the subcommand to get the available OTP delivery mechanisms for a 1345 // user. 1346 createSubCommand(GET_AVAILABLE_OTP_DELIVERY_MECHANISMS, 1347 INFO_MANAGE_ACCT_SC_GET_AVAILABLE_OTP_MECHS_EXAMPLE.get( 1348 EXAMPLE_TARGET_USER_DN)); 1349 1350 1351 // Define the subcommand to determine whether a user has at least one TOTP 1352 // shared secret. 1353 createSubCommand(GET_HAS_TOTP_SHARED_SECRET, 1354 INFO_MANAGE_ACCT_SC_GET_HAS_TOTP_SHARED_SECRET_EXAMPLE.get( 1355 EXAMPLE_TARGET_USER_DN)); 1356 1357 1358 // Define the subcommand to add a value to the set of TOTP shared secrets 1359 // for a user. 1360 final ArgumentParser addTOTPSharedSecretParser = 1361 createSubCommandParser(ADD_TOTP_SHARED_SECRET); 1362 1363 final StringArgument addTOTPSharedSecretValueArg = 1364 new StringArgument('O', "totpSharedSecret", true, 0, null, 1365 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_ARG_VALUE.get()); 1366 addTOTPSharedSecretValueArg.addLongIdentifier("operationValue", true); 1367 addTOTPSharedSecretValueArg.addLongIdentifier("totp-shared-secret", true); 1368 addTOTPSharedSecretValueArg.addLongIdentifier("operation-value", true); 1369 addTOTPSharedSecretParser.addArgument( 1370 addTOTPSharedSecretValueArg); 1371 1372 createSubCommand(ADD_TOTP_SHARED_SECRET, addTOTPSharedSecretParser, 1373 createSubCommandExample(ADD_TOTP_SHARED_SECRET, 1374 INFO_MANAGE_ACCT_SC_ADD_TOTP_SHARED_SECRET_EXAMPLE.get( 1375 "abcdefghijklmnop", EXAMPLE_TARGET_USER_DN), 1376 "--totpSharedSecret", "abcdefghijklmnop")); 1377 1378 1379 // Define the subcommand to remove a value from the set of TOTP shared 1380 // secrets for a user. 1381 final ArgumentParser removeTOTPSharedSecretParser = 1382 createSubCommandParser(REMOVE_TOTP_SHARED_SECRET); 1383 1384 final StringArgument removeTOTPSharedSecretValueArg = 1385 new StringArgument('O', "totpSharedSecret", true, 0, null, 1386 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_ARG_VALUE.get()); 1387 removeTOTPSharedSecretValueArg.addLongIdentifier("operationValue", true); 1388 removeTOTPSharedSecretValueArg.addLongIdentifier("totp-shared-secret", 1389 true); 1390 removeTOTPSharedSecretValueArg.addLongIdentifier("operation-value", true); 1391 removeTOTPSharedSecretParser.addArgument( 1392 removeTOTPSharedSecretValueArg); 1393 1394 createSubCommand(REMOVE_TOTP_SHARED_SECRET, removeTOTPSharedSecretParser, 1395 createSubCommandExample(REMOVE_TOTP_SHARED_SECRET, 1396 INFO_MANAGE_ACCT_SC_REMOVE_TOTP_SHARED_SECRET_EXAMPLE.get( 1397 "abcdefghijklmnop", EXAMPLE_TARGET_USER_DN), 1398 "--totpSharedSecret", "abcdefghijklmnop")); 1399 1400 1401 // Define the subcommand to replace set of TOTP shared secrets for a user. 1402 final ArgumentParser setTOTPSharedSecretsParser = 1403 createSubCommandParser(SET_TOTP_SHARED_SECRETS); 1404 1405 final StringArgument setTOTPSharedSecretsValueArg = 1406 new StringArgument('O', "totpSharedSecret", true, 0, null, 1407 INFO_MANAGE_ACCT_SC_SET_TOTP_SHARED_SECRETS_ARG_VALUE.get()); 1408 setTOTPSharedSecretsValueArg.addLongIdentifier("operationValue", true); 1409 setTOTPSharedSecretsValueArg.addLongIdentifier("totp-shared-secret", true); 1410 setTOTPSharedSecretsValueArg.addLongIdentifier("operation-value", true); 1411 setTOTPSharedSecretsParser.addArgument( 1412 setTOTPSharedSecretsValueArg); 1413 1414 createSubCommand(SET_TOTP_SHARED_SECRETS, 1415 setTOTPSharedSecretsParser, 1416 createSubCommandExample(SET_TOTP_SHARED_SECRETS, 1417 INFO_MANAGE_ACCT_SC_SET_TOTP_SHARED_SECRETS_EXAMPLE.get( 1418 EXAMPLE_TARGET_USER_DN, "abcdefghijklmnop"), 1419 "--totpSharedSecret", "abcdefghijklmnop")); 1420 1421 1422 // Define the subcommand to clear the set of TOTP shared secrets for a user. 1423 createSubCommand(CLEAR_TOTP_SHARED_SECRETS, 1424 INFO_MANAGE_ACCT_SC_CLEAR_TOTP_SHARED_SECRETS_EXAMPLE.get( 1425 EXAMPLE_TARGET_USER_DN)); 1426 1427 1428 // Define the subcommand to determine whether a user has at least one 1429 // registered YubiKey OTP device public ID. 1430 createSubCommand(GET_HAS_REGISTERED_YUBIKEY_PUBLIC_ID, 1431 INFO_MANAGE_ACCT_SC_GET_HAS_YUBIKEY_ID_EXAMPLE.get( 1432 EXAMPLE_TARGET_USER_DN)); 1433 1434 1435 // Define the subcommand to get the set of registered YubiKey OTP device 1436 // public IDs for a user. 1437 createSubCommand(GET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1438 INFO_MANAGE_ACCT_SC_GET_YUBIKEY_IDS_EXAMPLE.get( 1439 EXAMPLE_TARGET_USER_DN)); 1440 1441 1442 // Define the subcommand to add a value to the set of registered YubiKey OTP 1443 // device public IDs for a user. 1444 final ArgumentParser addRegisteredYubiKeyPublicIDParser = 1445 createSubCommandParser(ADD_REGISTERED_YUBIKEY_PUBLIC_ID); 1446 1447 final StringArgument addRegisteredYubiKeyPublicIDValueArg = 1448 new StringArgument('O', "publicID", true, 0, null, 1449 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_ARG_VALUE.get()); 1450 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1451 true); 1452 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", true); 1453 addRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1454 true); 1455 addRegisteredYubiKeyPublicIDParser.addArgument( 1456 addRegisteredYubiKeyPublicIDValueArg); 1457 1458 createSubCommand(ADD_REGISTERED_YUBIKEY_PUBLIC_ID, 1459 addRegisteredYubiKeyPublicIDParser, 1460 createSubCommandExample(ADD_REGISTERED_YUBIKEY_PUBLIC_ID, 1461 INFO_MANAGE_ACCT_SC_ADD_YUBIKEY_ID_EXAMPLE.get( 1462 "abcdefghijkl", EXAMPLE_TARGET_USER_DN), 1463 "--publicID", "abcdefghijkl")); 1464 1465 1466 // Define the subcommand to remove a value from the set of registered 1467 // YubiKey OTP device public IDs for a user. 1468 final ArgumentParser removeRegisteredYubiKeyPublicIDParser = 1469 createSubCommandParser(REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID); 1470 1471 final StringArgument removeRegisteredYubiKeyPublicIDValueArg = 1472 new StringArgument('O', "publicID", true, 0, null, 1473 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_ARG_VALUE.get()); 1474 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1475 true); 1476 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", 1477 true); 1478 removeRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1479 true); 1480 removeRegisteredYubiKeyPublicIDParser.addArgument( 1481 removeRegisteredYubiKeyPublicIDValueArg); 1482 1483 createSubCommand(REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID, 1484 removeRegisteredYubiKeyPublicIDParser, 1485 createSubCommandExample(REMOVE_REGISTERED_YUBIKEY_PUBLIC_ID, 1486 INFO_MANAGE_ACCT_SC_REMOVE_YUBIKEY_ID_EXAMPLE.get( 1487 "abcdefghijkl", EXAMPLE_TARGET_USER_DN), 1488 "--publicID", "abcdefghijkl")); 1489 1490 1491 // Define the subcommand to replace set of registered YubiKey OTP device 1492 // public IDs for a user. 1493 final ArgumentParser setRegisteredYubiKeyPublicIDParser = 1494 createSubCommandParser(SET_REGISTERED_YUBIKEY_PUBLIC_IDS); 1495 1496 final StringArgument setRegisteredYubiKeyPublicIDValueArg = 1497 new StringArgument('O', "publicID", true, 0, null, 1498 INFO_MANAGE_ACCT_SC_SET_YUBIKEY_IDS_ARG_VALUE.get()); 1499 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operationValue", 1500 true); 1501 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("public-id", true); 1502 setRegisteredYubiKeyPublicIDValueArg.addLongIdentifier("operation-value", 1503 true); 1504 setRegisteredYubiKeyPublicIDParser.addArgument( 1505 setRegisteredYubiKeyPublicIDValueArg); 1506 1507 createSubCommand(SET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1508 setRegisteredYubiKeyPublicIDParser, 1509 createSubCommandExample(SET_REGISTERED_YUBIKEY_PUBLIC_IDS, 1510 INFO_MANAGE_ACCT_SC_SET_YUBIKEY_IDS_EXAMPLE.get( 1511 EXAMPLE_TARGET_USER_DN, "abcdefghijkl"), 1512 "--publicID", "abcdefghijkl")); 1513 1514 1515 // Define the subcommand to clear the set of registered YubiKey OTP device 1516 // public IDs for a user. 1517 createSubCommand(CLEAR_REGISTERED_YUBIKEY_PUBLIC_IDS, 1518 INFO_MANAGE_ACCT_SC_CLEAR_YUBIKEY_IDS_EXAMPLE.get( 1519 EXAMPLE_TARGET_USER_DN)); 1520 1521 1522 // Define the subcommand to determine whether a user has at least one static 1523 // password. 1524 createSubCommand(GET_HAS_STATIC_PASSWORD, 1525 INFO_MANAGE_ACCT_SC_GET_HAS_STATIC_PW_EXAMPLE.get( 1526 EXAMPLE_TARGET_USER_DN)); 1527 } 1528 1529 1530 1531 /** 1532 * Creates an argument parser for the provided subcommand type. It will not 1533 * have any arguments associated with it. 1534 * 1535 * @param type The subcommand type for which to create the argument parser. 1536 * 1537 * @return The created argument parser. 1538 * 1539 * @throws ArgumentException If a problem is encountered while creating the 1540 * argument parser. 1541 */ 1542 private static ArgumentParser createSubCommandParser( 1543 final ManageAccountSubCommandType type) 1544 throws ArgumentException 1545 { 1546 return new ArgumentParser(type.getPrimaryName(), type.getDescription()); 1547 } 1548 1549 1550 1551 /** 1552 * Generates an example usage map for a specified subcommand. 1553 * 1554 * @param t The subcommand type. 1555 * @param description The description to use for the example. 1556 * @param args The set of arguments to include in the example, 1557 * excluding the subcommand name and the arguments used 1558 * to connect and authenticate to the server. This may 1559 * be empty if no additional arguments are needed. 1560 * 1561 * @return The generated example usage map. 1562 */ 1563 private static LinkedHashMap<String[],String> createSubCommandExample( 1564 final ManageAccountSubCommandType t, 1565 final String description, final String... args) 1566 { 1567 final LinkedHashMap<String[], String> examples = 1568 new LinkedHashMap<String[], String>(1); 1569 createSubCommandExample(examples, t, description, args); 1570 return examples; 1571 } 1572 1573 1574 1575 /** 1576 * Adds an example for a specified subcommand to the given map. 1577 * 1578 * @param examples The map to which the example should be added. 1579 * @param t The subcommand type. 1580 * @param description The description to use for the example. 1581 * @param args The set of arguments to include in the example, 1582 * excluding the subcommand name and the arguments used 1583 * to connect and authenticate to the server. This may 1584 * be empty if no additional arguments are needed. 1585 */ 1586 private static void createSubCommandExample( 1587 final LinkedHashMap<String[], String> examples, 1588 final ManageAccountSubCommandType t, final String description, 1589 final String... args) 1590 { 1591 final ArrayList<String> argList = new ArrayList<String>(10 + args.length); 1592 argList.add(t.getPrimaryName()); 1593 argList.add("--hostname"); 1594 argList.add("server.example.com"); 1595 argList.add("--port"); 1596 argList.add("389"); 1597 argList.add("--bindDN"); 1598 argList.add("uid=admin,dc=example,dc=com"); 1599 argList.add("--promptForBindPassword"); 1600 argList.add("--targetDN"); 1601 argList.add("uid=jdoe,ou=People,dc=example,dc=com"); 1602 1603 if (args.length > 0) 1604 { 1605 argList.addAll(Arrays.asList(args)); 1606 } 1607 1608 final String[] argArray = new String[argList.size()]; 1609 argList.toArray(argArray); 1610 1611 examples.put(argArray, description); 1612 } 1613 1614 1615 1616 /** 1617 * Creates a subcommand with the provided information. 1618 * 1619 * @param subcommandType The subcommand type. 1620 * @param exampleDescription The description to use for the 1621 * automatically-generated example. 1622 * 1623 * @throws ArgumentException If a problem is encountered while creating the 1624 * subcommand. 1625 */ 1626 private void createSubCommand( 1627 final ManageAccountSubCommandType subcommandType, 1628 final String exampleDescription) 1629 throws ArgumentException 1630 { 1631 final ArgumentParser subcommandParser = 1632 createSubCommandParser(subcommandType); 1633 1634 final LinkedHashMap<String[],String> examples = 1635 createSubCommandExample(subcommandType, exampleDescription); 1636 1637 createSubCommand(subcommandType, subcommandParser, examples); 1638 } 1639 1640 1641 1642 /** 1643 * Creates a subcommand with the provided information. 1644 * 1645 * @param subcommandType The subcommand type. 1646 * @param subcommandParser The argument parser for the subcommand-specific 1647 * arguments. 1648 * @param examples The example usages for the subcommand. 1649 * 1650 * @throws ArgumentException If a problem is encountered while creating the 1651 * subcommand. 1652 */ 1653 private void createSubCommand( 1654 final ManageAccountSubCommandType subcommandType, 1655 final ArgumentParser subcommandParser, 1656 final LinkedHashMap<String[],String> examples) 1657 throws ArgumentException 1658 { 1659 final SubCommand subCommand = new SubCommand( 1660 subcommandType.getPrimaryName(), subcommandType.getDescription(), 1661 subcommandParser, examples); 1662 1663 for (final String alternateName : subcommandType.getAlternateNames()) 1664 { 1665 subCommand.addName(alternateName, true); 1666 } 1667 1668 parser.addSubCommand(subCommand); 1669 } 1670 1671 1672 1673 /** 1674 * {@inheritDoc} 1675 */ 1676 @Override() 1677 public LDAPConnectionOptions getConnectionOptions() 1678 { 1679 return connectionOptions; 1680 } 1681 1682 1683 1684 /** 1685 * {@inheritDoc} 1686 */ 1687 @Override() 1688 public ResultCode doToolProcessing() 1689 { 1690 // If we should just generate a sample rate data file, then do that now. 1691 final FileArgument generateSampleRateFile = 1692 parser.getFileArgument(ARG_GENERATE_SAMPLE_RATE_FILE); 1693 if (generateSampleRateFile.isPresent()) 1694 { 1695 try 1696 { 1697 RateAdjustor.writeSampleVariableRateFile( 1698 generateSampleRateFile.getValue()); 1699 return ResultCode.SUCCESS; 1700 } 1701 catch (final Exception e) 1702 { 1703 Debug.debugException(e); 1704 wrapErr(0, WRAP_COLUMN, 1705 ERR_MANAGE_ACCT_CANNOT_GENERATE_SAMPLE_RATE_FILE.get( 1706 generateSampleRateFile.getValue().getAbsolutePath(), 1707 StaticUtils.getExceptionMessage(e))); 1708 return ResultCode.LOCAL_ERROR; 1709 } 1710 } 1711 1712 1713 // If we need to create a fixed-rate barrier and/or use a variable rate 1714 // definition, then set that up. 1715 final IntegerArgument ratePerSecond = 1716 parser.getIntegerArgument(ARG_RATE_PER_SECOND); 1717 final FileArgument variableRateData = 1718 parser.getFileArgument(ARG_VARIABLE_RATE_DATA); 1719 if (ratePerSecond.isPresent() || variableRateData.isPresent()) 1720 { 1721 if (ratePerSecond.isPresent()) 1722 { 1723 rateLimiter = new FixedRateBarrier(1000L, ratePerSecond.getValue()); 1724 } 1725 else 1726 { 1727 rateLimiter = new FixedRateBarrier(1000L, Integer.MAX_VALUE); 1728 } 1729 1730 if (variableRateData.isPresent()) 1731 { 1732 try 1733 { 1734 rateAdjustor = RateAdjustor.newInstance(rateLimiter, 1735 ratePerSecond.getValue(), variableRateData.getValue()); 1736 } 1737 catch (final Exception e) 1738 { 1739 Debug.debugException(e); 1740 wrapErr(0, WRAP_COLUMN, 1741 ERR_MANAGE_ACCT_CANNOT_CREATE_RATE_ADJUSTOR.get( 1742 variableRateData.getValue().getAbsolutePath(), 1743 StaticUtils.getExceptionMessage(e))); 1744 return ResultCode.PARAM_ERROR; 1745 } 1746 } 1747 } 1748 1749 1750 // Create the connection pool to use for all processing. 1751 final LDAPConnectionPool pool; 1752 final int numSearchThreads = 1753 parser.getIntegerArgument(ARG_NUM_SEARCH_THREADS).getValue(); 1754 try 1755 { 1756 final int numOperationThreads = 1757 parser.getIntegerArgument(ARG_NUM_THREADS).getValue(); 1758 pool = getConnectionPool(numOperationThreads, 1759 (numOperationThreads + numSearchThreads)); 1760 1761 // Explicitly disable automatic retry, since it probably won't work 1762 // reliably for extended operations anyway. We'll handle retry manually. 1763 pool.setRetryFailedOperationsDueToInvalidConnections(false); 1764 1765 // Set a maximum connection age of 30 minutes. 1766 pool.setMaxConnectionAgeMillis(1800000L); 1767 } 1768 catch (final LDAPException le) 1769 { 1770 Debug.debugException(le); 1771 1772 wrapErr(0, WRAP_COLUMN, 1773 ERR_MANAGE_ACCT_CANNOT_CREATE_CONNECTION_POOL.get(getToolName(), 1774 le.getMessage())); 1775 return le.getResultCode(); 1776 } 1777 1778 1779 try 1780 { 1781 // Create the output writer. This should always succeed. 1782 outputWriter = new LDIFWriter(getOut()); 1783 1784 1785 1786 // Create the reject writer if appropriate. 1787 final FileArgument rejectFile = parser.getFileArgument(ARG_REJECT_FILE); 1788 if (rejectFile.isPresent()) 1789 { 1790 final BooleanArgument appendToRejectFile = 1791 parser.getBooleanArgument(ARG_APPEND_TO_REJECT_FILE); 1792 1793 try 1794 { 1795 rejectWriter = new LDIFWriter(new FileOutputStream( 1796 rejectFile.getValue(), appendToRejectFile.isPresent())); 1797 } 1798 catch (final Exception e) 1799 { 1800 Debug.debugException(e); 1801 wrapErr(0, WRAP_COLUMN, 1802 ERR_MANAGE_ACCT_CANNOT_CREATE_REJECT_WRITER.get( 1803 rejectFile.getValue().getAbsolutePath(), 1804 StaticUtils.getExceptionMessage(e))); 1805 return ResultCode.LOCAL_ERROR; 1806 } 1807 } 1808 1809 1810 // Create the processor that will be used to actually perform the 1811 // manage-account operation processing for each entry. 1812 final ManageAccountProcessor processor; 1813 try 1814 { 1815 processor = new ManageAccountProcessor(this, pool, rateLimiter, 1816 outputWriter, rejectWriter); 1817 } 1818 catch (final LDAPException le) 1819 { 1820 Debug.debugException(le); 1821 wrapErr(0, WRAP_COLUMN, 1822 ERR_MANAGE_ACCT_CANNOT_CREATE_PROCESSOR.get( 1823 StaticUtils.getExceptionMessage(le))); 1824 return le.getResultCode(); 1825 } 1826 1827 1828 // If we should use a rate adjustor, then start it now. 1829 if (rateAdjustor != null) 1830 { 1831 rateAdjustor.start(); 1832 } 1833 1834 1835 // If any targetDN values were provided, then process them now. 1836 final DNArgument targetDN = parser.getDNArgument(ARG_TARGET_DN); 1837 if (targetDN.isPresent()) 1838 { 1839 for (final DN dn : targetDN.getValues()) 1840 { 1841 if (cancelRequested()) 1842 { 1843 return ResultCode.USER_CANCELED; 1844 } 1845 1846 processor.process(dn.toString()); 1847 } 1848 } 1849 1850 1851 // If any DN input files were specified, then process them now. 1852 final FileArgument dnInputFile = 1853 parser.getFileArgument(ARG_DN_INPUT_FILE); 1854 if (dnInputFile.isPresent()) 1855 { 1856 for (final File f : dnInputFile.getValues()) 1857 { 1858 DNFileReader reader = null; 1859 try 1860 { 1861 reader = new DNFileReader(f); 1862 while (true) 1863 { 1864 if (cancelRequested()) 1865 { 1866 return ResultCode.USER_CANCELED; 1867 } 1868 1869 final DN dn; 1870 try 1871 { 1872 dn = reader.readDN(); 1873 } 1874 catch (final LDAPException le) 1875 { 1876 Debug.debugException(le); 1877 processor.handleMessage(le.getMessage(), true); 1878 continue; 1879 } 1880 1881 if (dn == null) 1882 { 1883 break; 1884 } 1885 1886 processor.process(dn.toString()); 1887 } 1888 } 1889 catch (final Exception e) 1890 { 1891 Debug.debugException(e); 1892 processor.handleMessage( 1893 ERR_MANAGE_ACCT_ERROR_READING_DN_FILE.get( 1894 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 1895 true); 1896 } 1897 finally 1898 { 1899 if (reader != null) 1900 { 1901 try 1902 { 1903 reader.close(); 1904 } 1905 catch (final Exception e2) 1906 { 1907 Debug.debugException(e2); 1908 } 1909 } 1910 } 1911 } 1912 } 1913 1914 1915 // If any target filters were specified, then process them now. 1916 final FilterArgument targetFilter = 1917 parser.getFilterArgument(ARG_TARGET_FILTER); 1918 if (targetFilter.isPresent()) 1919 { 1920 searchProcessor = 1921 new ManageAccountSearchProcessor(this, processor, pool); 1922 for (final Filter f : targetFilter.getValues()) 1923 { 1924 searchProcessor.processFilter(f); 1925 } 1926 } 1927 1928 1929 // If any filter input files were specified, then process them now. 1930 final FileArgument filterInputFile = 1931 parser.getFileArgument(ARG_FILTER_INPUT_FILE); 1932 if (filterInputFile.isPresent()) 1933 { 1934 if (searchProcessor == null) 1935 { 1936 searchProcessor = 1937 new ManageAccountSearchProcessor(this, processor, pool); 1938 } 1939 1940 for (final File f : filterInputFile.getValues()) 1941 { 1942 FilterFileReader reader = null; 1943 try 1944 { 1945 reader = new FilterFileReader(f); 1946 while (true) 1947 { 1948 if (cancelRequested()) 1949 { 1950 return ResultCode.USER_CANCELED; 1951 } 1952 1953 final Filter filter; 1954 try 1955 { 1956 filter = reader.readFilter(); 1957 } 1958 catch (final LDAPException le) 1959 { 1960 Debug.debugException(le); 1961 processor.handleMessage(le.getMessage(), true); 1962 continue; 1963 } 1964 1965 if (filter == null) 1966 { 1967 break; 1968 } 1969 1970 searchProcessor.processFilter(filter); 1971 } 1972 } 1973 catch (final Exception e) 1974 { 1975 Debug.debugException(e); 1976 processor.handleMessage( 1977 ERR_MANAGE_ACCT_ERROR_READING_FILTER_FILE.get( 1978 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 1979 true); 1980 } 1981 finally 1982 { 1983 if (reader != null) 1984 { 1985 try 1986 { 1987 reader.close(); 1988 } 1989 catch (final Exception e2) 1990 { 1991 Debug.debugException(e2); 1992 } 1993 } 1994 } 1995 } 1996 } 1997 1998 1999 // If any target user IDs were specified, then process them now. 2000 final StringArgument targetUserID = 2001 parser.getStringArgument(ARG_TARGET_USER_ID); 2002 if (targetUserID.isPresent()) 2003 { 2004 if (searchProcessor == null) 2005 { 2006 searchProcessor = 2007 new ManageAccountSearchProcessor(this, processor, pool); 2008 } 2009 2010 for (final String userID : targetUserID.getValues()) 2011 { 2012 searchProcessor.processUserID(userID); 2013 } 2014 } 2015 2016 2017 // If any user ID input files were specified, then process them now. 2018 final FileArgument userIDInputFile = 2019 parser.getFileArgument(ARG_USER_ID_INPUT_FILE); 2020 if (userIDInputFile.isPresent()) 2021 { 2022 if (searchProcessor == null) 2023 { 2024 searchProcessor = 2025 new ManageAccountSearchProcessor(this, processor, pool); 2026 } 2027 2028 for (final File f : userIDInputFile.getValues()) 2029 { 2030 BufferedReader reader = null; 2031 try 2032 { 2033 reader = new BufferedReader(new FileReader(f)); 2034 while (true) 2035 { 2036 if (cancelRequested()) 2037 { 2038 return ResultCode.USER_CANCELED; 2039 } 2040 2041 final String line = reader.readLine(); 2042 if (line == null) 2043 { 2044 break; 2045 } 2046 2047 if ((line.length() == 0) || line.startsWith("#")) 2048 { 2049 continue; 2050 } 2051 2052 searchProcessor.processUserID(line.trim()); 2053 } 2054 } 2055 catch (final Exception e) 2056 { 2057 Debug.debugException(e); 2058 processor.handleMessage( 2059 ERR_MANAGE_ACCT_ERROR_READING_USER_ID_FILE.get( 2060 f.getAbsolutePath(), StaticUtils.getExceptionMessage(e)), 2061 true); 2062 } 2063 finally 2064 { 2065 if (reader != null) 2066 { 2067 try 2068 { 2069 reader.close(); 2070 } 2071 catch (final Exception e2) 2072 { 2073 Debug.debugException(e2); 2074 } 2075 } 2076 } 2077 } 2078 } 2079 2080 2081 allFiltersProvided.set(true); 2082 if (searchProcessor != null) 2083 { 2084 searchProcessor.waitForCompletion(); 2085 } 2086 2087 allDNsProvided.set(true); 2088 processor.waitForCompletion(); 2089 } 2090 finally 2091 { 2092 pool.close(); 2093 2094 if (rejectWriter != null) 2095 { 2096 try 2097 { 2098 rejectWriter.close(); 2099 } 2100 catch (final Exception e) 2101 { 2102 Debug.debugException(e); 2103 } 2104 } 2105 } 2106 2107 2108 // If we've gotten here, then we can consider the command successful, even 2109 // if some of the operations failed. 2110 return ResultCode.SUCCESS; 2111 } 2112 2113 2114 2115 /** 2116 * Retrieves the argument parser for this tool. 2117 * 2118 * @return The argument parser for this tool. 2119 */ 2120 ArgumentParser getArgumentParser() 2121 { 2122 return parser; 2123 } 2124 2125 2126 2127 /** 2128 * Indicates whether the tool should cancel its processing. 2129 * 2130 * @return {@code true} if the tool should cancel its processing, or 2131 * {@code false} if not. 2132 */ 2133 boolean cancelRequested() 2134 { 2135 return cancelRequested.get(); 2136 } 2137 2138 2139 2140 /** 2141 * Indicates whether the manage-account processor has been provided with all 2142 * of the DNs of all of the entries to process. 2143 * 2144 * @return {@code true} if the manage-account processor has been provided 2145 * with all of the DNs of all of the entries to process, or 2146 * {@code false} if not. 2147 */ 2148 boolean allDNsProvided() 2149 { 2150 return allDNsProvided.get(); 2151 } 2152 2153 2154 2155 /** 2156 * Indicates whether the manage-account search processor has been provided 2157 * with all of the filters to use to identify entries to process. 2158 * 2159 * @return {@code true} if the manage-account search processor has been 2160 * provided with all of the filters to use to identify entries to 2161 * process, or {@code false} if not. 2162 */ 2163 boolean allFiltersProvided() 2164 { 2165 return allFiltersProvided.get(); 2166 } 2167 2168 2169 2170 /** 2171 * {@inheritDoc} 2172 */ 2173 @Override() 2174 protected boolean registerShutdownHook() 2175 { 2176 return true; 2177 } 2178 2179 2180 2181 /** 2182 * {@inheritDoc} 2183 */ 2184 @Override() 2185 protected void doShutdownHookProcessing(final ResultCode resultCode) 2186 { 2187 cancelRequested.set(true); 2188 2189 if (rateLimiter != null) 2190 { 2191 rateLimiter.shutdownRequested(); 2192 } 2193 2194 if (searchProcessor != null) 2195 { 2196 searchProcessor.cancelSearches(); 2197 } 2198 } 2199 2200 2201 2202 /** 2203 * Performs any processing that may be necessary in response to the provided 2204 * unsolicited notification that has been received from the server. 2205 * 2206 * @param connection The connection on which the unsolicited notification 2207 * was received. 2208 * @param notification The unsolicited notification that has been received 2209 * from the server. 2210 */ 2211 public void handleUnsolicitedNotification(final LDAPConnection connection, 2212 final ExtendedResult notification) 2213 { 2214 final String message = NOTE_MANAGE_ACCT_UNSOLICITED_NOTIFICATION.get( 2215 String.valueOf(connection), String.valueOf(notification)); 2216 if (outputWriter == null) 2217 { 2218 err(); 2219 err("* " + message); 2220 err(); 2221 } 2222 else 2223 { 2224 try 2225 { 2226 outputWriter.writeComment(message, true, true); 2227 outputWriter.flush(); 2228 } 2229 catch (final Exception e) 2230 { 2231 // We can't really do anything about this. 2232 Debug.debugException(e); 2233 } 2234 } 2235 } 2236 2237 2238 2239 /** 2240 * {@inheritDoc} 2241 */ 2242 @Override() 2243 public LinkedHashMap<String[],String> getExampleUsages() 2244 { 2245 final LinkedHashMap<String[],String> examples = 2246 new LinkedHashMap<String[],String>(4); 2247 2248 createSubCommandExample(examples, GET_ALL, 2249 INFO_MANAGE_ACCT_SC_GET_ALL_EXAMPLE.get(EXAMPLE_TARGET_USER_DN)); 2250 2251 createSubCommandExample(examples, GET_ACCOUNT_USABILITY_ERRORS, 2252 INFO_MANAGE_ACCT_SC_GET_USABILITY_ERRORS_EXAMPLE.get( 2253 EXAMPLE_TARGET_USER_DN)); 2254 2255 createSubCommandExample(examples, SET_ACCOUNT_IS_DISABLED, 2256 INFO_MANAGE_ACCT_SC_SET_IS_DISABLED_EXAMPLE.get( 2257 EXAMPLE_TARGET_USER_DN), 2258 "--accountIsDisabled", "true"); 2259 2260 createSubCommandExample(examples, CLEAR_AUTHENTICATION_FAILURE_TIMES, 2261 INFO_MANAGE_ACCT_SC_CLEAR_AUTH_FAILURE_TIMES_EXAMPLE.get( 2262 EXAMPLE_TARGET_USER_DN)); 2263 2264 return examples; 2265 } 2266}