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 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 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 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.length() == 0))
171    {
172      referralURLs = Collections.emptyList();
173    }
174    else
175    {
176      final LinkedList<String> refs = new LinkedList<String>();
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<String>();
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.length() == 0))
213    {
214      serversAccessed = Collections.emptyList();
215    }
216    else
217    {
218      final LinkedList<String> servers = new LinkedList<String>();
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.length() == 0))
232    {
233      usedPrivileges = Collections.emptyList();
234    }
235    else
236    {
237      final LinkedList<String> privileges = new LinkedList<String>();
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.length() == 0))
251    {
252      preAuthZUsedPrivileges = Collections.emptyList();
253    }
254    else
255    {
256      final LinkedList<String> privileges = new LinkedList<String>();
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.length() == 0))
268    {
269      missingPrivileges = Collections.emptyList();
270    }
271    else
272    {
273      final LinkedList<String> privileges = new LinkedList<String>();
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  public ResultCode getResultCode()
293  {
294    return resultCode;
295  }
296
297
298
299  /**
300   * Retrieves the diagnostic message for the operation.
301   *
302   * @return  The diagnostic message for the operation, or {@code null} if it is
303   *          not included in the log message.
304   */
305  public String getDiagnosticMessage()
306  {
307    return diagnosticMessage;
308  }
309
310
311
312  /**
313   * Retrieves a message with additional information about the result of the
314   * operation.
315   *
316   * @return  A message with additional information about the result of the
317   *          operation, or {@code null} if it is not included in the log
318   *          message.
319   */
320  public String getAdditionalInformation()
321  {
322    return additionalInformation;
323  }
324
325
326
327  /**
328   * Retrieves the matched DN for the operation.
329   *
330   * @return  The matched DN for the operation, or {@code null} if it is not
331   *          included in the log message.
332   */
333  public String getMatchedDN()
334  {
335    return matchedDN;
336  }
337
338
339
340  /**
341   * Retrieves the list of referral URLs for the operation.
342   *
343   * @return  The list of referral URLs for the operation, or an empty list if
344   *          it is not included in the log message.
345   */
346  public List<String> getReferralURLs()
347  {
348    return referralURLs;
349  }
350
351
352
353  /**
354   * Retrieves the length of time in milliseconds required to process the
355   * operation.
356   *
357   * @return  The length of time in milliseconds required to process the
358   *          operation, or {@code null} if it is not included in the log
359   *          message.
360   */
361  public Double getProcessingTimeMillis()
362  {
363    return processingTime;
364  }
365
366
367
368  /**
369   * Retrieves the length of time in milliseconds the operation was required to
370   * wait on the work queue.
371   *
372   * @return  The length of time in milliseconds the operation was required to
373   *          wait on the work queue, or {@code null} if it is not included in
374   *          the log message.
375   */
376  public Double getQueueTimeMillis()
377  {
378    return queueTime;
379  }
380
381
382
383  /**
384   * Retrieves the OIDs of any response controls contained in the log message.
385   *
386   * @return  The OIDs of any response controls contained in the log message, or
387   *          an empty list if it is not included in the log message.
388   */
389  public List<String> getResponseControlOIDs()
390  {
391    return responseControlOIDs;
392  }
393
394
395
396  /**
397   * Retrieves a list of the additional servers that were accessed in the course
398   * of processing the operation.  For example, if the access log message is
399   * from a Directory Proxy Server instance, then this may contain a list of the
400   * backend servers used to process the operation.
401   *
402   * @return  A list of the additional servers that were accessed in the course
403   *          of processing the operation, or an empty list if it is not
404   *          included in the log message.
405   */
406  public List<String> getServersAccessed()
407  {
408    return serversAccessed;
409  }
410
411
412
413  /**
414   * Indicates whether the server accessed any uncached data in the course of
415   * processing the operation.
416   *
417   * @return  {@code true} if the server was known to access uncached data in
418   *          the course of processing the operation, {@code false} if the
419   *          server was known not to access uncached data, or {@code null} if
420   *          it is not included in the log message (and the server likely did
421   *          not access uncached data).
422   */
423  public Boolean getUncachedDataAccessed()
424  {
425    return uncachedDataAccessed;
426  }
427
428
429
430  /**
431   * Retrieves the content of the intermediate client result for the
432   * operation.
433   *
434   * @return  The content of the intermediate client result for the operation,
435   *          or {@code null} if it is not included in the log message.
436   */
437  public String getIntermediateClientResult()
438  {
439    return intermediateClientResult;
440  }
441
442
443
444  /**
445   * Retrieves the address of the backend server to which the request has been
446   * forwarded.
447   *
448   * @return  The address of the backend server to which the request has been
449   *          forwarded, or {@code null} if it is not included in the log
450   *          message.
451   */
452  public String getTargetHost()
453  {
454    return targetHost;
455  }
456
457
458
459  /**
460   * Retrieves the port of the backend server to which the request has been
461   * forwarded.
462   *
463   * @return  The port of the backend server to which the request has been
464   *          forwarded, or {@code null} if it is not included in the log
465   *          message.
466   */
467  public Integer getTargetPort()
468  {
469    return targetPort;
470  }
471
472
473
474  /**
475   * Retrieves the protocol used to forward the request to the backend server.
476   *
477   * @return  The protocol used to forward the request to the backend server, or
478   *          {@code null} if it is not included in the log message.
479   */
480  public String getTargetProtocol()
481  {
482    return targetProtocol;
483  }
484
485
486
487  /**
488   * Retrieves the names of any privileges used during the course of processing
489   * the operation.
490   *
491   * @return  The names of any privileges used during the course of processing
492   *          the operation, or an empty list if no privileges were used or this
493   *          is not included in the log message.
494   */
495  public List<String> getUsedPrivileges()
496  {
497    return usedPrivileges;
498  }
499
500
501
502  /**
503   * Retrieves the names of any privileges used during the course of processing
504   * the operation before an alternate authorization identity was assigned.
505   *
506   * @return  The names of any privileges used during the course of processing
507   *          the operation before an alternate authorization identity was
508   *          assigned, or an empty list if no privileges were used or this is
509   *          not included in the log message.
510   */
511  public List<String> getPreAuthorizationUsedPrivileges()
512  {
513    return preAuthZUsedPrivileges;
514  }
515
516
517
518  /**
519   * Retrieves the names of any privileges that would have been required for
520   * processing the operation but that the requester did not have.
521   *
522   * @return  The names of any privileges that would have been required for
523   *          processing the operation but that the requester did not have, or
524   *          an empty list if there were no missing privileges or this is not
525   *          included in the log message.
526   */
527  public List<String> getMissingPrivileges()
528  {
529    return missingPrivileges;
530  }
531
532
533
534  /**
535   * {@inheritDoc}
536   */
537  @Override()
538  public AccessLogMessageType getMessageType()
539  {
540    return AccessLogMessageType.RESULT;
541  }
542}