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