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