001/*
002 * Copyright 2009-2024 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2009-2024 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) 2009-2024 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.util.NotMutable;
047import com.unboundid.util.NotNull;
048import com.unboundid.util.Nullable;
049import com.unboundid.util.ThreadSafety;
050import com.unboundid.util.ThreadSafetyLevel;
051
052
053
054/**
055 * This class provides a data structure that holds information about a log
056 * message that may appear in the Directory Server access log about the result
057 * of an extended operation processed by the Directory Server.
058 * <BR>
059 * <BLOCKQUOTE>
060 *   <B>NOTE:</B>  This class, and other classes within the
061 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
062 *   supported for use against Ping Identity, UnboundID, and
063 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
064 *   for proprietary functionality or for external specifications that are not
065 *   considered stable or mature enough to be guaranteed to work in an
066 *   interoperable way with other types of LDAP servers.
067 * </BLOCKQUOTE>
068 */
069@NotMutable()
070@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
071public final class ExtendedResultAccessLogMessage
072       extends ExtendedRequestAccessLogMessage
073       implements OperationResultAccessLogMessage
074{
075  /**
076   * The serial version UID for this serializable class.
077   */
078  private static final long serialVersionUID = -3980496377400403461L;
079
080
081
082  // Indicates whether the any uncached data was accessed in the course of
083  // processing this operation.
084  @Nullable private final Boolean uncachedDataAccessed;
085
086  // The processing time for the operation.
087  @Nullable private final Double processingTime;
088
089  // The queue time for the operation.
090  @Nullable private final Double queueTime;
091
092  // The list of privileges required for processing the operation that the
093  // requester did not have.
094  @NotNull private final List<String> missingPrivileges;
095
096  // The list of privileges used during the course of processing the operation
097  // before an alternate authorization identity was assigned.
098  @NotNull private final List<String> preAuthZUsedPrivileges;
099
100  // The list of referral URLs for the operation.
101  @NotNull private final List<String> referralURLs;
102
103  // The list of response control OIDs for the operation.
104  @NotNull private final List<String> responseControlOIDs;
105
106  // The list of servers accessed while processing the operation.
107  @NotNull private final List<String> serversAccessed;
108
109  // The list of privileges used during the course of processing the operation.
110  @NotNull private final List<String> usedPrivileges;
111
112  // The number of intermediate response messages returned to the client.
113  @Nullable private final Long intermediateResponsesReturned;
114
115  // The result code for the operation.
116  @Nullable private final ResultCode resultCode;
117
118  // Additional information about the operation result.
119  @Nullable private final String additionalInformation;
120
121  // The name of the client connection policy selected for the client.
122  @Nullable private final String clientConnectionPolicy;
123
124  // The diagnostic message for the operation.
125  @Nullable private final String diagnosticMessage;
126
127  // The intermediate client result for the operation.
128  @Nullable private final String intermediateClientResult;
129
130  // The matched DN for the operation.
131  @Nullable private final String matchedDN;
132
133  // The OID of the extended response.
134  @Nullable private final String responseOID;
135
136  // The port of the backend server to which the request has been forwarded.
137  @Nullable private final Integer targetPort;
138
139  // The address of the backend server to which the request has been forwarded.
140  @Nullable private final String targetHost;
141
142  // The protocol used to forward the request to the backend server.
143  @Nullable private final String targetProtocol;
144
145
146
147  /**
148   * Creates a new extended result access log message from the provided message
149   * string.
150   *
151   * @param  s  The string to be parsed as an extended result access log
152   *            message.
153   *
154   * @throws  LogException  If the provided string cannot be parsed as a valid
155   *                        log message.
156   */
157  public ExtendedResultAccessLogMessage(@NotNull final String s)
158         throws LogException
159  {
160    this(new LogMessage(s));
161  }
162
163
164
165  /**
166   * Creates a new extended result access log message from the provided log
167   * message.
168   *
169   * @param  m  The log message to be parsed as an extended result access log
170   *            message.
171   */
172  public ExtendedResultAccessLogMessage(@NotNull final LogMessage m)
173  {
174    super(m);
175
176    diagnosticMessage        = getNamedValue("message");
177    additionalInformation    = getNamedValue("additionalInfo");
178    matchedDN                = getNamedValue("matchedDN");
179    processingTime           = getNamedValueAsDouble("etime");
180    queueTime                = getNamedValueAsDouble("qtime");
181    intermediateClientResult = getNamedValue("from");
182    responseOID              = getNamedValue("responseOID");
183    targetHost               = getNamedValue("targetHost");
184    targetPort               = getNamedValueAsInteger("targetPort");
185    targetProtocol           = getNamedValue("targetProtocol");
186    clientConnectionPolicy   = getNamedValue("clientConnectionPolicy");
187
188    intermediateResponsesReturned =
189         getNamedValueAsLong("intermediateResponsesReturned");
190
191    final Integer rcInteger = getNamedValueAsInteger("resultCode");
192    if (rcInteger == null)
193    {
194      resultCode = null;
195    }
196    else
197    {
198      resultCode = ResultCode.valueOf(rcInteger);
199    }
200
201    final String refStr = getNamedValue("referralURLs");
202    if ((refStr == null) || refStr.isEmpty())
203    {
204      referralURLs = Collections.emptyList();
205    }
206    else
207    {
208      final LinkedList<String> refs = new LinkedList<>();
209      int startPos = 0;
210      while (true)
211      {
212        final int commaPos = refStr.indexOf(",ldap", startPos);
213        if (commaPos < 0)
214        {
215          refs.add(refStr.substring(startPos));
216          break;
217        }
218        else
219        {
220          refs.add(refStr.substring(startPos, commaPos));
221          startPos = commaPos+1;
222        }
223      }
224      referralURLs = Collections.unmodifiableList(refs);
225    }
226
227    final String controlStr = getNamedValue("responseControls");
228    if (controlStr == null)
229    {
230      responseControlOIDs = Collections.emptyList();
231    }
232    else
233    {
234      final LinkedList<String> controlList = new LinkedList<>();
235      final StringTokenizer t = new StringTokenizer(controlStr, ",");
236      while (t.hasMoreTokens())
237      {
238        controlList.add(t.nextToken());
239      }
240      responseControlOIDs = Collections.unmodifiableList(controlList);
241    }
242
243    final String serversAccessedStr = getNamedValue("serversAccessed");
244    if ((serversAccessedStr == null) || serversAccessedStr.isEmpty())
245    {
246      serversAccessed = Collections.emptyList();
247    }
248    else
249    {
250      final LinkedList<String> servers = new LinkedList<>();
251      final StringTokenizer tokenizer =
252           new StringTokenizer(serversAccessedStr, ",");
253      while (tokenizer.hasMoreTokens())
254      {
255        servers.add(tokenizer.nextToken());
256      }
257      serversAccessed = Collections.unmodifiableList(servers);
258    }
259
260    uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed");
261
262    final String usedPrivilegesStr = getNamedValue("usedPrivileges");
263    if ((usedPrivilegesStr == null) || usedPrivilegesStr.isEmpty())
264    {
265      usedPrivileges = Collections.emptyList();
266    }
267    else
268    {
269      final LinkedList<String> privileges = new LinkedList<>();
270      final StringTokenizer tokenizer =
271           new StringTokenizer(usedPrivilegesStr, ",");
272      while (tokenizer.hasMoreTokens())
273      {
274        privileges.add(tokenizer.nextToken());
275      }
276      usedPrivileges = Collections.unmodifiableList(privileges);
277    }
278
279    final String preAuthZUsedPrivilegesStr =
280         getNamedValue("preAuthZUsedPrivileges");
281    if ((preAuthZUsedPrivilegesStr == null) ||
282        preAuthZUsedPrivilegesStr.isEmpty())
283    {
284      preAuthZUsedPrivileges = Collections.emptyList();
285    }
286    else
287    {
288      final LinkedList<String> privileges = new LinkedList<>();
289      final StringTokenizer tokenizer =
290           new StringTokenizer(preAuthZUsedPrivilegesStr, ",");
291      while (tokenizer.hasMoreTokens())
292      {
293        privileges.add(tokenizer.nextToken());
294      }
295      preAuthZUsedPrivileges = Collections.unmodifiableList(privileges);
296    }
297
298    final String missingPrivilegesStr = getNamedValue("missingPrivileges");
299    if ((missingPrivilegesStr == null) || missingPrivilegesStr.isEmpty())
300    {
301      missingPrivileges = Collections.emptyList();
302    }
303    else
304    {
305      final LinkedList<String> privileges = new LinkedList<>();
306      final StringTokenizer tokenizer =
307           new StringTokenizer(missingPrivilegesStr, ",");
308      while (tokenizer.hasMoreTokens())
309      {
310        privileges.add(tokenizer.nextToken());
311      }
312      missingPrivileges = Collections.unmodifiableList(privileges);
313    }
314  }
315
316
317
318  /**
319   * Retrieves the result code for the operation.
320   *
321   * @return  The result code for the operation, or {@code null} if it is not
322   *          included in the log message.
323   */
324  @Override()
325  @Nullable()
326  public ResultCode getResultCode()
327  {
328    return resultCode;
329  }
330
331
332
333  /**
334   * Retrieves the diagnostic message for the operation.
335   *
336   * @return  The diagnostic message for the operation, or {@code null} if it is
337   *          not included in the log message.
338   */
339  @Override()
340  @Nullable()
341  public String getDiagnosticMessage()
342  {
343    return diagnosticMessage;
344  }
345
346
347
348  /**
349   * Retrieves a message with additional information about the result of the
350   * operation.
351   *
352   * @return  A message with additional information about the result of the
353   *          operation, or {@code null} if it is not included in the log
354   *          message.
355   */
356  @Override()
357  @Nullable()
358  public String getAdditionalInformation()
359  {
360    return additionalInformation;
361  }
362
363
364
365  /**
366   * Retrieves the matched DN for the operation.
367   *
368   * @return  The matched DN for the operation, or {@code null} if it is not
369   *          included in the log message.
370   */
371  @Override()
372  @Nullable()
373  public String getMatchedDN()
374  {
375    return matchedDN;
376  }
377
378
379
380  /**
381   * Retrieves the list of referral URLs for the operation.
382   *
383   * @return  The list of referral URLs for the operation, or an empty list if
384   *          it is not included in the log message.
385   */
386  @Override()
387  @NotNull()
388  public List<String> getReferralURLs()
389  {
390    return referralURLs;
391  }
392
393
394
395  /**
396   * Retrieves a list of the additional servers that were accessed in the course
397   * of processing the operation.  For example, if the access log message is
398   * from a Directory Proxy Server instance, then this may contain a list of the
399   * backend servers used to process the operation.
400   *
401   * @return  A list of the additional servers that were accessed in the course
402   *          of processing the operation, or an empty list if it is not
403   *          included in the log message.
404   */
405  @Override()
406  @NotNull()
407  public List<String> getServersAccessed()
408  {
409    return serversAccessed;
410  }
411
412
413
414  /**
415   * Indicates whether the server accessed any uncached data in the course of
416   * processing the operation.
417   *
418   * @return  {@code true} if the server was known to access uncached data in
419   *          the course of processing the operation, {@code false} if the
420   *          server was known not to access uncached data, or {@code null} if
421   *          it is not included in the log message (and the server likely did
422   *          not access uncached data).
423   */
424  @Nullable()
425  public Boolean getUncachedDataAccessed()
426  {
427    return uncachedDataAccessed;
428  }
429
430
431
432  /**
433   * Retrieves the number of intermediate response messages returned in the
434   * course of processing the operation.
435   *
436   * @return  The number of intermediate response messages returned to the
437   *          client in the course of processing the operation, or {@code null}
438   *          if it is not included in the log message.
439   */
440  @Override()
441  @Nullable()
442  public Long getIntermediateResponsesReturned()
443  {
444    return intermediateResponsesReturned;
445  }
446
447
448
449  /**
450   * Retrieves the length of time in milliseconds required to process the
451   * operation.
452   *
453   * @return  The length of time in milliseconds required to process the
454   *          operation, or {@code null} if it is not included in the log
455   *          message.
456   */
457  @Override()
458  @Nullable()
459  public Double getProcessingTimeMillis()
460  {
461    return processingTime;
462  }
463
464
465
466  /**
467   * Retrieves the length of time in milliseconds the operation was required to
468   * wait on the work queue.
469   *
470   * @return  The length of time in milliseconds the operation was required to
471   *          wait on the work queue, or {@code null} if it is not included in
472   *          the log message.
473   */
474  @Override()
475  @Nullable()
476  public Double getQueueTimeMillis()
477  {
478    return queueTime;
479  }
480
481
482
483  /**
484   * Retrieves the OIDs of any response controls contained in the log message.
485   *
486   * @return  The OIDs of any response controls contained in the log message, or
487   *          an empty list if it is not included in the log message.
488   */
489  @Override()
490  @NotNull()
491  public List<String> getResponseControlOIDs()
492  {
493    return responseControlOIDs;
494  }
495
496
497
498  /**
499   * Retrieves the content of the intermediate client result for the
500   * operation.
501   *
502   * @return  The content of the intermediate client result for the operation,
503   *          or {@code null} if it is not included in the log message.
504   */
505  @Override()
506  @Nullable()
507  public String getIntermediateClientResult()
508  {
509    return intermediateClientResult;
510  }
511
512
513
514  /**
515   * Retrieves the OID for the extended response.
516   *
517   * @return  The OID for the extended response, or {@code null} if it is not
518   *          included in the log message.
519   */
520  @Nullable()
521  public String getResponseOID()
522  {
523    return responseOID;
524  }
525
526
527
528  /**
529   * Retrieves the address of the backend server to which the request has been
530   * forwarded.
531   *
532   * @return  The address of the backend server to which the request has been
533   *          forwarded, or {@code null} if it is not included in the log
534   *          message.
535   */
536  @Nullable()
537  public String getTargetHost()
538  {
539    return targetHost;
540  }
541
542
543
544  /**
545   * Retrieves the port of the backend server to which the request has been
546   * forwarded.
547   *
548   * @return  The port of the backend server to which the request has been
549   *          forwarded, or {@code null} if it is not included in the log
550   *          message.
551   */
552  @Nullable()
553  public Integer getTargetPort()
554  {
555    return targetPort;
556  }
557
558
559
560  /**
561   * Retrieves the protocol used to forward the request to the backend server.
562   *
563   * @return  The protocol used to forward the request to the backend server, or
564   *          {@code null} if it is not included in the log message.
565   */
566  @Nullable()
567  public String getTargetProtocol()
568  {
569    return targetProtocol;
570  }
571
572
573
574  /**
575   * Retrieves the name of the client connection policy that was selected for
576   * the client connection.
577   *
578   * @return  The name of the client connection policy that was selected for the
579   *          client connection, or {@code null} if it is not included in the
580   *          log message.
581   */
582  @Nullable()
583  public String getClientConnectionPolicy()
584  {
585    return clientConnectionPolicy;
586  }
587
588
589
590  /**
591   * Retrieves the names of any privileges used during the course of processing
592   * the operation.
593   *
594   * @return  The names of any privileges used during the course of processing
595   *          the operation, or an empty list if no privileges were used or this
596   *          is not included in the log message.
597   */
598  @NotNull()
599  public List<String> getUsedPrivileges()
600  {
601    return usedPrivileges;
602  }
603
604
605
606  /**
607   * Retrieves the names of any privileges used during the course of processing
608   * the operation before an alternate authorization identity was assigned.
609   *
610   * @return  The names of any privileges used during the course of processing
611   *          the operation before an alternate authorization identity was
612   *          assigned, or an empty list if no privileges were used or this is
613   *          not included in the log message.
614   */
615  @NotNull()
616  public List<String> getPreAuthorizationUsedPrivileges()
617  {
618    return preAuthZUsedPrivileges;
619  }
620
621
622
623  /**
624   * Retrieves the names of any privileges that would have been required for
625   * processing the operation but that the requester did not have.
626   *
627   * @return  The names of any privileges that would have been required for
628   *          processing the operation but that the requester did not have, or
629   *          an empty list if there were no missing privileges or this is not
630   *          included in the log message.
631   */
632  @NotNull()
633  public List<String> getMissingPrivileges()
634  {
635    return missingPrivileges;
636  }
637
638
639
640  /**
641   * {@inheritDoc}
642   */
643  @Override()
644  @NotNull()
645  public AccessLogMessageType getMessageType()
646  {
647    return AccessLogMessageType.RESULT;
648  }
649}