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