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