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