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