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