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