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