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