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