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