001/*
002 * Copyright 2009-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2019 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.logs;
022
023
024
025import java.util.Collections;
026import java.util.LinkedList;
027import java.util.List;
028import java.util.StringTokenizer;
029
030import com.unboundid.ldap.sdk.ResultCode;
031import com.unboundid.ldap.sdk.unboundidds.controls.AssuredReplicationLocalLevel;
032import com.unboundid.ldap.sdk.unboundidds.controls.
033            AssuredReplicationRemoteLevel;
034import com.unboundid.util.NotExtensible;
035import com.unboundid.util.NotMutable;
036import com.unboundid.util.ThreadSafety;
037import com.unboundid.util.ThreadSafetyLevel;
038
039
040
041/**
042 * This class provides a data structure that holds information about a log
043 * message that may appear in the Directory Server access log about the result
044 * of a modify DN operation processed by the Directory Server.
045 * <BR>
046 * <BLOCKQUOTE>
047 *   <B>NOTE:</B>  This class, and other classes within the
048 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
049 *   supported for use against Ping Identity, UnboundID, and
050 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
051 *   for proprietary functionality or for external specifications that are not
052 *   considered stable or mature enough to be guaranteed to work in an
053 *   interoperable way with other types of LDAP servers.
054 * </BLOCKQUOTE>
055 */
056@NotExtensible()
057@NotMutable()
058@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
059public class ModifyDNResultAccessLogMessage
060       extends ModifyDNRequestAccessLogMessage
061       implements OperationResultAccessLogMessage
062{
063  /**
064   * The serial version UID for this serializable class.
065   */
066  private static final long serialVersionUID = 8460618419048326026L;
067
068
069
070  // The assured replication level to use for local servers.
071  private final AssuredReplicationLocalLevel assuredReplicationLocalLevel;
072
073  // The assured replication level to use for remote servers.
074  private final AssuredReplicationRemoteLevel assuredReplicationRemoteLevel;
075
076  // Indicates whether the response was known to be delayed by replication
077  // assurance processing.
078  private final Boolean responseDelayedByAssurance;
079
080  // Indicates whether the any uncached data was accessed in the course of
081  // processing this operation.
082  private final Boolean uncachedDataAccessed;
083
084  // The processing time for the operation.
085  private final Double processingTime;
086
087  // The queue time for the operation.
088  private final Double queueTime;
089
090  // The list of indexes for which keys near the index entry limit were accessed
091  // while processing the operation.
092  private final List<String> indexesWithKeysAccessedNearEntryLimit;
093
094  // The list of indexes for which keys over the index entry limit were accessed
095  // while processing the operation.
096  private final List<String> indexesWithKeysAccessedOverEntryLimit;
097
098  // The list of privileges required for processing the operation that the
099  // requester did not have.
100  private final List<String> missingPrivileges;
101
102  // The list of privileges used during the course of processing the operation
103  // before an alternate authorization identity was assigned.
104  private final List<String> preAuthZUsedPrivileges;
105
106  // The list of referral URLs for the operation.
107  private final List<String> referralURLs;
108
109  // The list of response control OIDs for the operation.
110  private final List<String> responseControlOIDs;
111
112  // The list of servers accessed while processing the operation.
113  private final List<String> serversAccessed;
114
115  // The list of privileges used during the course of processing the operation.
116  private final List<String> usedPrivileges;
117
118  // The assured replication timeout, in milliseconds.
119  private final Long assuredReplicationTimeoutMillis;
120
121  // The number of intermediate response messages returned to the client.
122  private final Long intermediateResponsesReturned;
123
124  // The result code for the operation.
125  private final ResultCode resultCode;
126
127  // Additional information about the operation result.
128  private final String additionalInformation;
129
130  // The alternate authorization DN for the operation.
131  private final String authzDN;
132
133  // The diagnostic message for the operation.
134  private final String diagnosticMessage;
135
136  // The intermediate client result for the operation.
137  private final String intermediateClientResult;
138
139  // The matched DN for the operation.
140  private final String matchedDN;
141
142  // The replication change ID for the operation.
143  private final String replicationChangeID;
144
145  // The port of the backend server to which the request has been forwarded.
146  private final Integer targetPort;
147
148  // The address of the backend server to which the request has been forwarded.
149  private final String targetHost;
150
151  // The protocol used to forward the request to the backend server.
152  private final String targetProtocol;
153
154
155
156  /**
157   * Creates a new modify DN result access log message from the provided message
158   * string.
159   *
160   * @param  s  The string to be parsed as a modify DN result access log
161   *            message.
162   *
163   * @throws  LogException  If the provided string cannot be parsed as a valid
164   *                        log message.
165   */
166  public ModifyDNResultAccessLogMessage(final String s)
167         throws LogException
168  {
169    this(new LogMessage(s));
170  }
171
172
173
174  /**
175   * Creates a new modify DN result access log message from the provided log
176   * message.
177   *
178   * @param  m  The log message to be parsed as a modify DN result access log
179   *            message.
180   */
181  public ModifyDNResultAccessLogMessage(final LogMessage m)
182  {
183    super(m);
184
185    diagnosticMessage        = getNamedValue("message");
186    additionalInformation    = getNamedValue("additionalInfo");
187    matchedDN                = getNamedValue("matchedDN");
188    processingTime           = getNamedValueAsDouble("etime");
189    queueTime                = getNamedValueAsDouble("qtime");
190    intermediateClientResult = getNamedValue("from");
191    authzDN                  = getNamedValue("authzDN");
192    replicationChangeID      = getNamedValue("replicationChangeID");
193    targetHost               = getNamedValue("targetHost");
194    targetPort               = getNamedValueAsInteger("targetPort");
195    targetProtocol           = getNamedValue("targetProtocol");
196
197    intermediateResponsesReturned =
198         getNamedValueAsLong("intermediateResponsesReturned");
199
200    final Integer rcInteger = getNamedValueAsInteger("resultCode");
201    if (rcInteger == null)
202    {
203      resultCode = null;
204    }
205    else
206    {
207      resultCode = ResultCode.valueOf(rcInteger);
208    }
209
210    final String refStr = getNamedValue("referralURLs");
211    if ((refStr == null) || refStr.isEmpty())
212    {
213      referralURLs = Collections.emptyList();
214    }
215    else
216    {
217      final LinkedList<String> refs = new LinkedList<>();
218      int startPos = 0;
219      while (true)
220      {
221        final int commaPos = refStr.indexOf(",ldap", startPos);
222        if (commaPos < 0)
223        {
224          refs.add(refStr.substring(startPos));
225          break;
226        }
227        else
228        {
229          refs.add(refStr.substring(startPos, commaPos));
230          startPos = commaPos+1;
231        }
232      }
233      referralURLs = Collections.unmodifiableList(refs);
234    }
235
236    final String controlStr = getNamedValue("responseControls");
237    if (controlStr == null)
238    {
239      responseControlOIDs = Collections.emptyList();
240    }
241    else
242    {
243      final LinkedList<String> controlList = new LinkedList<>();
244      final StringTokenizer t = new StringTokenizer(controlStr, ",");
245      while (t.hasMoreTokens())
246      {
247        controlList.add(t.nextToken());
248      }
249      responseControlOIDs = Collections.unmodifiableList(controlList);
250    }
251
252    final String serversAccessedStr = getNamedValue("serversAccessed");
253    if ((serversAccessedStr == null) || serversAccessedStr.isEmpty())
254    {
255      serversAccessed = Collections.emptyList();
256    }
257    else
258    {
259      final LinkedList<String> servers = new LinkedList<>();
260      final StringTokenizer tokenizer =
261           new StringTokenizer(serversAccessedStr, ",");
262      while (tokenizer.hasMoreTokens())
263      {
264        servers.add(tokenizer.nextToken());
265      }
266      serversAccessed = Collections.unmodifiableList(servers);
267    }
268
269    uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed");
270
271
272    final String localLevelStr = getNamedValue("localAssuranceLevel");
273    if (localLevelStr == null)
274    {
275      assuredReplicationLocalLevel = null;
276    }
277    else
278    {
279      assuredReplicationLocalLevel =
280           AssuredReplicationLocalLevel.valueOf(localLevelStr);
281    }
282
283    final String remoteLevelStr = getNamedValue("remoteAssuranceLevel");
284    if (remoteLevelStr == null)
285    {
286      assuredReplicationRemoteLevel = null;
287    }
288    else
289    {
290      assuredReplicationRemoteLevel =
291           AssuredReplicationRemoteLevel.valueOf(remoteLevelStr);
292    }
293
294    assuredReplicationTimeoutMillis =
295         getNamedValueAsLong("assuranceTimeoutMillis");
296    responseDelayedByAssurance =
297         getNamedValueAsBoolean("responseDelayedByAssurance");
298
299    final String usedPrivilegesStr = getNamedValue("usedPrivileges");
300    if ((usedPrivilegesStr == null) || usedPrivilegesStr.isEmpty())
301    {
302      usedPrivileges = Collections.emptyList();
303    }
304    else
305    {
306      final LinkedList<String> privileges = new LinkedList<>();
307      final StringTokenizer tokenizer =
308           new StringTokenizer(usedPrivilegesStr, ",");
309      while (tokenizer.hasMoreTokens())
310      {
311        privileges.add(tokenizer.nextToken());
312      }
313      usedPrivileges = Collections.unmodifiableList(privileges);
314    }
315
316    final String preAuthZUsedPrivilegesStr =
317         getNamedValue("preAuthZUsedPrivileges");
318    if ((preAuthZUsedPrivilegesStr == null) ||
319        preAuthZUsedPrivilegesStr.isEmpty())
320    {
321      preAuthZUsedPrivileges = Collections.emptyList();
322    }
323    else
324    {
325      final LinkedList<String> privileges = new LinkedList<>();
326      final StringTokenizer tokenizer =
327           new StringTokenizer(preAuthZUsedPrivilegesStr, ",");
328      while (tokenizer.hasMoreTokens())
329      {
330        privileges.add(tokenizer.nextToken());
331      }
332      preAuthZUsedPrivileges = Collections.unmodifiableList(privileges);
333    }
334
335    final String missingPrivilegesStr = getNamedValue("missingPrivileges");
336    if ((missingPrivilegesStr == null) || missingPrivilegesStr.isEmpty())
337    {
338      missingPrivileges = Collections.emptyList();
339    }
340    else
341    {
342      final LinkedList<String> privileges = new LinkedList<>();
343      final StringTokenizer tokenizer =
344           new StringTokenizer(missingPrivilegesStr, ",");
345      while (tokenizer.hasMoreTokens())
346      {
347        privileges.add(tokenizer.nextToken());
348      }
349      missingPrivileges = Collections.unmodifiableList(privileges);
350    }
351
352    final String indexesNearLimitStr =
353         getNamedValue("indexesWithKeysAccessedNearEntryLimit");
354    if ((indexesNearLimitStr == null) || indexesNearLimitStr.isEmpty())
355    {
356      indexesWithKeysAccessedNearEntryLimit = Collections.emptyList();
357    }
358    else
359    {
360      final LinkedList<String> indexes = new LinkedList<>();
361      final StringTokenizer tokenizer =
362           new StringTokenizer(indexesNearLimitStr, ",");
363      while (tokenizer.hasMoreTokens())
364      {
365        indexes.add(tokenizer.nextToken());
366      }
367      indexesWithKeysAccessedNearEntryLimit =
368           Collections.unmodifiableList(indexes);
369    }
370
371    final String indexesOverLimitStr =
372         getNamedValue("indexesWithKeysAccessedExceedingEntryLimit");
373    if ((indexesOverLimitStr == null) || indexesOverLimitStr.isEmpty())
374    {
375      indexesWithKeysAccessedOverEntryLimit = Collections.emptyList();
376    }
377    else
378    {
379      final LinkedList<String> indexes = new LinkedList<>();
380      final StringTokenizer tokenizer =
381           new StringTokenizer(indexesOverLimitStr, ",");
382      while (tokenizer.hasMoreTokens())
383      {
384        indexes.add(tokenizer.nextToken());
385      }
386      indexesWithKeysAccessedOverEntryLimit =
387           Collections.unmodifiableList(indexes);
388    }
389  }
390
391
392
393  /**
394   * Retrieves the result code for the operation.
395   *
396   * @return  The result code for the operation, or {@code null} if it is not
397   *          included in the log message.
398   */
399  @Override()
400  public ResultCode getResultCode()
401  {
402    return resultCode;
403  }
404
405
406
407  /**
408   * Retrieves the diagnostic message for the operation.
409   *
410   * @return  The diagnostic message for the operation, or {@code null} if it is
411   *          not included in the log message.
412   */
413  @Override()
414  public String getDiagnosticMessage()
415  {
416    return diagnosticMessage;
417  }
418
419
420
421  /**
422   * Retrieves a message with additional information about the result of the
423   * operation.
424   *
425   * @return  A message with additional information about the result of the
426   *          operation, or {@code null} if it is not included in the log
427   *          message.
428   */
429  @Override()
430  public String getAdditionalInformation()
431  {
432    return additionalInformation;
433  }
434
435
436
437  /**
438   * Retrieves the matched DN for the operation.
439   *
440   * @return  The matched DN for the operation, or {@code null} if it is not
441   *          included in the log message.
442   */
443  @Override()
444  public String getMatchedDN()
445  {
446    return matchedDN;
447  }
448
449
450
451  /**
452   * Retrieves the list of referral URLs for the operation.
453   *
454   * @return  The list of referral URLs for the operation, or an empty list if
455   *          it is not included in the log message.
456   */
457  @Override()
458  public List<String> getReferralURLs()
459  {
460    return referralURLs;
461  }
462
463
464
465  /**
466   * Retrieves the number of intermediate response messages returned in the
467   * course of processing the operation.
468   *
469   * @return  The number of intermediate response messages returned to the
470   *          client in the course of processing the operation, or {@code null}
471   *          if it is not included in the log message.
472   */
473  @Override()
474  public Long getIntermediateResponsesReturned()
475  {
476    return intermediateResponsesReturned;
477  }
478
479
480
481  /**
482   * Retrieves the length of time in milliseconds required to process the
483   * operation.
484   *
485   * @return  The length of time in milliseconds required to process the
486   *          operation, or {@code null} if it is not included in the log
487   *          message.
488   */
489  @Override()
490  public Double getProcessingTimeMillis()
491  {
492    return processingTime;
493  }
494
495
496
497  /**
498   * Retrieves the length of time in milliseconds the operation was required to
499   * wait on the work queue.
500   *
501   * @return  The length of time in milliseconds the operation was required to
502   *          wait on the work queue, or {@code null} if it is not included in
503   *          the log message.
504   */
505  @Override()
506  public Double getQueueTimeMillis()
507  {
508    return queueTime;
509  }
510
511
512
513  /**
514   * Retrieves the OIDs of any response controls contained in the log message.
515   *
516   * @return  The OIDs of any response controls contained in the log message, or
517   *          an empty list if it is not included in the log message.
518   */
519  @Override()
520  public List<String> getResponseControlOIDs()
521  {
522    return responseControlOIDs;
523  }
524
525
526
527  /**
528   * Retrieves a list of the additional servers that were accessed in the course
529   * of processing the operation.  For example, if the access log message is
530   * from a Directory Proxy Server instance, then this may contain a list of the
531   * backend servers used to process the operation.
532   *
533   * @return  A list of the additional servers that were accessed in the course
534   *          of processing the operation, or an empty list if it is not
535   *          included in the log message.
536   */
537  @Override()
538  public List<String> getServersAccessed()
539  {
540    return serversAccessed;
541  }
542
543
544
545  /**
546   * Indicates whether the server accessed any uncached data in the course of
547   * processing the operation.
548   *
549   * @return  {@code true} if the server was known to access uncached data in
550   *          the course of processing the operation, {@code false} if the
551   *          server was known not to access uncached data, or {@code null} if
552   *          it is not included in the log message (and the server likely did
553   *          not access uncached data).
554   */
555  public Boolean getUncachedDataAccessed()
556  {
557    return uncachedDataAccessed;
558  }
559
560
561
562  /**
563   * Retrieves the content of the intermediate client result for the
564   * operation.
565   *
566   * @return  The content of the intermediate client result for the operation,
567   *          or {@code null} if it is not included in the log message.
568   */
569  @Override()
570  public String getIntermediateClientResult()
571  {
572    return intermediateClientResult;
573  }
574
575
576
577  /**
578   * Retrieves the alternate authorization DN for the operation.
579   *
580   * @return  The alternate authorization DN for the operation, or {@code null}
581   *          if it is not included in the log message.
582   */
583  public String getAlternateAuthorizationDN()
584  {
585    return authzDN;
586  }
587
588
589
590  /**
591   * Retrieves the replication change ID for the operation, if available.
592   *
593   * @return  The replication change ID for the operation, or {@code null} if it
594   *          is not included in the log message.
595   */
596  public String getReplicationChangeID()
597  {
598    return replicationChangeID;
599  }
600
601
602
603  /**
604   * Retrieves the address of the backend server to which the request has been
605   * forwarded.
606   *
607   * @return  The address of the backend server to which the request has been
608   *          forwarded, or {@code null} if it is not included in the log
609   *          message.
610   */
611  public String getTargetHost()
612  {
613    return targetHost;
614  }
615
616
617
618  /**
619   * Retrieves the port of the backend server to which the request has been
620   * forwarded.
621   *
622   * @return  The port of the backend server to which the request has been
623   *          forwarded, or {@code null} if it is not included in the log
624   *          message.
625   */
626  public Integer getTargetPort()
627  {
628    return targetPort;
629  }
630
631
632
633  /**
634   * Retrieves the protocol used to forward the request to the backend server.
635   *
636   * @return  The protocol used to forward the request to the backend server, or
637   *          {@code null} if it is not included in the log message.
638   */
639  public String getTargetProtocol()
640  {
641    return targetProtocol;
642  }
643
644
645
646  /**
647   * Retrieves the local level that will be used for assured replication
648   * processing, if available.
649   *
650   * @return  The local level that will be used for assured replication
651   *          processing, or {@code null} if this is not included in the log
652   *          message (e.g., because assured replication will not be performed
653   *          for the operation).
654   */
655  public AssuredReplicationLocalLevel getAssuredReplicationLocalLevel()
656  {
657    return assuredReplicationLocalLevel;
658  }
659
660
661
662  /**
663   * Retrieves the remote level that will be used for assured replication
664   * processing, if available.
665   *
666   * @return  The remote level that will be used for assured replication
667   *          processing, or {@code null} if this is not included in the log
668   *          message (e.g., because assured replication will not be performed
669   *          for the operation).
670   */
671  public AssuredReplicationRemoteLevel getAssuredReplicationRemoteLevel()
672  {
673    return assuredReplicationRemoteLevel;
674  }
675
676
677
678  /**
679   * Retrieves the maximum length of time in milliseconds that the server will
680   * delay the response to the client while waiting for the replication
681   * assurance requirement to be satisfied.
682   *
683   * @return  The maximum length of time in milliseconds that the server will
684   *          delay the response to the client while waiting for the replication
685   *          assurance requirement to be satisfied, or {@code null} if this is
686   *          not included in the log message (e.g., because assured replication
687   *          will not be performed for the operation).
688   */
689  public Long getAssuredReplicationTimeoutMillis()
690  {
691    return assuredReplicationTimeoutMillis;
692  }
693
694
695
696  /**
697   * Indicates whether the operation response to the client will be delayed
698   * until replication assurance has been satisfied or the timeout has occurred.
699   *
700   * @return  {@code true} if the operation response to the client will be
701   *          delayed until replication assurance has been satisfied,
702   *          {@code false} if the response will not be delayed by assurance
703   *          processing, or {@code null} if this was not included in the
704   *          log message (e.g., because assured replication will not be
705   *          performed for the operation)
706   */
707  public Boolean getResponseDelayedByAssurance()
708  {
709    return responseDelayedByAssurance;
710  }
711
712
713
714  /**
715   * Retrieves the names of any privileges used during the course of processing
716   * the operation.
717   *
718   * @return  The names of any privileges used during the course of processing
719   *          the operation, or an empty list if no privileges were used or this
720   *          is not included in the log message.
721   */
722  public List<String> getUsedPrivileges()
723  {
724    return usedPrivileges;
725  }
726
727
728
729  /**
730   * Retrieves the names of any privileges used during the course of processing
731   * the operation before an alternate authorization identity was assigned.
732   *
733   * @return  The names of any privileges used during the course of processing
734   *          the operation before an alternate authorization identity was
735   *          assigned, or an empty list if no privileges were used or this is
736   *          not included in the log message.
737   */
738  public List<String> getPreAuthorizationUsedPrivileges()
739  {
740    return preAuthZUsedPrivileges;
741  }
742
743
744
745  /**
746   * Retrieves the names of any privileges that would have been required for
747   * processing the operation but that the requester did not have.
748   *
749   * @return  The names of any privileges that would have been required for
750   *          processing the operation but that the requester did not have, or
751   *          an empty list if there were no missing privileges or this is not
752   *          included in the log message.
753   */
754  public List<String> getMissingPrivileges()
755  {
756    return missingPrivileges;
757  }
758
759
760
761  /**
762   * Retrieves the names of any indexes for which one or more keys near
763   * (typically, within 80% of) the index entry limit were accessed while
764   * processing the operation.
765   *
766   * @return  The names of any indexes for which one or more keys near the index
767   *          entry limit were accessed while processing the operation, or an
768   *          empty list if no such index keys were accessed, or if this is not
769   *          included in the log message.
770   */
771  public List<String> getIndexesWithKeysAccessedNearEntryLimit()
772  {
773    return indexesWithKeysAccessedNearEntryLimit;
774  }
775
776
777
778  /**
779   * Retrieves the names of any indexes for which one or more keys over the
780   * index entry limit were accessed while processing the operation.
781   *
782   * @return  The names of any indexes for which one or more keys over the index
783   *          entry limit were accessed while processing the operation, or an
784   *          empty list if no such index keys were accessed, or if this is not
785   *          included in the log message.
786   */
787  public List<String> getIndexesWithKeysAccessedOverEntryLimit()
788  {
789    return indexesWithKeysAccessedOverEntryLimit;
790  }
791
792
793
794  /**
795   * {@inheritDoc}
796   */
797  @Override()
798  public AccessLogMessageType getMessageType()
799  {
800    return AccessLogMessageType.RESULT;
801  }
802}