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