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