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.util.ArrayList; 041import java.util.Arrays; 042import java.util.List; 043import java.util.Map; 044 045import com.unboundid.asn1.ASN1OctetString; 046import com.unboundid.ldap.sdk.Attribute; 047import com.unboundid.ldap.sdk.Control; 048import com.unboundid.ldap.sdk.Entry; 049import com.unboundid.ldap.sdk.ExtendedResult; 050import com.unboundid.ldap.sdk.LDAPException; 051import com.unboundid.ldap.sdk.LDAPResult; 052import com.unboundid.ldap.sdk.OperationType; 053import com.unboundid.ldap.sdk.ResultCode; 054import com.unboundid.ldap.sdk.SearchResult; 055import com.unboundid.ldap.sdk.SearchResultEntry; 056import com.unboundid.ldap.sdk.SearchResultReference; 057import com.unboundid.ldap.sdk.controls.AuthorizationIdentityResponseControl; 058import com.unboundid.ldap.sdk.controls.ContentSyncDoneControl; 059import com.unboundid.ldap.sdk.controls.ContentSyncStateControl; 060import com.unboundid.ldap.sdk.controls.EntryChangeNotificationControl; 061import com.unboundid.ldap.sdk.controls.PasswordExpiredControl; 062import com.unboundid.ldap.sdk.controls.PasswordExpiringControl; 063import com.unboundid.ldap.sdk.controls.PersistentSearchChangeType; 064import com.unboundid.ldap.sdk.controls.PostReadResponseControl; 065import com.unboundid.ldap.sdk.controls.PreReadResponseControl; 066import com.unboundid.ldap.sdk.controls.ServerSideSortResponseControl; 067import com.unboundid.ldap.sdk.controls.SimplePagedResultsControl; 068import com.unboundid.ldap.sdk.controls.VirtualListViewResponseControl; 069import com.unboundid.ldap.sdk.extensions.AbortedTransactionExtendedResult; 070import com.unboundid.ldap.sdk.extensions.EndTransactionExtendedResult; 071import com.unboundid.ldap.sdk.extensions.NoticeOfDisconnectionExtendedResult; 072import com.unboundid.ldap.sdk.extensions.PasswordModifyExtendedResult; 073import com.unboundid.ldap.sdk.extensions.StartTransactionExtendedResult; 074import com.unboundid.ldap.sdk.unboundidds.controls.AccountUsableResponseControl; 075import com.unboundid.ldap.sdk.unboundidds.controls.AssuredReplicationLocalLevel; 076import com.unboundid.ldap.sdk.unboundidds.controls. 077 AssuredReplicationRemoteLevel; 078import com.unboundid.ldap.sdk.unboundidds.controls. 079 AssuredReplicationServerResult; 080import com.unboundid.ldap.sdk.unboundidds.controls. 081 AssuredReplicationServerResultCode; 082import com.unboundid.ldap.sdk.unboundidds.controls. 083 AssuredReplicationResponseControl; 084import com.unboundid.ldap.sdk.unboundidds.controls.AuthenticationFailureReason; 085import com.unboundid.ldap.sdk.unboundidds.controls. 086 GeneratePasswordResponseControl; 087import com.unboundid.ldap.sdk.unboundidds.controls. 088 GetAuthorizationEntryResponseControl; 089import com.unboundid.ldap.sdk.unboundidds.controls. 090 GetBackendSetIDResponseControl; 091import com.unboundid.ldap.sdk.unboundidds.controls. 092 GetPasswordPolicyStateIssuesResponseControl; 093import com.unboundid.ldap.sdk.unboundidds.controls. 094 GetRecentLoginHistoryResponseControl; 095import com.unboundid.ldap.sdk.unboundidds.controls.GetServerIDResponseControl; 096import com.unboundid.ldap.sdk.unboundidds.controls. 097 GetUserResourceLimitsResponseControl; 098import com.unboundid.ldap.sdk.unboundidds.controls. 099 IntermediateClientResponseControl; 100import com.unboundid.ldap.sdk.unboundidds.controls. 101 IntermediateClientResponseValue; 102import com.unboundid.ldap.sdk.unboundidds.controls.JoinedEntry; 103import com.unboundid.ldap.sdk.unboundidds.controls.JoinResultControl; 104import com.unboundid.ldap.sdk.unboundidds.controls. 105 MatchingEntryCountResponseControl; 106import com.unboundid.ldap.sdk.unboundidds.controls.PasswordPolicyErrorType; 107import com.unboundid.ldap.sdk.unboundidds.controls. 108 PasswordPolicyResponseControl; 109import com.unboundid.ldap.sdk.unboundidds.controls.PasswordPolicyWarningType; 110import com.unboundid.ldap.sdk.unboundidds.controls. 111 PasswordQualityRequirementValidationResult; 112import com.unboundid.ldap.sdk.unboundidds.controls. 113 PasswordValidationDetailsResponseControl; 114import com.unboundid.ldap.sdk.unboundidds.controls.RecentLoginHistory; 115import com.unboundid.ldap.sdk.unboundidds.controls.RecentLoginHistoryAttempt; 116import com.unboundid.ldap.sdk.unboundidds.controls.SoftDeleteResponseControl; 117import com.unboundid.ldap.sdk.unboundidds.controls. 118 TransactionSettingsResponseControl; 119import com.unboundid.ldap.sdk.unboundidds.controls.UniquenessResponseControl; 120import com.unboundid.ldap.sdk.unboundidds.extensions.MultiUpdateChangesApplied; 121import com.unboundid.ldap.sdk.unboundidds.extensions.MultiUpdateExtendedResult; 122import com.unboundid.ldap.sdk.unboundidds.extensions. 123 PasswordPolicyStateAccountUsabilityError; 124import com.unboundid.ldap.sdk.unboundidds.extensions. 125 PasswordPolicyStateAccountUsabilityNotice; 126import com.unboundid.ldap.sdk.unboundidds.extensions. 127 PasswordPolicyStateAccountUsabilityWarning; 128import com.unboundid.ldap.sdk.unboundidds.extensions.PasswordQualityRequirement; 129import com.unboundid.util.Debug; 130import com.unboundid.util.NotNull; 131import com.unboundid.util.ObjectPair; 132import com.unboundid.util.StaticUtils; 133import com.unboundid.util.ThreadSafety; 134import com.unboundid.util.ThreadSafetyLevel; 135 136import static com.unboundid.ldap.sdk.unboundidds.tools.ToolMessages.*; 137 138 139 140/** 141 * This class provides a set of utility methods for formatting operation 142 * results. 143 * <BR> 144 * <BLOCKQUOTE> 145 * <B>NOTE:</B> This class, and other classes within the 146 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 147 * supported for use against Ping Identity, UnboundID, and 148 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 149 * for proprietary functionality or for external specifications that are not 150 * considered stable or mature enough to be guaranteed to work in an 151 * interoperable way with other types of LDAP servers. 152 * </BLOCKQUOTE> 153 */ 154@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 155public final class ResultUtils 156{ 157 /** 158 * Ensures that this utility class can't be instantiated. 159 */ 160 private ResultUtils() 161 { 162 // No implementation required. 163 } 164 165 166 167 /** 168 * Retrieves a list of strings that comprise a formatted representation of the 169 * provided result. 170 * 171 * @param result The result to be formatted. 172 * @param comment Indicates whether to prefix each line with an octothorpe 173 * to indicate that it is a comment. 174 * @param indent The number of spaces to indent each line. 175 * @param maxWidth The maximum length of each line in characters, including 176 * the comment prefix and indent. 177 * 178 * @return A list of strings that comprise a formatted representation of the 179 * provided result. 180 */ 181 @NotNull() 182 public static List<String> formatResult(@NotNull final LDAPResult result, 183 final boolean comment, 184 final int indent, final int maxWidth) 185 { 186 final ArrayList<String> lines = new ArrayList<>(10); 187 formatResult(lines, result, comment, false, indent, maxWidth); 188 return lines; 189 } 190 191 192 193 /** 194 * Retrieves a list of strings that comprise a formatted representation of the 195 * result encapsulated by the provided exception. 196 * 197 * @param ldapException The exception to use to obtain the result to format. 198 * @param comment Indicates whether to prefix each line with an 199 * octothorpe to indicate that it is a comment. 200 * @param indent The number of spaces to indent each line. 201 * @param maxWidth The maximum length of each line in characters, 202 * including the comment prefix and indent. 203 * 204 * @return A list of strings that comprise a formatted representation of the 205 * result encapsulated by the provided exception. 206 */ 207 @NotNull() 208 public static List<String> formatResult( 209 @NotNull final LDAPException ldapException, 210 final boolean comment, 211 final int indent, final int maxWidth) 212 { 213 return formatResult(ldapException.toLDAPResult(), comment, indent, 214 maxWidth); 215 } 216 217 218 219 /** 220 * Adds a multi-line string representation of the provided result to the 221 * given list. 222 * 223 * @param lines The list to which the lines should be added. 224 * @param result The result to be formatted. 225 * @param comment Indicates whether to prefix each line with an octothorpe 226 * to indicate that it is a comment. 227 * @param inTxn Indicates whether the operation is part of an active 228 * transaction. 229 * @param indent The number of spaces to indent each line. 230 * @param maxWidth The maximum length of each line in characters, including 231 * the comment prefix and indent. 232 */ 233 public static void formatResult(@NotNull final List<String> lines, 234 @NotNull final LDAPResult result, 235 final boolean comment, final boolean inTxn, 236 final int indent, final int maxWidth) 237 { 238 formatResult(lines, result, inTxn, createPrefix(comment, indent), maxWidth); 239 } 240 241 242 243 /** 244 * Adds a multi-line string representation of the provided result to the 245 * given list. 246 * 247 * @param lines The list to which the lines should be added. 248 * @param result The result to be formatted. 249 * @param inTxn Indicates whether the operation is part of an active 250 * transaction. 251 * @param prefix The prefix to use for each line. 252 * @param maxWidth The maximum length of each line in characters, including 253 * the comment prefix and indent. 254 */ 255 private static void formatResult(@NotNull final List<String> lines, 256 @NotNull final LDAPResult result, 257 final boolean inTxn, 258 @NotNull final String prefix, 259 final int maxWidth) 260 { 261 // Format the result code. If it's a success result but the operation was 262 // part of a transaction, then indicate that no change has actually been 263 // made yet. 264 final ResultCode resultCode = result.getResultCode(); 265 wrap(lines, INFO_RESULT_UTILS_RESULT_CODE.get(String.valueOf(resultCode)), 266 prefix, maxWidth); 267 if (inTxn && (resultCode == ResultCode.SUCCESS)) 268 { 269 wrap(lines, INFO_RESULT_UTILS_SUCCESS_WITH_TXN.get(), prefix, maxWidth); 270 } 271 272 273 // Format the diagnostic message, if there is one. 274 final String diagnosticMessage = result.getDiagnosticMessage(); 275 if (diagnosticMessage != null) 276 { 277 wrap(lines, INFO_RESULT_UTILS_DIAGNOSTIC_MESSAGE.get(diagnosticMessage), 278 prefix, maxWidth); 279 } 280 281 282 // Format the matched DN, if there is one. 283 final String matchedDN = result.getMatchedDN(); 284 if (matchedDN != null) 285 { 286 wrap(lines, INFO_RESULT_UTILS_MATCHED_DN.get(matchedDN), prefix, 287 maxWidth); 288 } 289 290 291 // If there are any referral URLs, then display them. 292 final String[] referralURLs = result.getReferralURLs(); 293 if (referralURLs != null) 294 { 295 for (final String referralURL : referralURLs) 296 { 297 wrap(lines, INFO_RESULT_UTILS_REFERRAL_URL.get(referralURL), prefix, 298 maxWidth); 299 } 300 } 301 302 303 if (result instanceof SearchResult) 304 { 305 final SearchResult searchResult = (SearchResult) result; 306 307 // We'll always display the search entry count if we know it. 308 final int numEntries = searchResult.getEntryCount(); 309 if (numEntries >= 0) 310 { 311 wrap(lines, INFO_RESULT_UTILS_NUM_SEARCH_ENTRIES.get(numEntries), 312 prefix, maxWidth); 313 } 314 315 // We'll only display the search reference count if it's greater than 316 // zero. 317 final int numReferences = searchResult.getReferenceCount(); 318 if (numReferences > 0) 319 { 320 wrap(lines, INFO_RESULT_UTILS_NUM_SEARCH_REFERENCES.get(numReferences), 321 prefix, maxWidth); 322 } 323 } 324 else if (result instanceof StartTransactionExtendedResult) 325 { 326 final StartTransactionExtendedResult startTxnResult = 327 (StartTransactionExtendedResult) result; 328 final ASN1OctetString txnID = startTxnResult.getTransactionID(); 329 if (txnID != null) 330 { 331 if (StaticUtils.isPrintableString(txnID.getValue())) 332 { 333 wrap(lines, 334 INFO_RESULT_UTILS_START_TXN_RESULT_TXN_ID.get( 335 txnID.stringValue()), 336 prefix, maxWidth); 337 } 338 else 339 { 340 wrap(lines, 341 INFO_RESULT_UTILS_START_TXN_RESULT_TXN_ID.get( 342 "0x" + StaticUtils.toHex(txnID.getValue())), 343 prefix, maxWidth); 344 } 345 } 346 } 347 else if (result instanceof EndTransactionExtendedResult) 348 { 349 final EndTransactionExtendedResult endTxnResult = 350 (EndTransactionExtendedResult) result; 351 final int failedOpMessageID = endTxnResult.getFailedOpMessageID(); 352 if (failedOpMessageID > 0) 353 { 354 wrap(lines, 355 INFO_RESULT_UTILS_END_TXN_RESULT_FAILED_MSG_ID.get( 356 failedOpMessageID), 357 prefix, maxWidth); 358 } 359 360 final Map<Integer,Control[]> controls = 361 endTxnResult.getOperationResponseControls(); 362 if (controls != null) 363 { 364 for (final Map.Entry<Integer,Control[]> e : controls.entrySet()) 365 { 366 for (final Control c : e.getValue()) 367 { 368 wrap(lines, 369 INFO_RESULT_UTILS_END_TXN_RESULT_OP_CONTROL.get(e.getKey()), 370 prefix, maxWidth); 371 formatResponseControl(lines, c, prefix + " ", maxWidth); 372 } 373 } 374 } 375 } 376 else if (result instanceof MultiUpdateExtendedResult) 377 { 378 final MultiUpdateExtendedResult multiUpdateResult = 379 (MultiUpdateExtendedResult) result; 380 381 final MultiUpdateChangesApplied changesApplied = 382 multiUpdateResult.getChangesApplied(); 383 if (changesApplied != null) 384 { 385 wrap(lines, 386 INFO_RESULT_UTILS_MULTI_UPDATE_CHANGES_APPLIED.get( 387 changesApplied.name()), 388 prefix, maxWidth); 389 } 390 391 final List<ObjectPair<OperationType,LDAPResult>> multiUpdateResults = 392 multiUpdateResult.getResults(); 393 if (multiUpdateResults != null) 394 { 395 for (final ObjectPair<OperationType,LDAPResult> p : multiUpdateResults) 396 { 397 wrap(lines, 398 INFO_RESULT_UTILS_MULTI_UPDATE_RESULT_HEADER.get( 399 p.getFirst().name()), 400 prefix, maxWidth); 401 formatResult(lines, p.getSecond(), false, prefix + " ", maxWidth); 402 } 403 } 404 } 405 else if (result instanceof PasswordModifyExtendedResult) 406 { 407 final PasswordModifyExtendedResult passwordModifyResult = 408 (PasswordModifyExtendedResult) result; 409 410 final String generatedPassword = 411 passwordModifyResult.getGeneratedPassword(); 412 if (generatedPassword != null) 413 { 414 wrap(lines, 415 INFO_RESULT_UTILS_PASSWORD_MODIFY_RESULT_GENERATED_PW.get( 416 generatedPassword), 417 prefix, maxWidth); 418 } 419 } 420 else if (result instanceof ExtendedResult) 421 { 422 final ExtendedResult extendedResult = (ExtendedResult) result; 423 final String oid = ((ExtendedResult) result).getOID(); 424 if (oid != null) 425 { 426 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_OID.get(oid), prefix, 427 maxWidth); 428 } 429 430 final ASN1OctetString value = extendedResult.getValue(); 431 if ((value != null) && (value.getValueLength() > 0)) 432 { 433 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_RAW_VALUE_HEADER.get(), 434 prefix, maxWidth); 435 436 // We'll ignore the maximum width for this portion of the output. 437 for (final String line : 438 StaticUtils.stringToLines( 439 StaticUtils.toHexPlusASCII(value.getValue(), 0))) 440 { 441 lines.add(prefix + " " + line); 442 } 443 } 444 } 445 446 447 // If there are any controls, then display them. We'll interpret any 448 // controls that we can, but will fall back to a general display for any 449 // that we don't recognize or can't parse. 450 final Control[] controls = result.getResponseControls(); 451 if (controls != null) 452 { 453 for (final Control c : controls) 454 { 455 formatResponseControl(lines, c, prefix, maxWidth); 456 } 457 } 458 } 459 460 461 462 /** 463 * Updates the provided list with an LDIF representation of the provided 464 * search result entry to the given list, preceded by comments about any 465 * controls that may be included with the entry. 466 * 467 * @param lines The list to which the formatted representation will be 468 * added. 469 * @param entry The entry to be formatted. 470 * @param maxWidth The maximum length of each line in characters, including 471 * any comment prefix and indent. 472 */ 473 public static void formatSearchResultEntry(@NotNull final List<String> lines, 474 @NotNull final SearchResultEntry entry, 475 final int maxWidth) 476 { 477 for (final Control c : entry.getControls()) 478 { 479 formatResponseControl(lines, c, true, 0, maxWidth); 480 } 481 482 lines.addAll(Arrays.asList(entry.toLDIF(maxWidth))); 483 } 484 485 486 487 /** 488 * Updates the provided with with a string representation of the provided 489 * search result reference. The information will be written as LDIF 490 * comments, and will include any referral URLs contained in the reference, as 491 * well as information about any associated controls. 492 * 493 * @param lines The list to which the formatted representation will be 494 * added. 495 * @param reference The search result reference to be formatted. 496 * @param maxWidth The maximum length of each line in characters, including 497 * any comment prefix and indent. 498 */ 499 public static void formatSearchResultReference( 500 @NotNull final List<String> lines, 501 @NotNull final SearchResultReference reference, 502 final int maxWidth) 503 { 504 wrap(lines, INFO_RESULT_UTILS_SEARCH_REFERENCE_HEADER.get(), "# ", 505 maxWidth); 506 for (final String url : reference.getReferralURLs()) 507 { 508 wrap(lines, INFO_RESULT_UTILS_REFERRAL_URL.get(url), "# ", maxWidth); 509 } 510 511 for (final Control c : reference.getControls()) 512 { 513 formatResponseControl(lines, c, "# ", maxWidth); 514 } 515 } 516 517 518 519 /** 520 * Adds a multi-line string representation of the provided unsolicited 521 * notification to the given list. 522 * 523 * @param lines The list to which the lines should be added. 524 * @param notification The unsolicited notification to be formatted. 525 * @param comment Indicates whether to prefix each line with an 526 * octothorpe to indicate that it is a comment. 527 * @param indent The number of spaces to indent each line. 528 * @param maxWidth The maximum length of each line in characters, 529 * including the comment prefix and indent. 530 */ 531 public static void formatUnsolicitedNotification( 532 @NotNull final List<String> lines, 533 @NotNull final ExtendedResult notification, 534 final boolean comment, final int indent, 535 final int maxWidth) 536 { 537 final String prefix = createPrefix(comment, indent); 538 final String indentPrefix = prefix + " "; 539 540 boolean includeRawValue = true; 541 final String oid = notification.getOID(); 542 if (oid != null) 543 { 544 if (oid.equals(NoticeOfDisconnectionExtendedResult. 545 NOTICE_OF_DISCONNECTION_RESULT_OID)) 546 { 547 wrap(lines, INFO_RESULT_UTILS_NOTICE_OF_DISCONNECTION_HEADER.get(), 548 prefix, maxWidth); 549 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_OID.get(oid), 550 indentPrefix, maxWidth); 551 } 552 else if (oid.equals(AbortedTransactionExtendedResult. 553 ABORTED_TRANSACTION_RESULT_OID)) 554 { 555 wrap(lines, INFO_RESULT_UTILS_ABORTED_TXN_HEADER.get(), prefix, 556 maxWidth); 557 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_OID.get(oid), 558 indentPrefix, maxWidth); 559 560 try 561 { 562 final AbortedTransactionExtendedResult r = 563 new AbortedTransactionExtendedResult(notification); 564 565 final String txnID; 566 if (StaticUtils.isPrintableString(r.getTransactionID().getValue())) 567 { 568 txnID = r.getTransactionID().stringValue(); 569 } 570 else 571 { 572 txnID = "0x" + StaticUtils.toHex(r.getTransactionID().getValue()); 573 } 574 wrap(lines, INFO_RESULT_UTILS_TXN_ID_HEADER.get(txnID), indentPrefix, 575 maxWidth); 576 includeRawValue = false; 577 } 578 catch (final Exception e) 579 { 580 Debug.debugException(e); 581 } 582 } 583 else 584 { 585 wrap(lines, INFO_RESULT_UTILS_UNSOLICITED_NOTIFICATION_HEADER.get(), 586 prefix, maxWidth); 587 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_OID.get(oid), 588 indentPrefix, maxWidth); 589 } 590 } 591 else 592 { 593 wrap(lines, INFO_RESULT_UTILS_UNSOLICITED_NOTIFICATION_HEADER.get(), 594 prefix, maxWidth); 595 } 596 597 598 wrap(lines, 599 INFO_RESULT_UTILS_RESULT_CODE.get( 600 String.valueOf(notification.getResultCode())), 601 indentPrefix, maxWidth); 602 603 final String diagnosticMessage = notification.getDiagnosticMessage(); 604 if (diagnosticMessage != null) 605 { 606 wrap(lines, 607 INFO_RESULT_UTILS_DIAGNOSTIC_MESSAGE.get(diagnosticMessage), 608 indentPrefix, maxWidth); 609 } 610 611 final String matchedDN = notification.getMatchedDN(); 612 if (matchedDN != null) 613 { 614 wrap(lines, INFO_RESULT_UTILS_MATCHED_DN.get(matchedDN), indentPrefix, 615 maxWidth); 616 } 617 618 final String[] referralURLs = notification.getReferralURLs(); 619 if (referralURLs != null) 620 { 621 for (final String referralURL : referralURLs) 622 { 623 wrap(lines, INFO_RESULT_UTILS_REFERRAL_URL.get(referralURL), 624 indentPrefix, maxWidth); 625 } 626 } 627 628 if (includeRawValue) 629 { 630 final ASN1OctetString value = notification.getValue(); 631 if ((value != null) && (value.getValueLength() > 0)) 632 { 633 wrap(lines, INFO_RESULT_UTILS_RESPONSE_EXTOP_RAW_VALUE_HEADER.get(), 634 indentPrefix, maxWidth); 635 636 // We'll ignore the maximum width for this portion of the output. 637 for (final String line : 638 StaticUtils.stringToLines( 639 StaticUtils.toHexPlusASCII(value.getValue(), 0))) 640 { 641 lines.add(prefix + " " + line); 642 } 643 } 644 } 645 646 647 // If there are any controls, then display them. We'll interpret any 648 // controls that we can, but will fall back to a general display for any 649 // that we don't recognize or can't parse. 650 final Control[] controls = notification.getResponseControls(); 651 if (controls != null) 652 { 653 for (final Control c : controls) 654 { 655 formatResponseControl(lines, c, comment, indent+5, maxWidth); 656 } 657 } 658 } 659 660 661 662 /** 663 * Adds a multi-line string representation of the provided result to the 664 * given list. 665 * 666 * @param lines The list to which the lines should be added. 667 * @param c The control to be formatted. 668 * @param comment Indicates whether to prefix each line with an octothorpe 669 * to indicate that it is a comment. 670 * @param indent The number of spaces to indent each line. 671 * @param maxWidth The maximum length of each line in characters, including 672 * the comment prefix and indent. 673 */ 674 public static void formatResponseControl(@NotNull final List<String> lines, 675 @NotNull final Control c, 676 final boolean comment, 677 final int indent, final int maxWidth) 678 { 679 // Generate a prefix that will be used for every line. 680 final StringBuilder buffer = new StringBuilder(indent + 2); 681 if (comment) 682 { 683 buffer.append("# "); 684 } 685 for (int i=0; i < indent; i++) 686 { 687 buffer.append(' '); 688 } 689 final String prefix = buffer.toString(); 690 691 692 formatResponseControl(lines, c, prefix, maxWidth); 693 } 694 695 696 697 /** 698 * Adds a multi-line string representation of the provided control to the 699 * given list. 700 * 701 * @param lines The list to which the lines should be added. 702 * @param c The control to be formatted. 703 * @param prefix The prefix to use for each line. 704 * @param maxWidth The maximum length of each line in characters, including 705 * the comment prefix and indent. 706 */ 707 private static void formatResponseControl(@NotNull final List<String> lines, 708 @NotNull final Control c, 709 @NotNull final String prefix, 710 final int maxWidth) 711 { 712 final String oid = c.getOID(); 713 if (oid.equals(AuthorizationIdentityResponseControl. 714 AUTHORIZATION_IDENTITY_RESPONSE_OID)) 715 { 716 addAuthorizationIdentityResponseControl(lines, c, prefix, maxWidth); 717 } 718 else if (oid.equals(ContentSyncDoneControl.SYNC_DONE_OID)) 719 { 720 addContentSyncDoneControl(lines, c, prefix, maxWidth); 721 } 722 else if (oid.equals(ContentSyncStateControl.SYNC_STATE_OID)) 723 { 724 addContentSyncStateControl(lines, c, prefix, maxWidth); 725 } 726 else if (oid.equals(EntryChangeNotificationControl. 727 ENTRY_CHANGE_NOTIFICATION_OID)) 728 { 729 addEntryChangeNotificationControl(lines, c, prefix, maxWidth); 730 } 731 else if (oid.equals(PasswordExpiredControl.PASSWORD_EXPIRED_OID)) 732 { 733 addPasswordExpiredControl(lines, c, prefix, maxWidth); 734 } 735 else if (oid.equals(PasswordExpiringControl.PASSWORD_EXPIRING_OID)) 736 { 737 addPasswordExpiringControl(lines, c, prefix, maxWidth); 738 } 739 else if (oid.equals(PostReadResponseControl.POST_READ_RESPONSE_OID)) 740 { 741 addPostReadResponseControl(lines, c, prefix, maxWidth); 742 } 743 else if (oid.equals(PreReadResponseControl.PRE_READ_RESPONSE_OID)) 744 { 745 addPreReadResponseControl(lines, c, prefix, maxWidth); 746 } 747 else if (oid.equals(ServerSideSortResponseControl. 748 SERVER_SIDE_SORT_RESPONSE_OID)) 749 { 750 addServerSideSortResponseControl(lines, c, prefix, maxWidth); 751 } 752 else if (oid.equals(SimplePagedResultsControl.PAGED_RESULTS_OID)) 753 { 754 addSimplePagedResultsControl(lines, c, prefix, maxWidth); 755 } 756 else if (oid.equals(VirtualListViewResponseControl. 757 VIRTUAL_LIST_VIEW_RESPONSE_OID)) 758 { 759 addVirtualListViewResponseControl(lines, c, prefix, maxWidth); 760 } 761 else if (oid.equals(AccountUsableResponseControl. 762 ACCOUNT_USABLE_RESPONSE_OID)) 763 { 764 addAccountUsableResponseControl(lines, c, prefix, maxWidth); 765 } 766 else if (oid.equals(AssuredReplicationResponseControl. 767 ASSURED_REPLICATION_RESPONSE_OID)) 768 { 769 addAssuredReplicationResponseControl(lines, c, prefix, maxWidth); 770 } 771 else if (oid.equals(GeneratePasswordResponseControl. 772 GENERATE_PASSWORD_RESPONSE_OID)) 773 { 774 addGeneratePasswordResponseControl(lines, c, prefix, maxWidth); 775 } 776 else if (oid.equals(GetAuthorizationEntryResponseControl. 777 GET_AUTHORIZATION_ENTRY_RESPONSE_OID)) 778 { 779 addGetAuthorizationEntryResponseControl(lines, c, prefix, maxWidth); 780 } 781 else if (oid.equals(GetBackendSetIDResponseControl. 782 GET_BACKEND_SET_ID_RESPONSE_OID)) 783 { 784 addGetBackendSetIDResponseControl(lines, c, prefix, maxWidth); 785 } 786 else if (oid.equals(GetPasswordPolicyStateIssuesResponseControl. 787 GET_PASSWORD_POLICY_STATE_ISSUES_RESPONSE_OID)) 788 { 789 addGetPasswordPolicyStateIssuesResponseControl(lines, c, prefix, 790 maxWidth); 791 } 792 else if (oid.equals(GetRecentLoginHistoryResponseControl. 793 GET_RECENT_LOGIN_HISTORY_RESPONSE_OID)) 794 { 795 addGetRecentLoginHistoryResponseControl(lines, c, prefix, maxWidth); 796 } 797 else if (oid.equals(GetServerIDResponseControl.GET_SERVER_ID_RESPONSE_OID)) 798 { 799 addGetServerIDResponseControl(lines, c, prefix, maxWidth); 800 } 801 else if (oid.equals(GetUserResourceLimitsResponseControl. 802 GET_USER_RESOURCE_LIMITS_RESPONSE_OID)) 803 { 804 addGetUserResourceLimitsResponseControl(lines, c, prefix, maxWidth); 805 } 806 else if (oid.equals(IntermediateClientResponseControl. 807 INTERMEDIATE_CLIENT_RESPONSE_OID)) 808 { 809 addIntermediateClientResponseControl(lines, c, prefix, maxWidth); 810 } 811 else if (oid.equals(JoinResultControl.JOIN_RESULT_OID)) 812 { 813 addJoinResultControl(lines, c, prefix, maxWidth); 814 } 815 else if (oid.equals(MatchingEntryCountResponseControl. 816 MATCHING_ENTRY_COUNT_RESPONSE_OID)) 817 { 818 addMatchingEntryCountResponseControl(lines, c, prefix, maxWidth); 819 } 820 else if (oid.equals(PasswordPolicyResponseControl. 821 PASSWORD_POLICY_RESPONSE_OID)) 822 { 823 addPasswordPolicyResponseControl(lines, c, prefix, maxWidth); 824 } 825 else if (oid.equals(PasswordValidationDetailsResponseControl. 826 PASSWORD_VALIDATION_DETAILS_RESPONSE_OID)) 827 { 828 addPasswordValidationDetailsResponseControl(lines, c, prefix, maxWidth); 829 } 830 else if (oid.equals(SoftDeleteResponseControl.SOFT_DELETE_RESPONSE_OID)) 831 { 832 addSoftDeleteResponseControl(lines, c, prefix, maxWidth); 833 } 834 else if (oid.equals(TransactionSettingsResponseControl. 835 TRANSACTION_SETTINGS_RESPONSE_OID)) 836 { 837 addTransactionSettingsResponseControl(lines, c, prefix, maxWidth); 838 } 839 else if (oid.equals(UniquenessResponseControl.UNIQUENESS_RESPONSE_OID)) 840 { 841 addUniquenessResponseControl(lines, c, prefix, maxWidth); 842 } 843 else 844 { 845 addGenericResponseControl(lines, c, prefix, maxWidth); 846 } 847 } 848 849 850 851 /** 852 * Adds a multi-line string representation of the provided control, which will 853 * be treated as a generic control, to the given list. 854 * 855 * @param lines The list to which the lines should be added. 856 * @param c The control to be formatted. 857 * @param prefix The prefix to use for each line. 858 * @param maxWidth The maximum length of each line in characters, including 859 * the comment prefix and indent. 860 */ 861 private static void addGenericResponseControl( 862 @NotNull final List<String> lines, 863 @NotNull final Control c, 864 @NotNull final String prefix, 865 final int maxWidth) 866 { 867 wrap(lines, INFO_RESULT_UTILS_GENERIC_RESPONSE_CONTROL_HEADER.get(), 868 prefix, maxWidth); 869 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 870 prefix + " ", maxWidth); 871 wrap(lines, 872 INFO_RESULT_UTILS_RESPONSE_CONTROL_IS_CRITICAL.get(c.isCritical()), 873 prefix + " ", maxWidth); 874 875 final ASN1OctetString value = c.getValue(); 876 if ((value != null) && (value.getValue().length > 0)) 877 { 878 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_RAW_VALUE_HEADER.get(), 879 prefix + " ", maxWidth); 880 881 // We'll ignore the maximum width for this portion of the output. 882 for (final String line : 883 StaticUtils.stringToLines( 884 StaticUtils.toHexPlusASCII(value.getValue(), 0))) 885 { 886 lines.add(prefix + " " + line); 887 } 888 } 889 } 890 891 892 893 /** 894 * Adds a multi-line string representation of the provided control, which is 895 * expected to be an authorization identity response control, to the given 896 * list. 897 * 898 * @param lines The list to which the lines should be added. 899 * @param c The control to be formatted. 900 * @param prefix The prefix to use for each line. 901 * @param maxWidth The maximum length of each line in characters, including 902 * the comment prefix and indent. 903 */ 904 private static void addAuthorizationIdentityResponseControl( 905 @NotNull final List<String> lines, 906 @NotNull final Control c, 907 @NotNull final String prefix, final int maxWidth) 908 { 909 final AuthorizationIdentityResponseControl decoded; 910 try 911 { 912 decoded = new AuthorizationIdentityResponseControl(c.getOID(), 913 c.isCritical(), c.getValue()); 914 } 915 catch (final Exception e) 916 { 917 Debug.debugException(e); 918 addGenericResponseControl(lines, c, prefix, maxWidth); 919 return; 920 } 921 922 wrap(lines, INFO_RESULT_UTILS_AUTHZ_ID_RESPONSE_HEADER.get(), prefix, 923 maxWidth); 924 925 final String indentPrefix = prefix + " "; 926 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 927 indentPrefix, maxWidth); 928 wrap(lines, 929 INFO_RESULT_UTILS_AUTHZ_ID_RESPONSE_ID.get( 930 decoded.getAuthorizationID()), 931 indentPrefix, maxWidth); 932 } 933 934 935 936 /** 937 * Adds a multi-line string representation of the provided control, which is 938 * expected to be a content sync done control, to the given list. 939 * 940 * @param lines The list to which the lines should be added. 941 * @param c The control to be formatted. 942 * @param prefix The prefix to use for each line. 943 * @param maxWidth The maximum length of each line in characters, including 944 * the comment prefix and indent. 945 */ 946 private static void addContentSyncDoneControl( 947 @NotNull final List<String> lines, 948 @NotNull final Control c, 949 @NotNull final String prefix, 950 final int maxWidth) 951 { 952 final ContentSyncDoneControl decoded; 953 try 954 { 955 decoded = new ContentSyncDoneControl(c.getOID(), c.isCritical(), 956 c.getValue()); 957 } 958 catch (final Exception e) 959 { 960 Debug.debugException(e); 961 addGenericResponseControl(lines, c, prefix, maxWidth); 962 return; 963 } 964 965 wrap(lines, INFO_RESULT_UTILS_CONTENT_SYNC_DONE_RESPONSE_HEADER.get(), 966 prefix, maxWidth); 967 final String indentPrefix = prefix + " "; 968 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 969 indentPrefix, maxWidth); 970 wrap(lines, 971 INFO_RESULT_UTILS_CONTENT_SYNC_DONE_REFRESH_DELETES.get( 972 decoded.refreshDeletes()), 973 indentPrefix, maxWidth); 974 975 final ASN1OctetString cookie = decoded.getCookie(); 976 if (cookie != null) 977 { 978 wrap(lines, INFO_RESULT_UTILS_CONTENT_SYNC_DONE_COOKIE_HEADER.get(), 979 indentPrefix, maxWidth); 980 981 // We'll ignore the maximum width for this portion of the output. 982 for (final String line : 983 StaticUtils.stringToLines( 984 StaticUtils.toHexPlusASCII(cookie.getValue(), 0))) 985 { 986 lines.add(indentPrefix + " " + line); 987 } 988 } 989 } 990 991 992 993 /** 994 * Adds a multi-line string representation of the provided control, which is 995 * expected to be a content sync state control, to the given list. 996 * 997 * @param lines The list to which the lines should be added. 998 * @param c The control to be formatted. 999 * @param prefix The prefix to use for each line. 1000 * @param maxWidth The maximum length of each line in characters, including 1001 * the comment prefix and indent. 1002 */ 1003 private static void addContentSyncStateControl( 1004 @NotNull final List<String> lines, 1005 @NotNull final Control c, 1006 @NotNull final String prefix, 1007 final int maxWidth) 1008 { 1009 final ContentSyncStateControl decoded; 1010 try 1011 { 1012 decoded = new ContentSyncStateControl(c.getOID(), c.isCritical(), 1013 c.getValue()); 1014 } 1015 catch (final Exception e) 1016 { 1017 Debug.debugException(e); 1018 addGenericResponseControl(lines, c, prefix, maxWidth); 1019 return; 1020 } 1021 1022 wrap(lines, INFO_RESULT_UTILS_CONTENT_SYNC_STATE_RESPONSE_HEADER.get(), 1023 prefix, maxWidth); 1024 final String indentPrefix = prefix + " "; 1025 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1026 indentPrefix, maxWidth); 1027 wrap(lines, 1028 INFO_RESULT_UTILS_CONTENT_SYNC_STATE_ENTRY_UUID.get( 1029 decoded.getEntryUUID()), 1030 indentPrefix, maxWidth); 1031 wrap(lines, 1032 INFO_RESULT_UTILS_CONTENT_SYNC_STATE_NAME.get( 1033 decoded.getState().name()), 1034 indentPrefix, maxWidth); 1035 1036 final ASN1OctetString cookie = decoded.getCookie(); 1037 if (cookie != null) 1038 { 1039 wrap(lines, INFO_RESULT_UTILS_CONTENT_SYNC_STATE_COOKIE_HEADER.get(), 1040 indentPrefix, maxWidth); 1041 1042 // We'll ignore the maximum width for this portion of the output. 1043 for (final String line : 1044 StaticUtils.stringToLines( 1045 StaticUtils.toHexPlusASCII(cookie.getValue(), 0))) 1046 { 1047 lines.add(indentPrefix + " " + line); 1048 } 1049 } 1050 } 1051 1052 1053 1054 /** 1055 * Adds a multi-line string representation of the provided control, which is 1056 * expected to be an entry change notification control, to the given list. 1057 * 1058 * @param lines The list to which the lines should be added. 1059 * @param c The control to be formatted. 1060 * @param prefix The prefix to use for each line. 1061 * @param maxWidth The maximum length of each line in characters, including 1062 * the comment prefix and indent. 1063 */ 1064 private static void addEntryChangeNotificationControl( 1065 @NotNull final List<String> lines, 1066 @NotNull final Control c, 1067 @NotNull final String prefix, 1068 final int maxWidth) 1069 { 1070 final EntryChangeNotificationControl decoded; 1071 try 1072 { 1073 decoded = new EntryChangeNotificationControl(c.getOID(), c.isCritical(), 1074 c.getValue()); 1075 } 1076 catch (final Exception e) 1077 { 1078 Debug.debugException(e); 1079 addGenericResponseControl(lines, c, prefix, maxWidth); 1080 return; 1081 } 1082 1083 wrap(lines, INFO_RESULT_UTILS_ECN_HEADER.get(), prefix, maxWidth); 1084 1085 final String indentPrefix = prefix + " "; 1086 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1087 indentPrefix, maxWidth); 1088 1089 final PersistentSearchChangeType changeType = decoded.getChangeType(); 1090 if (changeType != null) 1091 { 1092 wrap(lines, INFO_RESULT_UTILS_ECN_CHANGE_TYPE.get(changeType.getName()), 1093 indentPrefix, maxWidth); 1094 } 1095 1096 final long changeNumber = decoded.getChangeNumber(); 1097 if (changeNumber >= 0L) 1098 { 1099 wrap(lines, INFO_RESULT_UTILS_ECN_CHANGE_NUMBER.get(changeNumber), 1100 indentPrefix, maxWidth); 1101 } 1102 1103 final String previousDN = decoded.getPreviousDN(); 1104 if (previousDN != null) 1105 { 1106 wrap(lines, INFO_RESULT_UTILS_ECN_PREVIOUS_DN.get(previousDN), 1107 indentPrefix, maxWidth); 1108 } 1109 } 1110 1111 1112 1113 /** 1114 * Adds a multi-line string representation of the provided control, which is 1115 * expected to be a password expired control, to the given list. 1116 * 1117 * @param lines The list to which the lines should be added. 1118 * @param c The control to be formatted. 1119 * @param prefix The prefix to use for each line. 1120 * @param maxWidth The maximum length of each line in characters, including 1121 * the comment prefix and indent. 1122 */ 1123 private static void addPasswordExpiredControl( 1124 @NotNull final List<String> lines, 1125 @NotNull final Control c, 1126 @NotNull final String prefix, 1127 final int maxWidth) 1128 { 1129 final PasswordExpiredControl decoded; 1130 try 1131 { 1132 decoded = new PasswordExpiredControl(c.getOID(), c.isCritical(), 1133 c.getValue()); 1134 } 1135 catch (final Exception e) 1136 { 1137 Debug.debugException(e); 1138 addGenericResponseControl(lines, c, prefix, maxWidth); 1139 return; 1140 } 1141 1142 wrap(lines, INFO_RESULT_UTILS_PASSWORD_EXPIRED_HEADER.get(), prefix, 1143 maxWidth); 1144 1145 final String indentPrefix = prefix + " "; 1146 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(decoded.getOID()), 1147 indentPrefix, maxWidth); 1148 } 1149 1150 1151 1152 /** 1153 * Adds a multi-line string representation of the provided control, which is 1154 * expected to be a password expiring control, to the given list. 1155 * 1156 * @param lines The list to which the lines should be added. 1157 * @param c The control to be formatted. 1158 * @param prefix The prefix to use for each line. 1159 * @param maxWidth The maximum length of each line in characters, including 1160 * the comment prefix and indent. 1161 */ 1162 private static void addPasswordExpiringControl( 1163 @NotNull final List<String> lines, 1164 @NotNull final Control c, 1165 @NotNull final String prefix, 1166 final int maxWidth) 1167 { 1168 final PasswordExpiringControl decoded; 1169 try 1170 { 1171 decoded = new PasswordExpiringControl(c.getOID(), c.isCritical(), 1172 c.getValue()); 1173 } 1174 catch (final Exception e) 1175 { 1176 Debug.debugException(e); 1177 addGenericResponseControl(lines, c, prefix, maxWidth); 1178 return; 1179 } 1180 1181 wrap(lines, INFO_RESULT_UTILS_PASSWORD_EXPIRING_HEADER.get(), prefix, 1182 maxWidth); 1183 1184 final String indentPrefix = prefix + " "; 1185 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1186 indentPrefix, maxWidth); 1187 1188 final int secondsUntilExpiration = decoded.getSecondsUntilExpiration(); 1189 if (secondsUntilExpiration >= 0) 1190 { 1191 wrap(lines, 1192 INFO_RESULT_UTILS_PASSWORD_EXPIRING_SECONDS_UNTIL_EXPIRATION.get( 1193 secondsUntilExpiration), 1194 indentPrefix, maxWidth); 1195 } 1196 } 1197 1198 1199 1200 /** 1201 * Adds a multi-line string representation of the provided control, which is 1202 * expected to be a post-read response control, to the given list. 1203 * 1204 * @param lines The list to which the lines should be added. 1205 * @param c The control to be formatted. 1206 * @param prefix The prefix to use for each line. 1207 * @param maxWidth The maximum length of each line in characters, including 1208 * the comment prefix and indent. 1209 */ 1210 private static void addPostReadResponseControl( 1211 @NotNull final List<String> lines, 1212 @NotNull final Control c, 1213 @NotNull final String prefix, 1214 final int maxWidth) 1215 { 1216 final PostReadResponseControl decoded; 1217 try 1218 { 1219 decoded = new PostReadResponseControl(c.getOID(), c.isCritical(), 1220 c.getValue()); 1221 } 1222 catch (final Exception e) 1223 { 1224 Debug.debugException(e); 1225 addGenericResponseControl(lines, c, prefix, maxWidth); 1226 return; 1227 } 1228 1229 wrap(lines, INFO_RESULT_UTILS_POST_READ_HEADER.get(), prefix, maxWidth); 1230 1231 final String indentPrefix = prefix + " "; 1232 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1233 indentPrefix, maxWidth); 1234 wrap(lines, INFO_RESULT_UTILS_POST_READ_ENTRY_HEADER.get(c.getOID()), 1235 indentPrefix, maxWidth); 1236 addLDIF(lines, decoded.getEntry(), true, indentPrefix + " ", maxWidth); 1237 } 1238 1239 1240 1241 /** 1242 * Adds a multi-line string representation of the provided control, which is 1243 * expected to be a pre-read response control, to the given list. 1244 * 1245 * @param lines The list to which the lines should be added. 1246 * @param c The control to be formatted. 1247 * @param prefix The prefix to use for each line. 1248 * @param maxWidth The maximum length of each line in characters, including 1249 * the comment prefix and indent. 1250 */ 1251 private static void addPreReadResponseControl( 1252 @NotNull final List<String> lines, 1253 @NotNull final Control c, 1254 @NotNull final String prefix, 1255 final int maxWidth) 1256 { 1257 final PreReadResponseControl decoded; 1258 try 1259 { 1260 decoded = new PreReadResponseControl(c.getOID(), c.isCritical(), 1261 c.getValue()); 1262 } 1263 catch (final Exception e) 1264 { 1265 Debug.debugException(e); 1266 addGenericResponseControl(lines, c, prefix, maxWidth); 1267 return; 1268 } 1269 1270 wrap(lines, INFO_RESULT_UTILS_PRE_READ_HEADER.get(), prefix, maxWidth); 1271 1272 final String indentPrefix = prefix + " "; 1273 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1274 indentPrefix, maxWidth); 1275 wrap(lines, INFO_RESULT_UTILS_PRE_READ_ENTRY_HEADER.get(c.getOID()), 1276 indentPrefix, maxWidth); 1277 addLDIF(lines, decoded.getEntry(), true, indentPrefix + " ", maxWidth); 1278 } 1279 1280 1281 1282 /** 1283 * Adds a multi-line string representation of the provided control, which is 1284 * expected to be a server-side sort response control, to the given list. 1285 * 1286 * @param lines The list to which the lines should be added. 1287 * @param c The control to be formatted. 1288 * @param prefix The prefix to use for each line. 1289 * @param maxWidth The maximum length of each line in characters, including 1290 * the comment prefix and indent. 1291 */ 1292 private static void addServerSideSortResponseControl( 1293 @NotNull final List<String> lines, 1294 @NotNull final Control c, 1295 @NotNull final String prefix, 1296 final int maxWidth) 1297 { 1298 final ServerSideSortResponseControl decoded; 1299 try 1300 { 1301 decoded = new ServerSideSortResponseControl(c.getOID(), c.isCritical(), 1302 c.getValue()); 1303 } 1304 catch (final Exception e) 1305 { 1306 Debug.debugException(e); 1307 addGenericResponseControl(lines, c, prefix, maxWidth); 1308 return; 1309 } 1310 1311 wrap(lines, INFO_RESULT_UTILS_SORT_HEADER.get(), prefix, maxWidth); 1312 1313 final String indentPrefix = prefix + " "; 1314 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1315 indentPrefix, maxWidth); 1316 1317 final ResultCode resultCode = decoded.getResultCode(); 1318 if (resultCode != null) 1319 { 1320 wrap(lines, 1321 INFO_RESULT_UTILS_SORT_RESULT_CODE.get(String.valueOf(resultCode)), 1322 indentPrefix, maxWidth); 1323 } 1324 1325 final String attributeName = decoded.getAttributeName(); 1326 if (attributeName != null) 1327 { 1328 wrap(lines, INFO_RESULT_UTILS_SORT_ATTRIBUTE_NAME.get(attributeName), 1329 indentPrefix, maxWidth); 1330 } 1331 } 1332 1333 1334 1335 /** 1336 * Adds a multi-line string representation of the provided control, which is 1337 * expected to be a simple paged results control, to the given list. 1338 * 1339 * @param lines The list to which the lines should be added. 1340 * @param c The control to be formatted. 1341 * @param prefix The prefix to use for each line. 1342 * @param maxWidth The maximum length of each line in characters, including 1343 * the comment prefix and indent. 1344 */ 1345 private static void addSimplePagedResultsControl( 1346 @NotNull final List<String> lines, 1347 @NotNull final Control c, 1348 @NotNull final String prefix, 1349 final int maxWidth) 1350 { 1351 final SimplePagedResultsControl decoded; 1352 try 1353 { 1354 decoded = new SimplePagedResultsControl(c.getOID(), c.isCritical(), 1355 c.getValue()); 1356 } 1357 catch (final Exception e) 1358 { 1359 Debug.debugException(e); 1360 addGenericResponseControl(lines, c, prefix, maxWidth); 1361 return; 1362 } 1363 1364 wrap(lines, INFO_RESULT_UTILS_PAGED_RESULTS_HEADER.get(), prefix, maxWidth); 1365 1366 final String indentPrefix = prefix + " "; 1367 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1368 indentPrefix, maxWidth); 1369 1370 final int estimatedCount = decoded.getSize(); 1371 if (estimatedCount >= 0) 1372 { 1373 wrap(lines, INFO_RESULT_UTILS_PAGED_RESULTS_COUNT.get(estimatedCount), 1374 indentPrefix, maxWidth); 1375 } 1376 1377 final ASN1OctetString cookie = decoded.getCookie(); 1378 if (cookie != null) 1379 { 1380 wrap(lines, INFO_RESULT_UTILS_PAGED_RESULTS_COOKIE_HEADER.get(), 1381 indentPrefix, maxWidth); 1382 1383 // We'll ignore the maximum width for this portion of the output. 1384 for (final String line : 1385 StaticUtils.stringToLines( 1386 StaticUtils.toHexPlusASCII(cookie.getValue(), 0))) 1387 { 1388 lines.add(indentPrefix + " " + line); 1389 } 1390 } 1391 } 1392 1393 1394 1395 /** 1396 * Adds a multi-line string representation of the provided control, which is 1397 * expected to be a virtual list view response control, to the given list. 1398 * 1399 * @param lines The list to which the lines should be added. 1400 * @param c The control to be formatted. 1401 * @param prefix The prefix to use for each line. 1402 * @param maxWidth The maximum length of each line in characters, including 1403 * the comment prefix and indent. 1404 */ 1405 private static void addVirtualListViewResponseControl( 1406 @NotNull final List<String> lines, 1407 @NotNull final Control c, 1408 @NotNull final String prefix, 1409 final int maxWidth) 1410 { 1411 final VirtualListViewResponseControl decoded; 1412 try 1413 { 1414 decoded = new VirtualListViewResponseControl(c.getOID(), c.isCritical(), 1415 c.getValue()); 1416 } 1417 catch (final Exception e) 1418 { 1419 Debug.debugException(e); 1420 addGenericResponseControl(lines, c, prefix, maxWidth); 1421 return; 1422 } 1423 1424 wrap(lines, INFO_RESULT_UTILS_VLV_HEADER.get(), prefix, maxWidth); 1425 1426 final String indentPrefix = prefix + " "; 1427 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1428 indentPrefix, maxWidth); 1429 1430 final ResultCode resultCode = decoded.getResultCode(); 1431 if (resultCode != null) 1432 { 1433 wrap(lines, 1434 INFO_RESULT_UTILS_VLV_RESULT_CODE.get(String.valueOf(resultCode)), 1435 indentPrefix, maxWidth); 1436 } 1437 1438 final int contentCount = decoded.getContentCount(); 1439 if (contentCount >= 0) 1440 { 1441 wrap(lines, INFO_RESULT_UTILS_VLV_CONTENT_COUNT.get(contentCount), 1442 indentPrefix, maxWidth); 1443 } 1444 1445 final int targetPosition = decoded.getTargetPosition(); 1446 if (targetPosition >= 0) 1447 { 1448 wrap(lines, INFO_RESULT_UTILS_VLV_TARGET_POSITION.get(targetPosition), 1449 indentPrefix, maxWidth); 1450 } 1451 1452 final ASN1OctetString contextID = decoded.getContextID(); 1453 if (contextID != null) 1454 { 1455 wrap(lines, INFO_RESULT_UTILS_VLV_CONTEXT_ID_HEADER.get(), 1456 indentPrefix, maxWidth); 1457 1458 // We'll ignore the maximum width for this portion of the output. 1459 for (final String line : 1460 StaticUtils.stringToLines( 1461 StaticUtils.toHexPlusASCII(contextID.getValue(), 0))) 1462 { 1463 lines.add(indentPrefix + " " + line); 1464 } 1465 } 1466 } 1467 1468 1469 1470 /** 1471 * Adds a multi-line string representation of the provided control, which is 1472 * expected to be an account usable response control, to the given list. 1473 * 1474 * @param lines The list to which the lines should be added. 1475 * @param c The control to be formatted. 1476 * @param prefix The prefix to use for each line. 1477 * @param maxWidth The maximum length of each line in characters, including 1478 * the comment prefix and indent. 1479 */ 1480 private static void addAccountUsableResponseControl( 1481 @NotNull final List<String> lines, 1482 @NotNull final Control c, 1483 @NotNull final String prefix, 1484 final int maxWidth) 1485 { 1486 final AccountUsableResponseControl decoded; 1487 try 1488 { 1489 decoded = new AccountUsableResponseControl(c.getOID(), c.isCritical(), 1490 c.getValue()); 1491 } 1492 catch (final Exception e) 1493 { 1494 Debug.debugException(e); 1495 addGenericResponseControl(lines, c, prefix, maxWidth); 1496 return; 1497 } 1498 1499 wrap(lines, INFO_RESULT_UTILS_ACCOUNT_USABLE_HEADER.get(), prefix, 1500 maxWidth); 1501 1502 final String indentPrefix = prefix + " "; 1503 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1504 indentPrefix, maxWidth); 1505 wrap(lines, 1506 INFO_RESULT_UTILS_ACCOUNT_USABLE_IS_USABLE.get(decoded.isUsable()), 1507 indentPrefix, maxWidth); 1508 1509 final List<String> unusableReasons = decoded.getUnusableReasons(); 1510 if ((unusableReasons != null) && (! unusableReasons.isEmpty())) 1511 { 1512 wrap(lines, 1513 INFO_RESULT_UTILS_ACCOUNT_USABLE_UNUSABLE_REASONS_HEADER.get(), 1514 indentPrefix, maxWidth); 1515 for (final String reason : unusableReasons) 1516 { 1517 wrap(lines, reason, indentPrefix + " ", maxWidth); 1518 } 1519 } 1520 1521 wrap(lines, 1522 INFO_RESULT_UTILS_ACCOUNT_USABLE_PW_EXPIRED.get( 1523 decoded.passwordIsExpired()), 1524 indentPrefix, maxWidth); 1525 wrap(lines, 1526 INFO_RESULT_UTILS_ACCOUNT_USABLE_MUST_CHANGE_PW.get( 1527 decoded.mustChangePassword()), 1528 indentPrefix, maxWidth); 1529 wrap(lines, 1530 INFO_RESULT_UTILS_ACCOUNT_USABLE_IS_INACTIVE.get(decoded.isInactive()), 1531 indentPrefix, maxWidth); 1532 1533 final int remainingGraceLogins = decoded.getRemainingGraceLogins(); 1534 if (remainingGraceLogins >= 0) 1535 { 1536 wrap(lines, 1537 INFO_RESULT_UTILS_ACCOUNT_USABLE_REMAINING_GRACE.get( 1538 remainingGraceLogins), 1539 indentPrefix, maxWidth); 1540 } 1541 1542 final int secondsUntilExpiration = decoded.getSecondsUntilExpiration(); 1543 if (secondsUntilExpiration >= 0) 1544 { 1545 wrap(lines, 1546 INFO_RESULT_UTILS_ACCOUNT_USABLE_SECONDS_UNTIL_EXPIRATION.get( 1547 secondsUntilExpiration), 1548 indentPrefix, maxWidth); 1549 } 1550 1551 final int secondsUntilUnlock = decoded.getSecondsUntilUnlock(); 1552 if (secondsUntilUnlock >= 0) 1553 { 1554 wrap(lines, 1555 INFO_RESULT_UTILS_ACCOUNT_USABLE_SECONDS_UNTIL_UNLOCK.get( 1556 secondsUntilUnlock), 1557 indentPrefix, maxWidth); 1558 } 1559 } 1560 1561 1562 1563 /** 1564 * Adds a multi-line string representation of the provided control, which is 1565 * expected to be an assured replication response control, to the given list. 1566 * 1567 * @param lines The list to which the lines should be added. 1568 * @param c The control to be formatted. 1569 * @param prefix The prefix to use for each line. 1570 * @param maxWidth The maximum length of each line in characters, including 1571 * the comment prefix and indent. 1572 */ 1573 private static void addAssuredReplicationResponseControl( 1574 @NotNull final List<String> lines, 1575 @NotNull final Control c, 1576 @NotNull final String prefix, 1577 final int maxWidth) 1578 { 1579 final AssuredReplicationResponseControl decoded; 1580 try 1581 { 1582 decoded = new AssuredReplicationResponseControl(c.getOID(), 1583 c.isCritical(), c.getValue()); 1584 } 1585 catch (final Exception e) 1586 { 1587 Debug.debugException(e); 1588 addGenericResponseControl(lines, c, prefix, maxWidth); 1589 return; 1590 } 1591 1592 wrap(lines, INFO_RESULT_UTILS_ASSURED_REPL_HEADER.get(), prefix, maxWidth); 1593 1594 final String indentPrefix = prefix + " "; 1595 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1596 indentPrefix, maxWidth); 1597 1598 final String csn = decoded.getCSN(); 1599 if (csn != null) 1600 { 1601 wrap(lines, INFO_RESULT_UTILS_ASSURED_REPL_CSN.get(csn), indentPrefix, 1602 maxWidth); 1603 } 1604 1605 final AssuredReplicationLocalLevel localLevel = decoded.getLocalLevel(); 1606 if (localLevel != null) 1607 { 1608 wrap(lines, 1609 INFO_RESULT_UTILS_ASSURED_REPL_LOCAL_LEVEL.get(localLevel.name()), 1610 indentPrefix, maxWidth); 1611 } 1612 1613 wrap(lines, 1614 INFO_RESULT_UTILS_ASSURED_REPL_LOCAL_SATISFIED.get( 1615 decoded.localAssuranceSatisfied()), 1616 indentPrefix, maxWidth); 1617 1618 final String localMessage = decoded.getLocalAssuranceMessage(); 1619 if (localMessage != null) 1620 { 1621 wrap(lines, 1622 INFO_RESULT_UTILS_ASSURED_REPL_LOCAL_MESSAGE.get(localMessage), 1623 indentPrefix, maxWidth); 1624 } 1625 1626 final AssuredReplicationRemoteLevel remoteLevel = decoded.getRemoteLevel(); 1627 if (remoteLevel != null) 1628 { 1629 wrap(lines, 1630 INFO_RESULT_UTILS_ASSURED_REPL_REMOTE_LEVEL.get(remoteLevel.name()), 1631 indentPrefix, maxWidth); 1632 } 1633 1634 wrap(lines, 1635 INFO_RESULT_UTILS_ASSURED_REPL_REMOTE_SATISFIED.get( 1636 decoded.remoteAssuranceSatisfied()), 1637 indentPrefix, maxWidth); 1638 1639 final String remoteMessage = decoded.getRemoteAssuranceMessage(); 1640 if (remoteMessage != null) 1641 { 1642 wrap(lines, 1643 INFO_RESULT_UTILS_ASSURED_REPL_REMOTE_MESSAGE.get(remoteMessage), 1644 indentPrefix, maxWidth); 1645 } 1646 1647 final List<AssuredReplicationServerResult> serverResults = 1648 decoded.getServerResults(); 1649 if (serverResults != null) 1650 { 1651 for (final AssuredReplicationServerResult r : serverResults) 1652 { 1653 wrap(lines, 1654 INFO_RESULT_UTILS_ASSURED_REPL_SERVER_RESULT_HEADER.get(), 1655 indentPrefix, maxWidth); 1656 1657 final AssuredReplicationServerResultCode rc = r.getResultCode(); 1658 if (rc != null) 1659 { 1660 wrap(lines, 1661 INFO_RESULT_UTILS_ASSURED_REPL_SERVER_RESULT_CODE.get(rc.name()), 1662 indentPrefix + " ", maxWidth); 1663 } 1664 1665 final Short replicationServerID = r.getReplicationServerID(); 1666 if (replicationServerID != null) 1667 { 1668 wrap(lines, 1669 INFO_RESULT_UTILS_ASSURED_REPL_SERVER_RESULT_REPL_SERVER_ID.get( 1670 replicationServerID), 1671 indentPrefix + " ", maxWidth); 1672 } 1673 1674 final Short replicaID = r.getReplicaID(); 1675 if (replicaID != null) 1676 { 1677 wrap(lines, 1678 INFO_RESULT_UTILS_ASSURED_REPL_SERVER_RESULT_REPL_ID.get( 1679 replicaID), 1680 indentPrefix + " ", maxWidth); 1681 } 1682 } 1683 } 1684 } 1685 1686 1687 1688 /** 1689 * Adds a multi-line string representation of the provided control, which is 1690 * expected to be a generate password response control, to the given list. 1691 * 1692 * @param lines The list to which the lines should be added. 1693 * @param c The control to be formatted. 1694 * @param prefix The prefix to use for each line. 1695 * @param maxWidth The maximum length of each line in characters, including 1696 * the comment prefix and indent. 1697 */ 1698 private static void addGeneratePasswordResponseControl( 1699 @NotNull final List<String> lines, 1700 @NotNull final Control c, 1701 @NotNull final String prefix, 1702 final int maxWidth) 1703 { 1704 final GeneratePasswordResponseControl decoded; 1705 try 1706 { 1707 decoded = new GeneratePasswordResponseControl(c.getOID(), 1708 c.isCritical(), c.getValue()); 1709 } 1710 catch (final Exception e) 1711 { 1712 Debug.debugException(e); 1713 addGenericResponseControl(lines, c, prefix, maxWidth); 1714 return; 1715 } 1716 1717 wrap(lines, INFO_RESULT_UTILS_GENERATE_PW_HEADER.get(), prefix, 1718 maxWidth); 1719 1720 final String indentPrefix = prefix + " "; 1721 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1722 indentPrefix, maxWidth); 1723 wrap(lines, 1724 INFO_RESULT_UTILS_GENERATE_PW_PASSWORD.get( 1725 decoded.getGeneratedPasswordString()), 1726 indentPrefix, maxWidth); 1727 wrap(lines, 1728 INFO_RESULT_UTILS_GENERATE_PW_MUST_CHANGE.get( 1729 String.valueOf(decoded.mustChangePassword())), 1730 indentPrefix, maxWidth); 1731 1732 if (decoded.getSecondsUntilExpiration() != null) 1733 { 1734 wrap(lines, 1735 INFO_RESULT_UTILS_GENERATE_PW_SECONDS_UNTIL_EXPIRATION.get( 1736 decoded.getSecondsUntilExpiration().longValue()), 1737 indentPrefix, maxWidth); 1738 } 1739 } 1740 1741 1742 1743 /** 1744 * Adds a multi-line string representation of the provided control, which is 1745 * expected to be a get authorization entry response control, to the given 1746 * list. 1747 * 1748 * @param lines The list to which the lines should be added. 1749 * @param c The control to be formatted. 1750 * @param prefix The prefix to use for each line. 1751 * @param maxWidth The maximum length of each line in characters, including 1752 * the comment prefix and indent. 1753 */ 1754 private static void addGetAuthorizationEntryResponseControl( 1755 @NotNull final List<String> lines, 1756 @NotNull final Control c, 1757 @NotNull final String prefix, 1758 final int maxWidth) 1759 { 1760 final GetAuthorizationEntryResponseControl decoded; 1761 try 1762 { 1763 decoded = new GetAuthorizationEntryResponseControl(c.getOID(), 1764 c.isCritical(), c.getValue()); 1765 } 1766 catch (final Exception e) 1767 { 1768 Debug.debugException(e); 1769 addGenericResponseControl(lines, c, prefix, maxWidth); 1770 return; 1771 } 1772 1773 wrap(lines, INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_HEADER.get(), prefix, 1774 maxWidth); 1775 1776 final String indentPrefix = prefix + " "; 1777 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1778 indentPrefix, maxWidth); 1779 wrap(lines, 1780 INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_IS_AUTHENTICATED.get( 1781 decoded.isAuthenticated()), 1782 indentPrefix, maxWidth); 1783 1784 if (! decoded.isAuthenticated()) 1785 { 1786 return; 1787 } 1788 1789 wrap(lines, 1790 INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_IDS_MATCH.get( 1791 decoded.identitiesMatch()), 1792 indentPrefix, maxWidth); 1793 1794 final String authNID = decoded.getAuthNID(); 1795 if (authNID != null) 1796 { 1797 wrap(lines, INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_AUTHN_ID.get(authNID), 1798 indentPrefix, maxWidth); 1799 } 1800 1801 final Entry authNEntry = decoded.getAuthNEntry(); 1802 if (authNEntry != null) 1803 { 1804 wrap(lines, INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_AUTHN_ENTRY_HEADER.get(), 1805 indentPrefix, maxWidth); 1806 addLDIF(lines, authNEntry, true, indentPrefix + " ", maxWidth); 1807 } 1808 1809 if (decoded.identitiesMatch()) 1810 { 1811 return; 1812 } 1813 1814 final String authZID = decoded.getAuthZID(); 1815 if (authZID != null) 1816 { 1817 wrap(lines, INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_AUTHZ_ID.get(authZID), 1818 indentPrefix, maxWidth); 1819 } 1820 1821 final Entry authZEntry = decoded.getAuthZEntry(); 1822 if (authZEntry != null) 1823 { 1824 wrap(lines, INFO_RESULT_UTILS_GET_AUTHZ_ENTRY_AUTHZ_ENTRY_HEADER.get(), 1825 indentPrefix, maxWidth); 1826 addLDIF(lines, authZEntry, true, indentPrefix + " ", maxWidth); 1827 } 1828 } 1829 1830 1831 1832 /** 1833 * Adds a multi-line string representation of the provided control, which is 1834 * expected to be a get backend set ID response control, to the given list. 1835 * 1836 * @param lines The list to which the lines should be added. 1837 * @param c The control to be formatted. 1838 * @param prefix The prefix to use for each line. 1839 * @param maxWidth The maximum length of each line in characters, including 1840 * the comment prefix and indent. 1841 */ 1842 private static void addGetBackendSetIDResponseControl( 1843 @NotNull final List<String> lines, 1844 @NotNull final Control c, 1845 @NotNull final String prefix, 1846 final int maxWidth) 1847 { 1848 final GetBackendSetIDResponseControl decoded; 1849 try 1850 { 1851 decoded = new GetBackendSetIDResponseControl(c.getOID(), c.isCritical(), 1852 c.getValue()); 1853 } 1854 catch (final Exception e) 1855 { 1856 Debug.debugException(e); 1857 addGenericResponseControl(lines, c, prefix, maxWidth); 1858 return; 1859 } 1860 1861 wrap(lines, INFO_RESULT_UTILS_GET_BACKEND_SET_ID_HEADER.get(), prefix, 1862 maxWidth); 1863 1864 final String indentPrefix = prefix + " "; 1865 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1866 indentPrefix, maxWidth); 1867 wrap(lines, 1868 INFO_RESULT_UTILS_GET_BACKEND_SET_ID_EB_RP_ID.get( 1869 decoded.getEntryBalancingRequestProcessorID()), 1870 indentPrefix, maxWidth); 1871 1872 for (final String id : decoded.getBackendSetIDs()) 1873 { 1874 wrap(lines, INFO_RESULT_UTILS_GET_BACKEND_SET_ID.get(id), indentPrefix, 1875 maxWidth); 1876 } 1877 } 1878 1879 1880 1881 /** 1882 * Adds a multi-line string representation of the provided control, which is 1883 * expected to be a get password policy state issues response control, to the 1884 * given list. 1885 * 1886 * @param lines The list to which the lines should be added. 1887 * @param c The control to be formatted. 1888 * @param prefix The prefix to use for each line. 1889 * @param maxWidth The maximum length of each line in characters, including 1890 * the comment prefix and indent. 1891 */ 1892 private static void addGetPasswordPolicyStateIssuesResponseControl( 1893 @NotNull final List<String> lines, 1894 @NotNull final Control c, 1895 @NotNull final String prefix, 1896 final int maxWidth) 1897 { 1898 final GetPasswordPolicyStateIssuesResponseControl decoded; 1899 try 1900 { 1901 decoded = new GetPasswordPolicyStateIssuesResponseControl(c.getOID(), 1902 c.isCritical(), c.getValue()); 1903 } 1904 catch (final Exception e) 1905 { 1906 Debug.debugException(e); 1907 addGenericResponseControl(lines, c, prefix, maxWidth); 1908 return; 1909 } 1910 1911 wrap(lines, INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_HEADER.get(), prefix, 1912 maxWidth); 1913 1914 final String indentPrefix = prefix + " "; 1915 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 1916 indentPrefix, maxWidth); 1917 1918 final String doubleIndentPrefix = indentPrefix + " "; 1919 final AuthenticationFailureReason authFailureReason = 1920 decoded.getAuthenticationFailureReason(); 1921 if (authFailureReason != null) 1922 { 1923 wrap(lines, 1924 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_FAILURE_REASON_HEADER.get(), 1925 indentPrefix, maxWidth); 1926 wrap(lines, 1927 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_FAILURE_TYPE.get( 1928 authFailureReason.getName()), 1929 doubleIndentPrefix, maxWidth); 1930 1931 final String message = authFailureReason.getMessage(); 1932 if (message != null) 1933 { 1934 wrap(lines, 1935 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_FAILURE_MESSAGE.get(message), 1936 doubleIndentPrefix, maxWidth); 1937 } 1938 } 1939 1940 final List<PasswordPolicyStateAccountUsabilityError> errors = 1941 decoded.getErrors(); 1942 if (errors != null) 1943 { 1944 for (final PasswordPolicyStateAccountUsabilityError e : errors) 1945 { 1946 wrap(lines, INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_ERROR_HEADER.get(), 1947 indentPrefix, maxWidth); 1948 wrap(lines, 1949 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_ERROR_NAME.get(e.getName()), 1950 doubleIndentPrefix, maxWidth); 1951 1952 final String message = e.getMessage(); 1953 if (message != null) 1954 { 1955 wrap(lines, 1956 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_ERROR_MESSAGE.get(message), 1957 doubleIndentPrefix, maxWidth); 1958 } 1959 } 1960 } 1961 1962 final List<PasswordPolicyStateAccountUsabilityWarning> warnings = 1963 decoded.getWarnings(); 1964 if (warnings != null) 1965 { 1966 for (final PasswordPolicyStateAccountUsabilityWarning w : warnings) 1967 { 1968 wrap(lines, INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_WARNING_HEADER.get(), 1969 indentPrefix, maxWidth); 1970 wrap(lines, 1971 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_WARNING_NAME.get( 1972 w.getName()), 1973 doubleIndentPrefix, maxWidth); 1974 1975 final String message = w.getMessage(); 1976 if (message != null) 1977 { 1978 wrap(lines, 1979 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_WARNING_MESSAGE.get( 1980 message), 1981 doubleIndentPrefix, maxWidth); 1982 } 1983 } 1984 } 1985 1986 final List<PasswordPolicyStateAccountUsabilityNotice> notices = 1987 decoded.getNotices(); 1988 if (notices != null) 1989 { 1990 for (final PasswordPolicyStateAccountUsabilityNotice n : notices) 1991 { 1992 wrap(lines, INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_NOTICE_HEADER.get(), 1993 indentPrefix, maxWidth); 1994 wrap(lines, 1995 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_NOTICE_NAME.get(n.getName()), 1996 doubleIndentPrefix, maxWidth); 1997 1998 final String message = n.getMessage(); 1999 if (message != null) 2000 { 2001 wrap(lines, 2002 INFO_RESULT_UTILS_GET_PW_STATE_ISSUES_NOTICE_MESSAGE.get( 2003 message), 2004 doubleIndentPrefix, maxWidth); 2005 } 2006 } 2007 } 2008 } 2009 2010 2011 2012 /** 2013 * Adds a multi-line string representation of the provided control, which is 2014 * expected to be a get recent login history response control, to the given 2015 * list. 2016 * 2017 * @param lines The list to which the lines should be added. 2018 * @param c The control to be formatted. 2019 * @param prefix The prefix to use for each line. 2020 * @param maxWidth The maximum length of each line in characters, including 2021 * the comment prefix and indent. 2022 */ 2023 private static void addGetRecentLoginHistoryResponseControl( 2024 @NotNull final List<String> lines, 2025 @NotNull final Control c, 2026 @NotNull final String prefix, 2027 final int maxWidth) 2028 { 2029 final GetRecentLoginHistoryResponseControl decoded; 2030 try 2031 { 2032 decoded = new GetRecentLoginHistoryResponseControl(c.getOID(), 2033 c.isCritical(), c.getValue()); 2034 } 2035 catch (final Exception e) 2036 { 2037 Debug.debugException(e); 2038 addGenericResponseControl(lines, c, prefix, maxWidth); 2039 return; 2040 } 2041 2042 wrap(lines, INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_HEADER.get(), prefix, 2043 maxWidth); 2044 2045 final String indentPrefix = prefix + " "; 2046 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2047 indentPrefix, maxWidth); 2048 2049 final RecentLoginHistory history = decoded.getRecentLoginHistory(); 2050 if (history.getSuccessfulAttempts().isEmpty()) 2051 { 2052 wrap(lines, 2053 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_NO_SUCCESSES.get(), 2054 indentPrefix, maxWidth); 2055 } 2056 2057 for (final RecentLoginHistoryAttempt attempt : 2058 history.getSuccessfulAttempts()) 2059 { 2060 wrap(lines, 2061 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_SUCCESS_HEADER.get(), 2062 indentPrefix, maxWidth); 2063 2064 final String doubleIndentPrefix = indentPrefix + " "; 2065 wrap(lines, 2066 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_TIMESTAMP.get( 2067 StaticUtils.encodeRFC3339Time(attempt.getTimestamp())), 2068 doubleIndentPrefix, maxWidth); 2069 wrap(lines, 2070 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_AUTH_METHOD.get( 2071 attempt.getAuthenticationMethod()), 2072 doubleIndentPrefix, maxWidth); 2073 2074 final String clientIP = attempt.getClientIPAddress(); 2075 if (clientIP != null) 2076 { 2077 wrap(lines, 2078 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_CLIENT_IP.get(clientIP), 2079 doubleIndentPrefix, maxWidth); 2080 } 2081 2082 final Long additionalAttemptCount = attempt.getAdditionalAttemptCount(); 2083 if (additionalAttemptCount != null) 2084 { 2085 wrap(lines, 2086 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_ADDITIONAL_COUNT.get( 2087 additionalAttemptCount), 2088 doubleIndentPrefix, maxWidth); 2089 } 2090 } 2091 2092 if (history.getFailedAttempts().isEmpty()) 2093 { 2094 wrap(lines, 2095 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_NO_FAILURES.get(), 2096 indentPrefix, maxWidth); 2097 } 2098 2099 for (final RecentLoginHistoryAttempt attempt : 2100 history.getFailedAttempts()) 2101 { 2102 wrap(lines, 2103 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_FAILURE_HEADER.get(), 2104 indentPrefix, maxWidth); 2105 2106 final String doubleIndentPrefix = indentPrefix + " "; 2107 wrap(lines, 2108 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_TIMESTAMP.get( 2109 StaticUtils.encodeRFC3339Time(attempt.getTimestamp())), 2110 doubleIndentPrefix, maxWidth); 2111 wrap(lines, 2112 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_AUTH_METHOD.get( 2113 attempt.getAuthenticationMethod()), 2114 doubleIndentPrefix, maxWidth); 2115 2116 final String clientIP = attempt.getClientIPAddress(); 2117 if (clientIP != null) 2118 { 2119 wrap(lines, 2120 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_CLIENT_IP.get(clientIP), 2121 doubleIndentPrefix, maxWidth); 2122 } 2123 2124 wrap(lines, 2125 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_FAILURE_REASON.get( 2126 attempt.getFailureReason()), 2127 doubleIndentPrefix, maxWidth); 2128 2129 final Long additionalAttemptCount = attempt.getAdditionalAttemptCount(); 2130 if (additionalAttemptCount != null) 2131 { 2132 wrap(lines, 2133 INFO_RESULT_UTILS_GET_RECENT_LOGIN_HISTORY_ADDITIONAL_COUNT.get( 2134 additionalAttemptCount), 2135 doubleIndentPrefix, maxWidth); 2136 } 2137 } 2138 } 2139 2140 2141 2142 /** 2143 * Adds a multi-line string representation of the provided control, which is 2144 * expected to be a get server ID response control, to the given list. 2145 * 2146 * @param lines The list to which the lines should be added. 2147 * @param c The control to be formatted. 2148 * @param prefix The prefix to use for each line. 2149 * @param maxWidth The maximum length of each line in characters, including 2150 * the comment prefix and indent. 2151 */ 2152 private static void addGetServerIDResponseControl( 2153 @NotNull final List<String> lines, 2154 @NotNull final Control c, 2155 @NotNull final String prefix, 2156 final int maxWidth) 2157 { 2158 final GetServerIDResponseControl decoded; 2159 try 2160 { 2161 decoded = new GetServerIDResponseControl(c.getOID(), c.isCritical(), 2162 c.getValue()); 2163 } 2164 catch (final Exception e) 2165 { 2166 Debug.debugException(e); 2167 addGenericResponseControl(lines, c, prefix, maxWidth); 2168 return; 2169 } 2170 2171 2172 wrap(lines, INFO_RESULT_UTILS_GET_SERVER_ID_HEADER.get(), prefix, 2173 maxWidth); 2174 2175 final String indentPrefix = prefix + " "; 2176 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2177 indentPrefix, maxWidth); 2178 wrap(lines, INFO_RESULT_UTILS_GET_SERVER_ID.get(decoded.getServerID()), 2179 indentPrefix, maxWidth); 2180 } 2181 2182 2183 2184 /** 2185 * Adds a multi-line string representation of the provided control, which is 2186 * expected to be a get user resource limits response control, to the given 2187 * list. 2188 * 2189 * @param lines The list to which the lines should be added. 2190 * @param c The control to be formatted. 2191 * @param prefix The prefix to use for each line. 2192 * @param maxWidth The maximum length of each line in characters, including 2193 * the comment prefix and indent. 2194 */ 2195 private static void addGetUserResourceLimitsResponseControl( 2196 @NotNull final List<String> lines, 2197 @NotNull final Control c, 2198 @NotNull final String prefix, 2199 final int maxWidth) 2200 { 2201 final GetUserResourceLimitsResponseControl decoded; 2202 try 2203 { 2204 decoded = new GetUserResourceLimitsResponseControl(c.getOID(), 2205 c.isCritical(), c.getValue()); 2206 } 2207 catch (final Exception e) 2208 { 2209 Debug.debugException(e); 2210 addGenericResponseControl(lines, c, prefix, maxWidth); 2211 return; 2212 } 2213 2214 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_HEADER.get(), prefix, 2215 maxWidth); 2216 2217 final String indentPrefix = prefix + " "; 2218 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2219 indentPrefix, maxWidth); 2220 2221 final Long sizeLimit = decoded.getSizeLimit(); 2222 if (sizeLimit != null) 2223 { 2224 final String value; 2225 if (sizeLimit > 0L) 2226 { 2227 value = String.valueOf(sizeLimit); 2228 } 2229 else 2230 { 2231 value = INFO_RESULT_UTILS_GET_USER_RLIM_VALUE_UNLIMITED.get(); 2232 } 2233 2234 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_SIZE_LIMIT.get(value), 2235 indentPrefix, maxWidth); 2236 } 2237 2238 final Long timeLimit = decoded.getTimeLimitSeconds(); 2239 if (timeLimit != null) 2240 { 2241 final String value; 2242 if (timeLimit > 0L) 2243 { 2244 value = timeLimit + " " + 2245 INFO_RESULT_UTILS_GET_USER_RLIM_UNIT_SECONDS.get(); 2246 } 2247 else 2248 { 2249 value = INFO_RESULT_UTILS_GET_USER_RLIM_VALUE_UNLIMITED.get(); 2250 } 2251 2252 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_TIME_LIMIT.get(value), 2253 indentPrefix, maxWidth); 2254 } 2255 2256 final Long idleTimeLimit = decoded.getIdleTimeLimitSeconds(); 2257 if (idleTimeLimit != null) 2258 { 2259 final String value; 2260 if (idleTimeLimit > 0L) 2261 { 2262 value = idleTimeLimit + " " + 2263 INFO_RESULT_UTILS_GET_USER_RLIM_UNIT_SECONDS.get(); 2264 } 2265 else 2266 { 2267 value = INFO_RESULT_UTILS_GET_USER_RLIM_VALUE_UNLIMITED.get(); 2268 } 2269 2270 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_IDLE_TIME_LIMIT.get(value), 2271 indentPrefix, maxWidth); 2272 } 2273 2274 final Long lookthroughLimit = decoded.getLookthroughLimit(); 2275 if (lookthroughLimit != null) 2276 { 2277 final String value; 2278 if (lookthroughLimit > 0L) 2279 { 2280 value = String.valueOf(lookthroughLimit); 2281 } 2282 else 2283 { 2284 value = INFO_RESULT_UTILS_GET_USER_RLIM_VALUE_UNLIMITED.get(); 2285 } 2286 2287 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_LOOKTHROUGH_LIMIT.get(value), 2288 indentPrefix, maxWidth); 2289 } 2290 2291 final String equivalentUserDN = decoded.getEquivalentAuthzUserDN(); 2292 if (equivalentUserDN != null) 2293 { 2294 wrap(lines, 2295 INFO_RESULT_UTILS_GET_USER_RLIM_EQUIVALENT_AUTHZ_USER_DN.get( 2296 equivalentUserDN), 2297 indentPrefix, maxWidth); 2298 } 2299 2300 final String ccpName = decoded.getClientConnectionPolicyName(); 2301 if (ccpName != null) 2302 { 2303 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_CCP_NAME.get(ccpName), 2304 indentPrefix, maxWidth); 2305 } 2306 2307 final String doubleIndentPrefix = indentPrefix + " "; 2308 final List<String> groupDNs = decoded.getGroupDNs(); 2309 if ((groupDNs != null) && (! groupDNs.isEmpty())) 2310 { 2311 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_GROUP_DNS_HEADER.get(), 2312 indentPrefix, maxWidth); 2313 for (final String groupDN : groupDNs) 2314 { 2315 wrap(lines, groupDN, doubleIndentPrefix, maxWidth); 2316 } 2317 } 2318 2319 final List<String> privilegeNames = decoded.getPrivilegeNames(); 2320 if ((privilegeNames != null) && (! privilegeNames.isEmpty())) 2321 { 2322 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_PRIVILEGES_HEADER.get(), 2323 indentPrefix, maxWidth); 2324 for (final String privilegeName : privilegeNames) 2325 { 2326 wrap(lines, privilegeName, doubleIndentPrefix, maxWidth); 2327 } 2328 } 2329 2330 final List<Attribute> otherAttrs = decoded.getOtherAttributes(); 2331 if ((otherAttrs != null) && (! otherAttrs.isEmpty())) 2332 { 2333 wrap(lines, INFO_RESULT_UTILS_GET_USER_RLIM_OTHER_ATTRIBUTES_HEADER.get(), 2334 indentPrefix, maxWidth); 2335 addLDIF(lines, new Entry("", otherAttrs), false, doubleIndentPrefix, 2336 maxWidth); 2337 } 2338 } 2339 2340 2341 2342 /** 2343 * Adds a multi-line string representation of the provided control, which is 2344 * expected to be an intermediate client response control, to the given list. 2345 * 2346 * @param lines The list to which the lines should be added. 2347 * @param c The control to be formatted. 2348 * @param prefix The prefix to use for each line. 2349 * @param maxWidth The maximum length of each line in characters, including 2350 * the comment prefix and indent. 2351 */ 2352 private static void addIntermediateClientResponseControl( 2353 @NotNull final List<String> lines, 2354 @NotNull final Control c, 2355 @NotNull final String prefix, 2356 final int maxWidth) 2357 { 2358 final IntermediateClientResponseControl decoded; 2359 try 2360 { 2361 decoded = new IntermediateClientResponseControl(c.getOID(), 2362 c.isCritical(), c.getValue()); 2363 } 2364 catch (final Exception e) 2365 { 2366 Debug.debugException(e); 2367 addGenericResponseControl(lines, c, prefix, maxWidth); 2368 return; 2369 } 2370 2371 wrap(lines, INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_HEADER.get(), prefix, 2372 maxWidth); 2373 2374 final String indentPrefix = prefix + " "; 2375 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2376 indentPrefix, maxWidth); 2377 addIntermediateResponseValue(lines, decoded.getResponseValue(), 2378 indentPrefix, maxWidth); 2379 } 2380 2381 2382 2383 /** 2384 * Adds a multi-line string representation of the provided intermediate 2385 * response value to the given list. 2386 * 2387 * @param lines The list to which the lines should be added. 2388 * @param v The value to be formatted. 2389 * @param prefix The prefix to use for each line. 2390 * @param maxWidth The maximum length of each line in characters, including 2391 * the comment prefix and indent. 2392 */ 2393 private static void addIntermediateResponseValue( 2394 @NotNull final List<String> lines, 2395 @NotNull final IntermediateClientResponseValue v, 2396 @NotNull final String prefix, 2397 final int maxWidth) 2398 { 2399 final String address = v.getUpstreamServerAddress(); 2400 if (address != null) 2401 { 2402 wrap(lines, 2403 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_UPSTREAM_ADDRESS.get(address), 2404 prefix, maxWidth); 2405 } 2406 2407 final Boolean secure = v.upstreamServerSecure(); 2408 if (secure != null) 2409 { 2410 wrap(lines, 2411 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_UPSTREAM_SECURE.get( 2412 String.valueOf(secure)), 2413 prefix, maxWidth); 2414 } 2415 2416 final String serverName = v.getServerName(); 2417 if (serverName != null) 2418 { 2419 wrap(lines, 2420 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_SERVER_NAME.get(serverName), 2421 prefix, maxWidth); 2422 } 2423 2424 final String sessionID = v.getServerSessionID(); 2425 if (sessionID != null) 2426 { 2427 wrap(lines, 2428 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_SESSION_ID.get(sessionID), 2429 prefix, maxWidth); 2430 } 2431 2432 final String responseID = v.getServerResponseID(); 2433 if (responseID != null) 2434 { 2435 wrap(lines, 2436 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_RESPONSE_ID.get(responseID), 2437 prefix, maxWidth); 2438 } 2439 2440 final IntermediateClientResponseValue upstreamResponse = 2441 v.getUpstreamResponse(); 2442 if (upstreamResponse != null) 2443 { 2444 wrap(lines, 2445 INFO_RESULT_UTILS_INTERMEDIATE_CLIENT_UPSTREAM_RESPONSE_HEADER.get(), 2446 prefix, maxWidth); 2447 addIntermediateResponseValue(lines, upstreamResponse, prefix + " ", 2448 maxWidth); 2449 } 2450 } 2451 2452 2453 2454 /** 2455 * Adds a multi-line string representation of the provided control, which is 2456 * expected to be a join result control, to the given list. 2457 * 2458 * @param lines The list to which the lines should be added. 2459 * @param c The control to be formatted. 2460 * @param prefix The prefix to use for each line. 2461 * @param maxWidth The maximum length of each line in characters, including 2462 * the comment prefix and indent. 2463 */ 2464 private static void addJoinResultControl( 2465 @NotNull final List<String> lines, 2466 @NotNull final Control c, 2467 @NotNull final String prefix, 2468 final int maxWidth) 2469 { 2470 final JoinResultControl decoded; 2471 try 2472 { 2473 decoded = new JoinResultControl(c.getOID(), c.isCritical(), c.getValue()); 2474 } 2475 catch (final Exception e) 2476 { 2477 Debug.debugException(e); 2478 addGenericResponseControl(lines, c, prefix, maxWidth); 2479 return; 2480 } 2481 2482 wrap(lines, INFO_RESULT_UTILS_JOIN_HEADER.get(), prefix, 2483 maxWidth); 2484 2485 final String indentPrefix = prefix + " "; 2486 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2487 indentPrefix, maxWidth); 2488 2489 final ResultCode resultCode = decoded.getResultCode(); 2490 if (resultCode != null) 2491 { 2492 wrap(lines, 2493 INFO_RESULT_UTILS_JOIN_RESULT_CODE.get( 2494 String.valueOf(resultCode)), 2495 indentPrefix, maxWidth); 2496 } 2497 2498 final String diagnosticMessage = decoded.getDiagnosticMessage(); 2499 if (diagnosticMessage != null) 2500 { 2501 wrap(lines, 2502 INFO_RESULT_UTILS_JOIN_DIAGNOSTIC_MESSAGE.get(diagnosticMessage), 2503 indentPrefix, maxWidth); 2504 } 2505 2506 final String matchedDN = decoded.getMatchedDN(); 2507 if (matchedDN != null) 2508 { 2509 wrap(lines, INFO_RESULT_UTILS_JOIN_MATCHED_DN.get(matchedDN), 2510 indentPrefix, maxWidth); 2511 } 2512 2513 final List<String> referralURLs = decoded.getReferralURLs(); 2514 if (referralURLs != null) 2515 { 2516 for (final String referralURL : referralURLs) 2517 { 2518 wrap(lines, INFO_RESULT_UTILS_JOIN_REFERRAL_URL.get(referralURL), 2519 indentPrefix, maxWidth); 2520 } 2521 } 2522 2523 final List<JoinedEntry> joinedEntries = decoded.getJoinResults(); 2524 if (joinedEntries != null) 2525 { 2526 for (final JoinedEntry e : joinedEntries) 2527 { 2528 addJoinedEntry(lines, e, indentPrefix, maxWidth); 2529 } 2530 } 2531 } 2532 2533 2534 2535 /** 2536 * Adds a multi-line string representation of the provided joined entry to the 2537 * given list. 2538 * 2539 * @param lines The list to which the lines should be added. 2540 * @param joinedEntry The joined entry to be formatted. 2541 * @param prefix The prefix to use for each line. 2542 * @param maxWidth The maximum length of each line in characters, 2543 * including the comment prefix and indent. 2544 */ 2545 private static void addJoinedEntry( 2546 @NotNull final List<String> lines, 2547 @NotNull final JoinedEntry joinedEntry, 2548 @NotNull final String prefix, 2549 final int maxWidth) 2550 { 2551 wrap(lines, INFO_RESULT_UTILS_JOINED_WITH_ENTRY_HEADER.get(), prefix, 2552 maxWidth); 2553 addLDIF(lines, joinedEntry, true, prefix + " ", maxWidth); 2554 2555 final List<JoinedEntry> nestedJoinResults = 2556 joinedEntry.getNestedJoinResults(); 2557 if (nestedJoinResults != null) 2558 { 2559 for (final JoinedEntry e : nestedJoinResults) 2560 { 2561 addJoinedEntry(lines, e, prefix + " ", maxWidth); 2562 } 2563 } 2564 } 2565 2566 2567 2568 /** 2569 * Adds a multi-line string representation of the provided control, which is 2570 * expected to be a matching entry count response control, to the given list. 2571 * 2572 * @param lines The list to which the lines should be added. 2573 * @param c The control to be formatted. 2574 * @param prefix The prefix to use for each line. 2575 * @param maxWidth The maximum length of each line in characters, including 2576 * the comment prefix and indent. 2577 */ 2578 private static void addMatchingEntryCountResponseControl( 2579 @NotNull final List<String> lines, 2580 @NotNull final Control c, 2581 @NotNull final String prefix, 2582 final int maxWidth) 2583 { 2584 final MatchingEntryCountResponseControl decoded; 2585 try 2586 { 2587 decoded = new MatchingEntryCountResponseControl(c.getOID(), 2588 c.isCritical(), c.getValue()); 2589 } 2590 catch (final Exception e) 2591 { 2592 Debug.debugException(e); 2593 addGenericResponseControl(lines, c, prefix, maxWidth); 2594 return; 2595 } 2596 2597 wrap(lines, INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_HEADER.get(), prefix, 2598 maxWidth); 2599 2600 final String indentPrefix = prefix + " "; 2601 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2602 indentPrefix, maxWidth); 2603 2604 switch (decoded.getCountType()) 2605 { 2606 case EXAMINED_COUNT: 2607 wrap(lines, INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_TYPE_EXAMINED.get(), 2608 indentPrefix, maxWidth); 2609 wrap(lines, 2610 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_VALUE.get( 2611 decoded.getCountValue()), 2612 indentPrefix, maxWidth); 2613 break; 2614 2615 case UNEXAMINED_COUNT: 2616 wrap(lines, 2617 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_TYPE_UNEXAMINED.get(), 2618 indentPrefix, maxWidth); 2619 wrap(lines, 2620 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_VALUE.get( 2621 decoded.getCountValue()), 2622 indentPrefix, maxWidth); 2623 break; 2624 2625 case UPPER_BOUND: 2626 wrap(lines, 2627 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_TYPE_UPPER_BOUND.get(), 2628 indentPrefix, maxWidth); 2629 wrap(lines, 2630 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_VALUE.get( 2631 decoded.getCountValue()), 2632 indentPrefix, maxWidth); 2633 break; 2634 2635 case UNKNOWN: 2636 default: 2637 wrap(lines, INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_TYPE_UNKNOWN.get(), 2638 indentPrefix, maxWidth); 2639 break; 2640 } 2641 2642 wrap(lines, 2643 INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_INDEXED.get( 2644 decoded.searchIndexed()), 2645 indentPrefix, maxWidth); 2646 2647 final List<String> debugInfo = decoded.getDebugInfo(); 2648 if ((debugInfo != null) && (! debugInfo.isEmpty())) 2649 { 2650 wrap(lines, INFO_RESULT_UTILS_MATCHING_ENTRY_COUNT_DEBUG_HEADER.get(), 2651 indentPrefix, maxWidth); 2652 for (final String s : debugInfo) 2653 { 2654 wrap(lines, s, indentPrefix + " ", maxWidth); 2655 } 2656 } 2657 } 2658 2659 2660 2661 /** 2662 * Adds a multi-line string representation of the provided control, which is 2663 * expected to be password policy response control, to the given list. 2664 * 2665 * @param lines The list to which the lines should be added. 2666 * @param c The control to be formatted. 2667 * @param prefix The prefix to use for each line. 2668 * @param maxWidth The maximum length of each line in characters, including 2669 * the comment prefix and indent. 2670 */ 2671 private static void addPasswordPolicyResponseControl( 2672 @NotNull final List<String> lines, 2673 @NotNull final Control c, 2674 @NotNull final String prefix, 2675 final int maxWidth) 2676 { 2677 final PasswordPolicyResponseControl decoded; 2678 try 2679 { 2680 decoded = new PasswordPolicyResponseControl(c.getOID(), c.isCritical(), 2681 c.getValue()); 2682 } 2683 catch (final Exception e) 2684 { 2685 Debug.debugException(e); 2686 addGenericResponseControl(lines, c, prefix, maxWidth); 2687 return; 2688 } 2689 2690 wrap(lines, INFO_RESULT_UTILS_PW_POLICY_HEADER.get(), prefix, maxWidth); 2691 2692 final String indentPrefix = prefix + " "; 2693 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2694 indentPrefix, maxWidth); 2695 2696 final PasswordPolicyErrorType errorType = decoded.getErrorType(); 2697 if (errorType == null) 2698 { 2699 wrap(lines, INFO_RESULT_UTILS_PW_POLICY_ERROR_TYPE_NONE.get(), 2700 indentPrefix, maxWidth); 2701 } 2702 else 2703 { 2704 wrap(lines, 2705 INFO_RESULT_UTILS_PW_POLICY_ERROR_TYPE.get(errorType.getName()), 2706 indentPrefix, maxWidth); 2707 } 2708 2709 final PasswordPolicyWarningType warningType = decoded.getWarningType(); 2710 if (warningType == null) 2711 { 2712 wrap(lines, INFO_RESULT_UTILS_PW_POLICY_WARNING_TYPE_NONE.get(), 2713 indentPrefix, maxWidth); 2714 } 2715 else 2716 { 2717 wrap(lines, 2718 INFO_RESULT_UTILS_PW_POLICY_WARNING_TYPE.get(warningType.getName()), 2719 indentPrefix, maxWidth); 2720 wrap(lines, 2721 INFO_RESULT_UTILS_PW_POLICY_WARNING_VALUE.get( 2722 decoded.getWarningValue()), 2723 indentPrefix, maxWidth); 2724 } 2725 } 2726 2727 2728 2729 /** 2730 * Adds a multi-line string representation of the provided control, which is 2731 * expected to be a password validation details response control, to the given 2732 * list. 2733 * 2734 * @param lines The list to which the lines should be added. 2735 * @param c The control to be formatted. 2736 * @param prefix The prefix to use for each line. 2737 * @param maxWidth The maximum length of each line in characters, including 2738 * the comment prefix and indent. 2739 */ 2740 private static void addPasswordValidationDetailsResponseControl( 2741 @NotNull final List<String> lines, 2742 @NotNull final Control c, 2743 @NotNull final String prefix, 2744 final int maxWidth) 2745 { 2746 final PasswordValidationDetailsResponseControl decoded; 2747 try 2748 { 2749 decoded = new PasswordValidationDetailsResponseControl(c.getOID(), 2750 c.isCritical(), c.getValue()); 2751 } 2752 catch (final Exception e) 2753 { 2754 Debug.debugException(e); 2755 addGenericResponseControl(lines, c, prefix, maxWidth); 2756 return; 2757 } 2758 2759 wrap(lines, INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_HEADER.get(), prefix, 2760 maxWidth); 2761 2762 final String indentPrefix = prefix + " "; 2763 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2764 indentPrefix, maxWidth); 2765 2766 switch (decoded.getResponseType()) 2767 { 2768 case VALIDATION_DETAILS: 2769 wrap(lines, 2770 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_RESULT_TYPE_RESULT.get(), 2771 indentPrefix, maxWidth); 2772 2773 final List<PasswordQualityRequirementValidationResult> results = 2774 decoded.getValidationResults(); 2775 if (results != null) 2776 { 2777 for (final PasswordQualityRequirementValidationResult r : results) 2778 { 2779 wrap(lines, 2780 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_HEADER.get(), 2781 indentPrefix + " ", maxWidth); 2782 2783 final String tripleIndentPrefix = indentPrefix + " "; 2784 final PasswordQualityRequirement pqr = r.getPasswordRequirement(); 2785 2786 final String description = pqr.getDescription(); 2787 if (description != null) 2788 { 2789 wrap(lines, 2790 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_DESC.get( 2791 description), 2792 tripleIndentPrefix, maxWidth); 2793 } 2794 2795 final String clientSideType = pqr.getClientSideValidationType(); 2796 if (clientSideType != null) 2797 { 2798 wrap(lines, 2799 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_TYPE.get( 2800 clientSideType), 2801 tripleIndentPrefix, maxWidth); 2802 } 2803 2804 final Map<String,String> properties = 2805 pqr.getClientSideValidationProperties(); 2806 if (properties != null) 2807 { 2808 for (final Map.Entry<String,String> e : properties.entrySet()) 2809 { 2810 wrap(lines, 2811 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_PROP.get( 2812 e.getKey(), e.getValue()), 2813 tripleIndentPrefix, maxWidth); 2814 } 2815 } 2816 2817 wrap(lines, 2818 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_SATISFIED.get( 2819 r.requirementSatisfied()), 2820 tripleIndentPrefix, maxWidth); 2821 2822 final String additionalInfo = r.getAdditionalInfo(); 2823 if (additionalInfo != null) 2824 { 2825 wrap(lines, 2826 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_PQR_INFO.get( 2827 additionalInfo), 2828 tripleIndentPrefix, maxWidth); 2829 } 2830 } 2831 } 2832 break; 2833 case NO_PASSWORD_PROVIDED: 2834 wrap(lines, 2835 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_RESULT_TYPE_NO_PW.get(), 2836 indentPrefix, maxWidth); 2837 break; 2838 case MULTIPLE_PASSWORDS_PROVIDED: 2839 wrap(lines, 2840 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_RESULT_TYPE_MULTIPLE_PW. 2841 get(), 2842 indentPrefix, maxWidth); 2843 break; 2844 case NO_VALIDATION_ATTEMPTED: 2845 wrap(lines, 2846 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_RESULT_TYPE_NO_VALIDATION. 2847 get(), 2848 indentPrefix, maxWidth); 2849 break; 2850 default: 2851 wrap(lines, 2852 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_RESULT_TYPE_DEFAULT.get( 2853 decoded.getResponseType().name()), 2854 indentPrefix, maxWidth); 2855 break; 2856 } 2857 2858 wrap(lines, 2859 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_MISSING_CURRENT.get( 2860 decoded.missingCurrentPassword()), 2861 indentPrefix, maxWidth); 2862 wrap(lines, 2863 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_MUST_CHANGE.get( 2864 decoded.mustChangePassword()), 2865 indentPrefix, maxWidth); 2866 2867 final Integer secondsUntilExpiration = decoded.getSecondsUntilExpiration(); 2868 if (secondsUntilExpiration != null) 2869 { 2870 wrap(lines, 2871 INFO_RESULT_UTILS_PW_VALIDATION_DETAILS_SECONDS_TO_EXP.get( 2872 secondsUntilExpiration), 2873 indentPrefix, maxWidth); 2874 } 2875 } 2876 2877 2878 2879 /** 2880 * Adds a multi-line string representation of the provided control, which is 2881 * expected to be a soft delete response control, to the given list. 2882 * 2883 * @param lines The list to which the lines should be added. 2884 * @param c The control to be formatted. 2885 * @param prefix The prefix to use for each line. 2886 * @param maxWidth The maximum length of each line in characters, including 2887 * the comment prefix and indent. 2888 */ 2889 private static void addSoftDeleteResponseControl( 2890 @NotNull final List<String> lines, 2891 @NotNull final Control c, 2892 @NotNull final String prefix, 2893 final int maxWidth) 2894 { 2895 final SoftDeleteResponseControl decoded; 2896 try 2897 { 2898 decoded = new SoftDeleteResponseControl(c.getOID(), c.isCritical(), 2899 c.getValue()); 2900 } 2901 catch (final Exception e) 2902 { 2903 Debug.debugException(e); 2904 addGenericResponseControl(lines, c, prefix, maxWidth); 2905 return; 2906 } 2907 2908 wrap(lines, INFO_RESULT_UTILS_SOFT_DELETE_HEADER.get(), prefix, maxWidth); 2909 2910 final String indentPrefix = prefix + " "; 2911 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2912 indentPrefix, maxWidth); 2913 2914 final String dn = decoded.getSoftDeletedEntryDN(); 2915 if (dn != null) 2916 { 2917 wrap(lines, INFO_RESULT_UTILS_SOFT_DELETED_DN.get(dn), indentPrefix, 2918 maxWidth); 2919 } 2920 } 2921 2922 2923 2924 /** 2925 * Adds a multi-line string representation of the provided control, which is 2926 * expected to be a transaction settings response control, to the given list. 2927 * 2928 * @param lines The list to which the lines should be added. 2929 * @param c The control to be formatted. 2930 * @param prefix The prefix to use for each line. 2931 * @param maxWidth The maximum length of each line in characters, including 2932 * the comment prefix and indent. 2933 */ 2934 private static void addTransactionSettingsResponseControl( 2935 @NotNull final List<String> lines, 2936 @NotNull final Control c, 2937 @NotNull final String prefix, 2938 final int maxWidth) 2939 { 2940 final TransactionSettingsResponseControl decoded; 2941 try 2942 { 2943 decoded = new TransactionSettingsResponseControl(c.getOID(), 2944 c.isCritical(), c.getValue()); 2945 } 2946 catch (final Exception e) 2947 { 2948 Debug.debugException(e); 2949 addGenericResponseControl(lines, c, prefix, maxWidth); 2950 return; 2951 } 2952 2953 wrap(lines, INFO_RESULT_UTILS_TXN_SETTINGS_HEADER.get(), prefix, 2954 maxWidth); 2955 2956 final String indentPrefix = prefix + " "; 2957 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 2958 indentPrefix, maxWidth); 2959 wrap(lines, 2960 INFO_RESULT_UTILS_TXN_SETTINGS_NUM_CONFLICTS.get( 2961 decoded.getNumLockConflicts()), 2962 indentPrefix, maxWidth); 2963 wrap(lines, 2964 INFO_RESULT_UTILS_TXN_SETTINGS_BACKEND_LOCK_ACQUIRED.get( 2965 decoded.backendLockAcquired()), 2966 indentPrefix, maxWidth); 2967 } 2968 2969 2970 2971 /** 2972 * Adds a multi-line string representation of the provided control, which is 2973 * expected to be a uniqueness response control, to the given list. 2974 * 2975 * @param lines The list to which the lines should be added. 2976 * @param c The control to be formatted. 2977 * @param prefix The prefix to use for each line. 2978 * @param maxWidth The maximum length of each line in characters, including 2979 * the comment prefix and indent. 2980 */ 2981 private static void addUniquenessResponseControl( 2982 @NotNull final List<String> lines, 2983 @NotNull final Control c, 2984 @NotNull final String prefix, 2985 final int maxWidth) 2986 { 2987 final UniquenessResponseControl decoded; 2988 try 2989 { 2990 decoded = new UniquenessResponseControl(c.getOID(), c.isCritical(), 2991 c.getValue()); 2992 } 2993 catch (final Exception e) 2994 { 2995 Debug.debugException(e); 2996 addGenericResponseControl(lines, c, prefix, maxWidth); 2997 return; 2998 } 2999 3000 wrap(lines, INFO_RESULT_UTILS_UNIQUENESS_HEADER.get(), prefix, maxWidth); 3001 3002 final String indentPrefix = prefix + " "; 3003 wrap(lines, INFO_RESULT_UTILS_RESPONSE_CONTROL_OID.get(c.getOID()), 3004 indentPrefix, maxWidth); 3005 wrap(lines, INFO_RESULT_UTILS_UNIQUENESS_ID.get(decoded.getUniquenessID()), 3006 indentPrefix, maxWidth); 3007 3008 final String preCommitStatus; 3009 if (decoded.getPreCommitValidationPassed() == null) 3010 { 3011 preCommitStatus = 3012 INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_NOT_ATTEMPTED.get(); 3013 } 3014 else if (decoded.getPreCommitValidationPassed() == Boolean.TRUE) 3015 { 3016 preCommitStatus = INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_PASSED.get(); 3017 } 3018 else 3019 { 3020 preCommitStatus = INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_FAILED.get(); 3021 } 3022 wrap(lines, 3023 INFO_RESULT_UTILS_UNIQUENESS_PRE_COMMIT_STATUS.get(preCommitStatus), 3024 indentPrefix, maxWidth); 3025 3026 final String postCommitStatus; 3027 if (decoded.getPostCommitValidationPassed() == null) 3028 { 3029 postCommitStatus = 3030 INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_NOT_ATTEMPTED.get(); 3031 } 3032 else if (decoded.getPostCommitValidationPassed() == Boolean.TRUE) 3033 { 3034 postCommitStatus = INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_PASSED.get(); 3035 } 3036 else 3037 { 3038 postCommitStatus = INFO_RESULT_UTILS_UNIQUENESS_STATUS_VALUE_FAILED.get(); 3039 } 3040 wrap(lines, 3041 INFO_RESULT_UTILS_UNIQUENESS_POST_COMMIT_STATUS.get(postCommitStatus), 3042 indentPrefix, maxWidth); 3043 3044 final String message = decoded.getValidationMessage(); 3045 if (message != null) 3046 { 3047 wrap(lines, INFO_RESULT_UTILS_UNIQUENESS_MESSAGE.get(message), 3048 indentPrefix, maxWidth); 3049 } 3050 } 3051 3052 3053 3054 /** 3055 * Creates a string that may be used as a prefix for all lines with the given 3056 * settings. 3057 * 3058 * @param comment Indicates whether to prefix each line with an octothorpe 3059 * to indicate that it is a comment. 3060 * @param indent The number of spaces to indent each line. 3061 * 3062 * @return A string that may be used as a prefix for all lines with the given 3063 * settings. 3064 */ 3065 @NotNull() 3066 private static String createPrefix(final boolean comment, final int indent) 3067 { 3068 // Generate a prefix that will be used for every line. 3069 final StringBuilder buffer = new StringBuilder(indent + 2); 3070 if (comment) 3071 { 3072 buffer.append("# "); 3073 } 3074 for (int i=0; i < indent; i++) 3075 { 3076 buffer.append(' '); 3077 } 3078 return buffer.toString(); 3079 } 3080 3081 3082 3083 /** 3084 * Adds a wrapped version of the provided string to the given list. 3085 * 3086 * @param lines The list to which the wrapped lines should be added. 3087 * @param s The string to be wrapped. 3088 * @param prefix The prefix to use at the beginning of each line. 3089 * @param maxWidth The maximum length of each line in characters. 3090 */ 3091 private static void wrap(@NotNull final List<String> lines, 3092 @NotNull final String s, 3093 @NotNull final String prefix, 3094 final int maxWidth) 3095 { 3096 // If the maximum width is less than the prefix length + 20 characters, then 3097 // make it make that the new effective maximum width. 3098 final int minimumMaxWidth = prefix.length() + 20; 3099 final int effectiveMaxWidth = Math.max(minimumMaxWidth, maxWidth); 3100 3101 3102 // If the prefix plus the provided string is within the maximum width, then 3103 // there's no need to do any wrapping. 3104 if ((prefix.length() + s.length()) <= effectiveMaxWidth) 3105 { 3106 lines.add(prefix + s); 3107 return; 3108 } 3109 3110 3111 // Wrap the provided string. If it spans multiple lines, all lines except 3112 // the first will be indented an extra five spaces. 3113 final List<String> wrappedLines = StaticUtils.wrapLine(s, 3114 (maxWidth - prefix.length()), 3115 (maxWidth - prefix.length() - 5)); 3116 3117 3118 3119 // Add the wrapped lines to the given list. 3120 for (int i=0; i < wrappedLines.size(); i++) 3121 { 3122 if (i > 0) 3123 { 3124 lines.add(prefix + " " + wrappedLines.get(i)); 3125 } 3126 else 3127 { 3128 lines.add(prefix + wrappedLines.get(i)); 3129 } 3130 } 3131 } 3132 3133 3134 3135 /** 3136 * Adds the lines that comprise an LDIF representation of the provided entry 3137 * to the given list. 3138 * 3139 * @param lines The list to which the lines should be added. 3140 * @param entry The entry to be formatted. 3141 * @param includeDN Indicates whether to include the DN of the entry in the 3142 * resulting LDIF representation. 3143 * @param prefix The prefix to use at the beginning of each line. 3144 * @param maxWidth The maximum length of each line in characters. 3145 */ 3146 private static void addLDIF(@NotNull final List<String> lines, 3147 @NotNull final Entry entry, 3148 final boolean includeDN, 3149 @NotNull final String prefix, 3150 final int maxWidth) 3151 { 3152 // Never use a wrap column that is less than 20 characters. 3153 final int wrapColumn = Math.max(maxWidth - prefix.length(), 20); 3154 3155 if (includeDN) 3156 { 3157 for (final String s : entry.toLDIF(wrapColumn)) 3158 { 3159 lines.add(prefix + s); 3160 } 3161 } 3162 else 3163 { 3164 final String[] ldifLinesWithDN; 3165 if (entry.getDN().length() > 10) 3166 { 3167 final Entry dup = entry.duplicate(); 3168 dup.setDN(""); 3169 ldifLinesWithDN = dup.toLDIF(wrapColumn); 3170 } 3171 else 3172 { 3173 ldifLinesWithDN = entry.toLDIF(wrapColumn); 3174 } 3175 3176 for (int i=1; i < ldifLinesWithDN.length; i++) 3177 { 3178 lines.add(prefix + ldifLinesWithDN[i]); 3179 } 3180 } 3181 } 3182}