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