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