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 }