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