001    /*
002     * Copyright 2009-2015 UnboundID Corp.
003     * All Rights Reserved.
004     */
005    /*
006     * Copyright (C) 2015 UnboundID Corp.
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     */
021    package com.unboundid.ldap.sdk.unboundidds.logs;
022    
023    
024    
025    import java.util.Collections;
026    import java.util.LinkedList;
027    import java.util.List;
028    import java.util.StringTokenizer;
029    
030    import com.unboundid.ldap.sdk.ResultCode;
031    import com.unboundid.util.NotMutable;
032    import com.unboundid.util.ThreadSafety;
033    import com.unboundid.util.ThreadSafetyLevel;
034    
035    
036    
037    /**
038     * <BLOCKQUOTE>
039     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
040     *   LDAP SDK for Java.  It is not available for use in applications that
041     *   include only the Standard Edition of the LDAP SDK, and is not supported for
042     *   use in conjunction with non-UnboundID products.
043     * </BLOCKQUOTE>
044     * This class provides a data structure that holds information about a log
045     * message that may appear in the Directory Server access log about the result
046     * of a bind operation processed by the Directory Server.
047     */
048    @NotMutable()
049    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
050    public final class BindResultAccessLogMessage
051           extends BindRequestAccessLogMessage
052           implements OperationResultAccessLogMessage
053    {
054      /**
055       * The serial version UID for this serializable class.
056       */
057      private static final long serialVersionUID = -5612410738721878134L;
058    
059    
060    
061      // Indicates whether a retired password was used to perform the bind.
062      private final Boolean retiredPasswordUsed;
063    
064      // Indicates whether the any uncached data was accessed in the course of
065      // processing this operation.
066      private final Boolean uncachedDataAccessed;
067    
068      // The processing time for the operation.
069      private final Double processingTime;
070    
071      // The queue time for the operation.
072      private final Double queueTime;
073    
074      // The list of privileges required for processing the operation that the
075      // requester did not have.
076      private final List<String> missingPrivileges;
077    
078      // The list of privileges used during the course of processing the operation
079      // before an alternate authorization identity was assigned.
080      private final List<String> preAuthZUsedPrivileges;
081    
082      // The list of referral URLs for the operation.
083      private final List<String> referralURLs;
084    
085      // The list of response control OIDs for the operation.
086      private final List<String> responseControlOIDs;
087    
088      // The list of servers accessed while processing the operation.
089      private final List<String> serversAccessed;
090    
091      // The list of privileges used during the course of processing the operation.
092      private final List<String> usedPrivileges;
093    
094      // The numeric identifier for the authentication failure reason.
095      private final Long authFailureID;
096    
097      // The number of intermediate response messages returned to the client.
098      private final Long intermediateResponsesReturned;
099    
100      // The result code for the operation.
101      private final ResultCode resultCode;
102    
103      // Additional information about the operation result.
104      private final String additionalInformation;
105    
106      // The DN of the authenticated user.
107      private final String authDN;
108    
109      // A message with information about the reason for the authentication failure.
110      private final String authFailureReason;
111    
112      // The DN of the alternate authorization identity.
113      private final String authzDN;
114    
115      // The name of the client connection policy selected for the client.
116      private final String clientConnectionPolicy;
117    
118      // The diagnostic message for the operation.
119      private final String diagnosticMessage;
120    
121      // The intermediate client result for the operation.
122      private final String intermediateClientResult;
123    
124      // The matched DN for the operation.
125      private final String matchedDN;
126    
127      // The port of the backend server to which the request has been forwarded.
128      private final Integer targetPort;
129    
130      // The address of the backend server to which the request has been forwarded.
131      private final String targetHost;
132    
133      // The protocol used to forward the request to the backend server.
134      private final String targetProtocol;
135    
136    
137    
138      /**
139       * Creates a new bind result access log message from the provided message
140       * string.
141       *
142       * @param  s  The string to be parsed as a bind result access log message.
143       *
144       * @throws  LogException  If the provided string cannot be parsed as a valid
145       *                        log message.
146       */
147      public BindResultAccessLogMessage(final String s)
148             throws LogException
149      {
150        this(new LogMessage(s));
151      }
152    
153    
154    
155      /**
156       * Creates a new bind result access log message from the provided log message.
157       *
158       * @param  m  The log message to be parsed as a bind result access log
159       *            message.
160       */
161      public BindResultAccessLogMessage(final LogMessage m)
162      {
163        super(m);
164    
165        diagnosticMessage        = getNamedValue("message");
166        additionalInformation    = getNamedValue("additionalInfo");
167        matchedDN                = getNamedValue("matchedDN");
168        processingTime           = getNamedValueAsDouble("etime");
169        queueTime                = getNamedValueAsDouble("qtime");
170        intermediateClientResult = getNamedValue("from");
171        authDN                   = getNamedValue("authDN");
172        authzDN                  = getNamedValue("authzDN");
173        authFailureID            = getNamedValueAsLong("authFailureID");
174        authFailureReason        = getNamedValue("authFailureReason");
175        targetHost               = getNamedValue("targetHost");
176        targetPort               = getNamedValueAsInteger("targetPort");
177        targetProtocol           = getNamedValue("targetProtocol");
178        clientConnectionPolicy   = getNamedValue("clientConnectionPolicy");
179    
180        intermediateResponsesReturned =
181             getNamedValueAsLong("intermediateResponsesReturned");
182    
183        final Integer rcInteger = getNamedValueAsInteger("resultCode");
184        if (rcInteger == null)
185        {
186          resultCode = null;
187        }
188        else
189        {
190          resultCode = ResultCode.valueOf(rcInteger);
191        }
192    
193        final String refStr = getNamedValue("referralURLs");
194        if ((refStr == null) || (refStr.length() == 0))
195        {
196          referralURLs = Collections.emptyList();
197        }
198        else
199        {
200          final LinkedList<String> refs = new LinkedList<String>();
201          int startPos = 0;
202          while (true)
203          {
204            final int commaPos = refStr.indexOf(",ldap", startPos);
205            if (commaPos < 0)
206            {
207              refs.add(refStr.substring(startPos));
208              break;
209            }
210            else
211            {
212              refs.add(refStr.substring(startPos, commaPos));
213              startPos = commaPos+1;
214            }
215          }
216          referralURLs = Collections.unmodifiableList(refs);
217        }
218    
219        final String controlStr = getNamedValue("responseControls");
220        if (controlStr == null)
221        {
222          responseControlOIDs = Collections.emptyList();
223        }
224        else
225        {
226          final LinkedList<String> controlList = new LinkedList<String>();
227          final StringTokenizer t = new StringTokenizer(controlStr, ",");
228          while (t.hasMoreTokens())
229          {
230            controlList.add(t.nextToken());
231          }
232          responseControlOIDs = Collections.unmodifiableList(controlList);
233        }
234    
235        final String serversAccessedStr = getNamedValue("serversAccessed");
236        if ((serversAccessedStr == null) || (serversAccessedStr.length() == 0))
237        {
238          serversAccessed = Collections.emptyList();
239        }
240        else
241        {
242          final LinkedList<String> servers = new LinkedList<String>();
243          final StringTokenizer tokenizer =
244               new StringTokenizer(serversAccessedStr, ",");
245          while (tokenizer.hasMoreTokens())
246          {
247            servers.add(tokenizer.nextToken());
248          }
249          serversAccessed = Collections.unmodifiableList(servers);
250        }
251    
252        uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed");
253        retiredPasswordUsed = getNamedValueAsBoolean("retiredPasswordUsed");
254    
255        final String usedPrivilegesStr = getNamedValue("usedPrivileges");
256        if ((usedPrivilegesStr == null) || (usedPrivilegesStr.length() == 0))
257        {
258          usedPrivileges = Collections.emptyList();
259        }
260        else
261        {
262          final LinkedList<String> privileges = new LinkedList<String>();
263          final StringTokenizer tokenizer =
264               new StringTokenizer(usedPrivilegesStr, ",");
265          while (tokenizer.hasMoreTokens())
266          {
267            privileges.add(tokenizer.nextToken());
268          }
269          usedPrivileges = Collections.unmodifiableList(privileges);
270        }
271    
272        final String preAuthZUsedPrivilegesStr =
273             getNamedValue("preAuthZUsedPrivileges");
274        if ((preAuthZUsedPrivilegesStr == null) ||
275            (preAuthZUsedPrivilegesStr.length() == 0))
276        {
277          preAuthZUsedPrivileges = Collections.emptyList();
278        }
279        else
280        {
281          final LinkedList<String> privileges = new LinkedList<String>();
282          final StringTokenizer tokenizer =
283               new StringTokenizer(preAuthZUsedPrivilegesStr, ",");
284          while (tokenizer.hasMoreTokens())
285          {
286            privileges.add(tokenizer.nextToken());
287          }
288          preAuthZUsedPrivileges = Collections.unmodifiableList(privileges);
289        }
290    
291        final String missingPrivilegesStr = getNamedValue("missingPrivileges");
292        if ((missingPrivilegesStr == null) || (missingPrivilegesStr.length() == 0))
293        {
294          missingPrivileges = Collections.emptyList();
295        }
296        else
297        {
298          final LinkedList<String> privileges = new LinkedList<String>();
299          final StringTokenizer tokenizer =
300               new StringTokenizer(missingPrivilegesStr, ",");
301          while (tokenizer.hasMoreTokens())
302          {
303            privileges.add(tokenizer.nextToken());
304          }
305          missingPrivileges = Collections.unmodifiableList(privileges);
306        }
307      }
308    
309    
310    
311      /**
312       * Retrieves the result code for the operation.
313       *
314       * @return  The result code for the operation, or {@code null} if it is not
315       *          included in the log message.
316       */
317      public ResultCode getResultCode()
318      {
319        return resultCode;
320      }
321    
322    
323    
324      /**
325       * Retrieves the diagnostic message for the operation.
326       *
327       * @return  The diagnostic message for the operation, or {@code null} if it is
328       *          not included in the log message.
329       */
330      public String getDiagnosticMessage()
331      {
332        return diagnosticMessage;
333      }
334    
335    
336    
337      /**
338       * Retrieves a message with additional information about the result of the
339       * operation.
340       *
341       * @return  A message with additional information about the result of the
342       *          operation, or {@code null} if it is not included in the log
343       *          message.
344       */
345      public String getAdditionalInformation()
346      {
347        return additionalInformation;
348      }
349    
350    
351    
352      /**
353       * Retrieves the matched DN for the operation.
354       *
355       * @return  The matched DN for the operation, or {@code null} if it is not
356       *          included in the log message.
357       */
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      public List<String> getReferralURLs()
372      {
373        return referralURLs;
374      }
375    
376    
377    
378      /**
379       * Retrieves the number of intermediate response messages returned in the
380       * course of processing the operation.
381       *
382       * @return  The number of intermediate response messages returned to the
383       *          client in the course of processing the operation, or {@code null}
384       *          if it is not included in the log message.
385       */
386      public Long getIntermediateResponsesReturned()
387      {
388        return intermediateResponsesReturned;
389      }
390    
391    
392    
393      /**
394       * Retrieves the length of time in milliseconds required to process the
395       * operation.
396       *
397       * @return  The length of time in milliseconds required to process the
398       *          operation, or {@code null} if it is not included in the log
399       *          message.
400       */
401      public Double getProcessingTimeMillis()
402      {
403        return processingTime;
404      }
405    
406    
407    
408      /**
409       * Retrieves the length of time in milliseconds the operation was required to
410       * wait on the work queue.
411       *
412       * @return  The length of time in milliseconds the operation was required to
413       *          wait on the work queue, or {@code null} if it is not included in
414       *          the log message.
415       */
416      public Double getQueueTimeMillis()
417      {
418        return queueTime;
419      }
420    
421    
422    
423      /**
424       * Retrieves the OIDs of any response controls contained in the log message.
425       *
426       * @return  The OIDs of any response controls contained in the log message, or
427       *          an empty list if it is not included in the log message.
428       */
429      public List<String> getResponseControlOIDs()
430      {
431        return responseControlOIDs;
432      }
433    
434    
435    
436      /**
437       * Retrieves a list of the additional servers that were accessed in the course
438       * of processing the operation.  For example, if the access log message is
439       * from a Directory Proxy Server instance, then this may contain a list of the
440       * backend servers used to process the operation.
441       *
442       * @return  A list of the additional servers that were accessed in the course
443       *          of processing the operation, or an empty list if it is not
444       *          included in the log message.
445       */
446      public List<String> getServersAccessed()
447      {
448        return serversAccessed;
449      }
450    
451    
452    
453      /**
454       * Indicates whether the server accessed any uncached data in the course of
455       * processing the operation.
456       *
457       * @return  {@code true} if the server was known to access uncached data in
458       *          the course of processing the operation, {@code false} if the
459       *          server was known not to access uncached data, or {@code null} if
460       *          it is not included in the log message (and the server likely did
461       *          not access uncached data).
462       */
463      public Boolean getUncachedDataAccessed()
464      {
465        return uncachedDataAccessed;
466      }
467    
468    
469    
470      /**
471       * Retrieves the content of the intermediate client result for the
472       * operation.
473       *
474       * @return  The content of the intermediate client result for the operation,
475       *          or {@code null} if it is not included in the log message.
476       */
477      public String getIntermediateClientResult()
478      {
479        return intermediateClientResult;
480      }
481    
482    
483    
484      /**
485       * Retrieves the DN of the user authenticated by the bind operation.
486       *
487       * @return  The DN of the user authenticated by the bind operation, or
488       *          {@code null} if it is not included in the log message.
489       */
490      public String getAuthenticationDN()
491      {
492        return authDN;
493      }
494    
495    
496    
497      /**
498       * Retrieves the DN of the alternate authorization identity for the bind
499       * operation.
500       *
501       * @return  The DN of the alternate authorization identity for the bind
502       *          operation, or {@code null} if it is not included in the log
503       *          message.
504       */
505      public String getAuthorizationDN()
506      {
507        return authzDN;
508      }
509    
510    
511    
512      /**
513       * Retrieves the numeric identifier for the authentication failure reason.
514       *
515       * @return  The numeric identifier for the authentication failure reason, or
516       *          {@code null} if it is not included in the log message.
517       */
518      public Long getAuthenticationFailureID()
519      {
520        return authFailureID;
521      }
522    
523    
524    
525      /**
526       * Retrieves a message with information about the reason that the
527       * authentication attempt failed.
528       *
529       * @return  A message with information about the reason that the
530       *          authentication attempt failed, or {@code null} if it is not
531       *          included in the log message.
532       */
533      public String getAuthenticationFailureReason()
534      {
535        return authFailureReason;
536      }
537    
538    
539    
540      /**
541       * Indicates whether a retired password was used in the course of processing
542       * the bind.
543       *
544       * @return  {@code true} if a retired password was used in the course of
545       *          processing the bind, {@code false} if a retired password was not
546       *          used in the course of processing the bind, or {@code null} if
547       *          this was not included in the log message (and a retired password
548       *          was likely not used in the course of processing the operation).
549       */
550      public Boolean getRetiredPasswordUsed()
551      {
552        return retiredPasswordUsed;
553      }
554    
555    
556    
557      /**
558       * Retrieves the address of the backend server to which the request has been
559       * forwarded.
560       *
561       * @return  The address of the backend server to which the request has been
562       *          forwarded, or {@code null} if it is not included in the log
563       *          message.
564       */
565      public String getTargetHost()
566      {
567        return targetHost;
568      }
569    
570    
571    
572      /**
573       * Retrieves the port of the backend server to which the request has been
574       * forwarded.
575       *
576       * @return  The port of the backend server to which the request has been
577       *          forwarded, or {@code null} if it is not included in the log
578       *          message.
579       */
580      public Integer getTargetPort()
581      {
582        return targetPort;
583      }
584    
585    
586    
587      /**
588       * Retrieves the protocol used to forward the request to the backend server.
589       *
590       * @return  The protocol used to forward the request to the backend server, or
591       *          {@code null} if it is not included in the log message.
592       */
593      public String getTargetProtocol()
594      {
595        return targetProtocol;
596      }
597    
598    
599    
600      /**
601       * Retrieves the name of the client connection policy that was selected for
602       * the client connection.
603       *
604       * @return  The name of the client connection policy that was selected for the
605       *          client connection, or {@code null} if it is not included in the
606       *          log message.
607       */
608      public String getClientConnectionPolicy()
609      {
610        return clientConnectionPolicy;
611      }
612    
613    
614    
615      /**
616       * Retrieves the names of any privileges used during the course of processing
617       * the operation.
618       *
619       * @return  The names of any privileges used during the course of processing
620       *          the operation, or an empty list if no privileges were used or this
621       *          is not included in the log message.
622       */
623      public List<String> getUsedPrivileges()
624      {
625        return usedPrivileges;
626      }
627    
628    
629    
630      /**
631       * Retrieves the names of any privileges used during the course of processing
632       * the operation before an alternate authorization identity was assigned.
633       *
634       * @return  The names of any privileges used during the course of processing
635       *          the operation before an alternate authorization identity was
636       *          assigned, or an empty list if no privileges were used or this is
637       *          not included in the log message.
638       */
639      public List<String> getPreAuthorizationUsedPrivileges()
640      {
641        return preAuthZUsedPrivileges;
642      }
643    
644    
645    
646      /**
647       * Retrieves the names of any privileges that would have been required for
648       * processing the operation but that the requester did not have.
649       *
650       * @return  The names of any privileges that would have been required for
651       *          processing the operation but that the requester did not have, or
652       *          an empty list if there were no missing privileges or this is not
653       *          included in the log message.
654       */
655      public List<String> getMissingPrivileges()
656      {
657        return missingPrivileges;
658      }
659    
660    
661    
662      /**
663       * {@inheritDoc}
664       */
665      @Override()
666      public AccessLogMessageType getMessageType()
667      {
668        return AccessLogMessageType.RESULT;
669      }
670    }