001/*
002 * Copyright 2009-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 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 Alcatel-Lucent 8661
050 *   server products.  These classes provide support for proprietary
051 *   functionality or for external specifications that are not considered stable
052 *   or mature enough to be guaranteed to work in an interoperable way with
053 *   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.length() == 0))
212    {
213      referralURLs = Collections.emptyList();
214    }
215    else
216    {
217      final LinkedList<String> refs = new LinkedList<String>();
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<String>();
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.length() == 0))
254    {
255      serversAccessed = Collections.emptyList();
256    }
257    else
258    {
259      final LinkedList<String> servers = new LinkedList<String>();
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.length() == 0))
301    {
302      usedPrivileges = Collections.emptyList();
303    }
304    else
305    {
306      final LinkedList<String> privileges = new LinkedList<String>();
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.length() == 0))
320    {
321      preAuthZUsedPrivileges = Collections.emptyList();
322    }
323    else
324    {
325      final LinkedList<String> privileges = new LinkedList<String>();
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.length() == 0))
337    {
338      missingPrivileges = Collections.emptyList();
339    }
340    else
341    {
342      final LinkedList<String> privileges = new LinkedList<String>();
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.length() == 0))
355    {
356      indexesWithKeysAccessedNearEntryLimit = Collections.emptyList();
357    }
358    else
359    {
360      final LinkedList<String> indexes = new LinkedList<String>();
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.length() == 0))
374    {
375      indexesWithKeysAccessedOverEntryLimit = Collections.emptyList();
376    }
377    else
378    {
379      final LinkedList<String> indexes = new LinkedList<String>();
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  public ResultCode getResultCode()
400  {
401    return resultCode;
402  }
403
404
405
406  /**
407   * Retrieves the diagnostic message for the operation.
408   *
409   * @return  The diagnostic message for the operation, or {@code null} if it is
410   *          not included in the log message.
411   */
412  public String getDiagnosticMessage()
413  {
414    return diagnosticMessage;
415  }
416
417
418
419  /**
420   * Retrieves a message with additional information about the result of the
421   * operation.
422   *
423   * @return  A message with additional information about the result of the
424   *          operation, or {@code null} if it is not included in the log
425   *          message.
426   */
427  public String getAdditionalInformation()
428  {
429    return additionalInformation;
430  }
431
432
433
434  /**
435   * Retrieves the matched DN for the operation.
436   *
437   * @return  The matched DN for the operation, or {@code null} if it is not
438   *          included in the log message.
439   */
440  public String getMatchedDN()
441  {
442    return matchedDN;
443  }
444
445
446
447  /**
448   * Retrieves the list of referral URLs for the operation.
449   *
450   * @return  The list of referral URLs for the operation, or an empty list if
451   *          it is not included in the log message.
452   */
453  public List<String> getReferralURLs()
454  {
455    return referralURLs;
456  }
457
458
459
460  /**
461   * Retrieves the number of intermediate response messages returned in the
462   * course of processing the operation.
463   *
464   * @return  The number of intermediate response messages returned to the
465   *          client in the course of processing the operation, or {@code null}
466   *          if it is not included in the log message.
467   */
468  public Long getIntermediateResponsesReturned()
469  {
470    return intermediateResponsesReturned;
471  }
472
473
474
475  /**
476   * Retrieves the length of time in milliseconds required to process the
477   * operation.
478   *
479   * @return  The length of time in milliseconds required to process the
480   *          operation, or {@code null} if it is not included in the log
481   *          message.
482   */
483  public Double getProcessingTimeMillis()
484  {
485    return processingTime;
486  }
487
488
489
490  /**
491   * Retrieves the length of time in milliseconds the operation was required to
492   * wait on the work queue.
493   *
494   * @return  The length of time in milliseconds the operation was required to
495   *          wait on the work queue, or {@code null} if it is not included in
496   *          the log message.
497   */
498  public Double getQueueTimeMillis()
499  {
500    return queueTime;
501  }
502
503
504
505  /**
506   * Retrieves the OIDs of any response controls contained in the log message.
507   *
508   * @return  The OIDs of any response controls contained in the log message, or
509   *          an empty list if it is not included in the log message.
510   */
511  public List<String> getResponseControlOIDs()
512  {
513    return responseControlOIDs;
514  }
515
516
517
518  /**
519   * Retrieves a list of the additional servers that were accessed in the course
520   * of processing the operation.  For example, if the access log message is
521   * from a Directory Proxy Server instance, then this may contain a list of the
522   * backend servers used to process the operation.
523   *
524   * @return  A list of the additional servers that were accessed in the course
525   *          of processing the operation, or an empty list if it is not
526   *          included in the log message.
527   */
528  public List<String> getServersAccessed()
529  {
530    return serversAccessed;
531  }
532
533
534
535  /**
536   * Indicates whether the server accessed any uncached data in the course of
537   * processing the operation.
538   *
539   * @return  {@code true} if the server was known to access uncached data in
540   *          the course of processing the operation, {@code false} if the
541   *          server was known not to access uncached data, or {@code null} if
542   *          it is not included in the log message (and the server likely did
543   *          not access uncached data).
544   */
545  public Boolean getUncachedDataAccessed()
546  {
547    return uncachedDataAccessed;
548  }
549
550
551
552  /**
553   * Retrieves the content of the intermediate client result for the
554   * operation.
555   *
556   * @return  The content of the intermediate client result for the operation,
557   *          or {@code null} if it is not included in the log message.
558   */
559  public String getIntermediateClientResult()
560  {
561    return intermediateClientResult;
562  }
563
564
565
566  /**
567   * Retrieves the alternate authorization DN for the operation.
568   *
569   * @return  The alternate authorization DN for the operation, or {@code null}
570   *          if it is not included in the log message.
571   */
572  public String getAlternateAuthorizationDN()
573  {
574    return authzDN;
575  }
576
577
578
579  /**
580   * Retrieves the replication change ID for the operation, if available.
581   *
582   * @return  The replication change ID for the operation, or {@code null} if it
583   *          is not included in the log message.
584   */
585  public String getReplicationChangeID()
586  {
587    return replicationChangeID;
588  }
589
590
591
592  /**
593   * Retrieves the address of the backend server to which the request has been
594   * forwarded.
595   *
596   * @return  The address of the backend server to which the request has been
597   *          forwarded, or {@code null} if it is not included in the log
598   *          message.
599   */
600  public String getTargetHost()
601  {
602    return targetHost;
603  }
604
605
606
607  /**
608   * Retrieves the port of the backend server to which the request has been
609   * forwarded.
610   *
611   * @return  The port of the backend server to which the request has been
612   *          forwarded, or {@code null} if it is not included in the log
613   *          message.
614   */
615  public Integer getTargetPort()
616  {
617    return targetPort;
618  }
619
620
621
622  /**
623   * Retrieves the protocol used to forward the request to the backend server.
624   *
625   * @return  The protocol used to forward the request to the backend server, or
626   *          {@code null} if it is not included in the log message.
627   */
628  public String getTargetProtocol()
629  {
630    return targetProtocol;
631  }
632
633
634
635  /**
636   * Retrieves the local level that will be used for assured replication
637   * processing, if available.
638   *
639   * @return  The local level that will be used for assured replication
640   *          processing, or {@code null} if this is not included in the log
641   *          message (e.g., because assured replication will not be performed
642   *          for the operation).
643   */
644  public AssuredReplicationLocalLevel getAssuredReplicationLocalLevel()
645  {
646    return assuredReplicationLocalLevel;
647  }
648
649
650
651  /**
652   * Retrieves the remote level that will be used for assured replication
653   * processing, if available.
654   *
655   * @return  The remote level that will be used for assured replication
656   *          processing, or {@code null} if this is not included in the log
657   *          message (e.g., because assured replication will not be performed
658   *          for the operation).
659   */
660  public AssuredReplicationRemoteLevel getAssuredReplicationRemoteLevel()
661  {
662    return assuredReplicationRemoteLevel;
663  }
664
665
666
667  /**
668   * Retrieves the maximum length of time in milliseconds that the server will
669   * delay the response to the client while waiting for the replication
670   * assurance requirement to be satisfied.
671   *
672   * @return  The maximum length of time in milliseconds that the server will
673   *          delay the response to the client while waiting for the replication
674   *          assurance requirement to be satisfied, or {@code null} if this is
675   *          not included in the log message (e.g., because assured replication
676   *          will not be performed for the operation).
677   */
678  public Long getAssuredReplicationTimeoutMillis()
679  {
680    return assuredReplicationTimeoutMillis;
681  }
682
683
684
685  /**
686   * Indicates whether the operation response to the client will be delayed
687   * until replication assurance has been satisfied or the timeout has occurred.
688   *
689   * @return  {@code true} if the operation response to the client will be
690   *          delayed until replication assurance has been satisfied,
691   *          {@code false} if the response will not be delayed by assurance
692   *          processing, or {@code null} if this was not included in the
693   *          log message (e.g., because assured replication will not be
694   *          performed for the operation)
695   */
696  public Boolean getResponseDelayedByAssurance()
697  {
698    return responseDelayedByAssurance;
699  }
700
701
702
703  /**
704   * Retrieves the names of any privileges used during the course of processing
705   * the operation.
706   *
707   * @return  The names of any privileges used during the course of processing
708   *          the operation, or an empty list if no privileges were used or this
709   *          is not included in the log message.
710   */
711  public List<String> getUsedPrivileges()
712  {
713    return usedPrivileges;
714  }
715
716
717
718  /**
719   * Retrieves the names of any privileges used during the course of processing
720   * the operation before an alternate authorization identity was assigned.
721   *
722   * @return  The names of any privileges used during the course of processing
723   *          the operation before an alternate authorization identity was
724   *          assigned, or an empty list if no privileges were used or this is
725   *          not included in the log message.
726   */
727  public List<String> getPreAuthorizationUsedPrivileges()
728  {
729    return preAuthZUsedPrivileges;
730  }
731
732
733
734  /**
735   * Retrieves the names of any privileges that would have been required for
736   * processing the operation but that the requester did not have.
737   *
738   * @return  The names of any privileges that would have been required for
739   *          processing the operation but that the requester did not have, or
740   *          an empty list if there were no missing privileges or this is not
741   *          included in the log message.
742   */
743  public List<String> getMissingPrivileges()
744  {
745    return missingPrivileges;
746  }
747
748
749
750  /**
751   * Retrieves the names of any indexes for which one or more keys near
752   * (typically, within 80% of) the index entry limit were accessed while
753   * processing the operation.
754   *
755   * @return  The names of any indexes for which one or more keys near the index
756   *          entry limit were accessed while processing the operation, or an
757   *          empty list if no such index keys were accessed, or if this is not
758   *          included in the log message.
759   */
760  public List<String> getIndexesWithKeysAccessedNearEntryLimit()
761  {
762    return indexesWithKeysAccessedNearEntryLimit;
763  }
764
765
766
767  /**
768   * Retrieves the names of any indexes for which one or more keys over the
769   * index entry limit were accessed while processing the operation.
770   *
771   * @return  The names of any indexes for which one or more keys over the index
772   *          entry limit were accessed while processing the operation, or an
773   *          empty list if no such index keys were accessed, or if this is not
774   *          included in the log message.
775   */
776  public List<String> getIndexesWithKeysAccessedOverEntryLimit()
777  {
778    return indexesWithKeysAccessedOverEntryLimit;
779  }
780
781
782
783  /**
784   * {@inheritDoc}
785   */
786  @Override()
787  public AccessLogMessageType getMessageType()
788  {
789    return AccessLogMessageType.RESULT;
790  }
791}