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