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