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