001/* 002 * Copyright 2009-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2009-2024 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2009-2024 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds.logs; 037 038 039 040import java.util.Collections; 041import java.util.LinkedList; 042import java.util.List; 043import java.util.StringTokenizer; 044 045import com.unboundid.ldap.sdk.ResultCode; 046import com.unboundid.util.NotMutable; 047import com.unboundid.util.NotNull; 048import com.unboundid.util.Nullable; 049import com.unboundid.util.ThreadSafety; 050import com.unboundid.util.ThreadSafetyLevel; 051 052 053 054/** 055 * This class provides a data structure that holds information about a log 056 * message that may appear in the Directory Server access log about the result 057 * of an extended operation processed by the Directory Server. 058 * <BR> 059 * <BLOCKQUOTE> 060 * <B>NOTE:</B> This class, and other classes within the 061 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 062 * supported for use against Ping Identity, UnboundID, and 063 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 064 * for proprietary functionality or for external specifications that are not 065 * considered stable or mature enough to be guaranteed to work in an 066 * interoperable way with other types of LDAP servers. 067 * </BLOCKQUOTE> 068 */ 069@NotMutable() 070@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 071public final class ExtendedResultAccessLogMessage 072 extends ExtendedRequestAccessLogMessage 073 implements OperationResultAccessLogMessage 074{ 075 /** 076 * The serial version UID for this serializable class. 077 */ 078 private static final long serialVersionUID = -3980496377400403461L; 079 080 081 082 // Indicates whether the any uncached data was accessed in the course of 083 // processing this operation. 084 @Nullable private final Boolean uncachedDataAccessed; 085 086 // The processing time for the operation. 087 @Nullable private final Double processingTime; 088 089 // The queue time for the operation. 090 @Nullable private final Double queueTime; 091 092 // The list of privileges required for processing the operation that the 093 // requester did not have. 094 @NotNull private final List<String> missingPrivileges; 095 096 // The list of privileges used during the course of processing the operation 097 // before an alternate authorization identity was assigned. 098 @NotNull private final List<String> preAuthZUsedPrivileges; 099 100 // The list of referral URLs for the operation. 101 @NotNull private final List<String> referralURLs; 102 103 // The list of response control OIDs for the operation. 104 @NotNull private final List<String> responseControlOIDs; 105 106 // The list of servers accessed while processing the operation. 107 @NotNull private final List<String> serversAccessed; 108 109 // The list of privileges used during the course of processing the operation. 110 @NotNull private final List<String> usedPrivileges; 111 112 // The number of intermediate response messages returned to the client. 113 @Nullable private final Long intermediateResponsesReturned; 114 115 // The result code for the operation. 116 @Nullable private final ResultCode resultCode; 117 118 // Additional information about the operation result. 119 @Nullable private final String additionalInformation; 120 121 // The name of the client connection policy selected for the client. 122 @Nullable private final String clientConnectionPolicy; 123 124 // The diagnostic message for the operation. 125 @Nullable private final String diagnosticMessage; 126 127 // The intermediate client result for the operation. 128 @Nullable private final String intermediateClientResult; 129 130 // The matched DN for the operation. 131 @Nullable private final String matchedDN; 132 133 // The OID of the extended response. 134 @Nullable private final String responseOID; 135 136 // The port of the backend server to which the request has been forwarded. 137 @Nullable private final Integer targetPort; 138 139 // The address of the backend server to which the request has been forwarded. 140 @Nullable private final String targetHost; 141 142 // The protocol used to forward the request to the backend server. 143 @Nullable private final String targetProtocol; 144 145 146 147 /** 148 * Creates a new extended result access log message from the provided message 149 * string. 150 * 151 * @param s The string to be parsed as an extended result access log 152 * message. 153 * 154 * @throws LogException If the provided string cannot be parsed as a valid 155 * log message. 156 */ 157 public ExtendedResultAccessLogMessage(@NotNull final String s) 158 throws LogException 159 { 160 this(new LogMessage(s)); 161 } 162 163 164 165 /** 166 * Creates a new extended result access log message from the provided log 167 * message. 168 * 169 * @param m The log message to be parsed as an extended result access log 170 * message. 171 */ 172 public ExtendedResultAccessLogMessage(@NotNull final LogMessage m) 173 { 174 super(m); 175 176 diagnosticMessage = getNamedValue("message"); 177 additionalInformation = getNamedValue("additionalInfo"); 178 matchedDN = getNamedValue("matchedDN"); 179 processingTime = getNamedValueAsDouble("etime"); 180 queueTime = getNamedValueAsDouble("qtime"); 181 intermediateClientResult = getNamedValue("from"); 182 responseOID = getNamedValue("responseOID"); 183 targetHost = getNamedValue("targetHost"); 184 targetPort = getNamedValueAsInteger("targetPort"); 185 targetProtocol = getNamedValue("targetProtocol"); 186 clientConnectionPolicy = getNamedValue("clientConnectionPolicy"); 187 188 intermediateResponsesReturned = 189 getNamedValueAsLong("intermediateResponsesReturned"); 190 191 final Integer rcInteger = getNamedValueAsInteger("resultCode"); 192 if (rcInteger == null) 193 { 194 resultCode = null; 195 } 196 else 197 { 198 resultCode = ResultCode.valueOf(rcInteger); 199 } 200 201 final String refStr = getNamedValue("referralURLs"); 202 if ((refStr == null) || refStr.isEmpty()) 203 { 204 referralURLs = Collections.emptyList(); 205 } 206 else 207 { 208 final LinkedList<String> refs = new LinkedList<>(); 209 int startPos = 0; 210 while (true) 211 { 212 final int commaPos = refStr.indexOf(",ldap", startPos); 213 if (commaPos < 0) 214 { 215 refs.add(refStr.substring(startPos)); 216 break; 217 } 218 else 219 { 220 refs.add(refStr.substring(startPos, commaPos)); 221 startPos = commaPos+1; 222 } 223 } 224 referralURLs = Collections.unmodifiableList(refs); 225 } 226 227 final String controlStr = getNamedValue("responseControls"); 228 if (controlStr == null) 229 { 230 responseControlOIDs = Collections.emptyList(); 231 } 232 else 233 { 234 final LinkedList<String> controlList = new LinkedList<>(); 235 final StringTokenizer t = new StringTokenizer(controlStr, ","); 236 while (t.hasMoreTokens()) 237 { 238 controlList.add(t.nextToken()); 239 } 240 responseControlOIDs = Collections.unmodifiableList(controlList); 241 } 242 243 final String serversAccessedStr = getNamedValue("serversAccessed"); 244 if ((serversAccessedStr == null) || serversAccessedStr.isEmpty()) 245 { 246 serversAccessed = Collections.emptyList(); 247 } 248 else 249 { 250 final LinkedList<String> servers = new LinkedList<>(); 251 final StringTokenizer tokenizer = 252 new StringTokenizer(serversAccessedStr, ","); 253 while (tokenizer.hasMoreTokens()) 254 { 255 servers.add(tokenizer.nextToken()); 256 } 257 serversAccessed = Collections.unmodifiableList(servers); 258 } 259 260 uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed"); 261 262 final String usedPrivilegesStr = getNamedValue("usedPrivileges"); 263 if ((usedPrivilegesStr == null) || usedPrivilegesStr.isEmpty()) 264 { 265 usedPrivileges = Collections.emptyList(); 266 } 267 else 268 { 269 final LinkedList<String> privileges = new LinkedList<>(); 270 final StringTokenizer tokenizer = 271 new StringTokenizer(usedPrivilegesStr, ","); 272 while (tokenizer.hasMoreTokens()) 273 { 274 privileges.add(tokenizer.nextToken()); 275 } 276 usedPrivileges = Collections.unmodifiableList(privileges); 277 } 278 279 final String preAuthZUsedPrivilegesStr = 280 getNamedValue("preAuthZUsedPrivileges"); 281 if ((preAuthZUsedPrivilegesStr == null) || 282 preAuthZUsedPrivilegesStr.isEmpty()) 283 { 284 preAuthZUsedPrivileges = Collections.emptyList(); 285 } 286 else 287 { 288 final LinkedList<String> privileges = new LinkedList<>(); 289 final StringTokenizer tokenizer = 290 new StringTokenizer(preAuthZUsedPrivilegesStr, ","); 291 while (tokenizer.hasMoreTokens()) 292 { 293 privileges.add(tokenizer.nextToken()); 294 } 295 preAuthZUsedPrivileges = Collections.unmodifiableList(privileges); 296 } 297 298 final String missingPrivilegesStr = getNamedValue("missingPrivileges"); 299 if ((missingPrivilegesStr == null) || missingPrivilegesStr.isEmpty()) 300 { 301 missingPrivileges = Collections.emptyList(); 302 } 303 else 304 { 305 final LinkedList<String> privileges = new LinkedList<>(); 306 final StringTokenizer tokenizer = 307 new StringTokenizer(missingPrivilegesStr, ","); 308 while (tokenizer.hasMoreTokens()) 309 { 310 privileges.add(tokenizer.nextToken()); 311 } 312 missingPrivileges = Collections.unmodifiableList(privileges); 313 } 314 } 315 316 317 318 /** 319 * Retrieves the result code for the operation. 320 * 321 * @return The result code for the operation, or {@code null} if it is not 322 * included in the log message. 323 */ 324 @Override() 325 @Nullable() 326 public ResultCode getResultCode() 327 { 328 return resultCode; 329 } 330 331 332 333 /** 334 * Retrieves the diagnostic message for the operation. 335 * 336 * @return The diagnostic message for the operation, or {@code null} if it is 337 * not included in the log message. 338 */ 339 @Override() 340 @Nullable() 341 public String getDiagnosticMessage() 342 { 343 return diagnosticMessage; 344 } 345 346 347 348 /** 349 * Retrieves a message with additional information about the result of the 350 * operation. 351 * 352 * @return A message with additional information about the result of the 353 * operation, or {@code null} if it is not included in the log 354 * message. 355 */ 356 @Override() 357 @Nullable() 358 public String getAdditionalInformation() 359 { 360 return additionalInformation; 361 } 362 363 364 365 /** 366 * Retrieves the matched DN for the operation. 367 * 368 * @return The matched DN for the operation, or {@code null} if it is not 369 * included in the log message. 370 */ 371 @Override() 372 @Nullable() 373 public String getMatchedDN() 374 { 375 return matchedDN; 376 } 377 378 379 380 /** 381 * Retrieves the list of referral URLs for the operation. 382 * 383 * @return The list of referral URLs for the operation, or an empty list if 384 * it is not included in the log message. 385 */ 386 @Override() 387 @NotNull() 388 public List<String> getReferralURLs() 389 { 390 return referralURLs; 391 } 392 393 394 395 /** 396 * Retrieves a list of the additional servers that were accessed in the course 397 * of processing the operation. For example, if the access log message is 398 * from a Directory Proxy Server instance, then this may contain a list of the 399 * backend servers used to process the operation. 400 * 401 * @return A list of the additional servers that were accessed in the course 402 * of processing the operation, or an empty list if it is not 403 * included in the log message. 404 */ 405 @Override() 406 @NotNull() 407 public List<String> getServersAccessed() 408 { 409 return serversAccessed; 410 } 411 412 413 414 /** 415 * Indicates whether the server accessed any uncached data in the course of 416 * processing the operation. 417 * 418 * @return {@code true} if the server was known to access uncached data in 419 * the course of processing the operation, {@code false} if the 420 * server was known not to access uncached data, or {@code null} if 421 * it is not included in the log message (and the server likely did 422 * not access uncached data). 423 */ 424 @Nullable() 425 public Boolean getUncachedDataAccessed() 426 { 427 return uncachedDataAccessed; 428 } 429 430 431 432 /** 433 * Retrieves the number of intermediate response messages returned in the 434 * course of processing the operation. 435 * 436 * @return The number of intermediate response messages returned to the 437 * client in the course of processing the operation, or {@code null} 438 * if it is not included in the log message. 439 */ 440 @Override() 441 @Nullable() 442 public Long getIntermediateResponsesReturned() 443 { 444 return intermediateResponsesReturned; 445 } 446 447 448 449 /** 450 * Retrieves the length of time in milliseconds required to process the 451 * operation. 452 * 453 * @return The length of time in milliseconds required to process the 454 * operation, or {@code null} if it is not included in the log 455 * message. 456 */ 457 @Override() 458 @Nullable() 459 public Double getProcessingTimeMillis() 460 { 461 return processingTime; 462 } 463 464 465 466 /** 467 * Retrieves the length of time in milliseconds the operation was required to 468 * wait on the work queue. 469 * 470 * @return The length of time in milliseconds the operation was required to 471 * wait on the work queue, or {@code null} if it is not included in 472 * the log message. 473 */ 474 @Override() 475 @Nullable() 476 public Double getQueueTimeMillis() 477 { 478 return queueTime; 479 } 480 481 482 483 /** 484 * Retrieves the OIDs of any response controls contained in the log message. 485 * 486 * @return The OIDs of any response controls contained in the log message, or 487 * an empty list if it is not included in the log message. 488 */ 489 @Override() 490 @NotNull() 491 public List<String> getResponseControlOIDs() 492 { 493 return responseControlOIDs; 494 } 495 496 497 498 /** 499 * Retrieves the content of the intermediate client result for the 500 * operation. 501 * 502 * @return The content of the intermediate client result for the operation, 503 * or {@code null} if it is not included in the log message. 504 */ 505 @Override() 506 @Nullable() 507 public String getIntermediateClientResult() 508 { 509 return intermediateClientResult; 510 } 511 512 513 514 /** 515 * Retrieves the OID for the extended response. 516 * 517 * @return The OID for the extended response, or {@code null} if it is not 518 * included in the log message. 519 */ 520 @Nullable() 521 public String getResponseOID() 522 { 523 return responseOID; 524 } 525 526 527 528 /** 529 * Retrieves the address of the backend server to which the request has been 530 * forwarded. 531 * 532 * @return The address 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 @Nullable() 537 public String getTargetHost() 538 { 539 return targetHost; 540 } 541 542 543 544 /** 545 * Retrieves the port of the backend server to which the request has been 546 * forwarded. 547 * 548 * @return The port of the backend server to which the request has been 549 * forwarded, or {@code null} if it is not included in the log 550 * message. 551 */ 552 @Nullable() 553 public Integer getTargetPort() 554 { 555 return targetPort; 556 } 557 558 559 560 /** 561 * Retrieves the protocol used to forward the request to the backend server. 562 * 563 * @return The protocol used to forward the request to the backend server, or 564 * {@code null} if it is not included in the log message. 565 */ 566 @Nullable() 567 public String getTargetProtocol() 568 { 569 return targetProtocol; 570 } 571 572 573 574 /** 575 * Retrieves the name of the client connection policy that was selected for 576 * the client connection. 577 * 578 * @return The name of the client connection policy that was selected for the 579 * client connection, or {@code null} if it is not included in the 580 * log message. 581 */ 582 @Nullable() 583 public String getClientConnectionPolicy() 584 { 585 return clientConnectionPolicy; 586 } 587 588 589 590 /** 591 * Retrieves the names of any privileges used during the course of processing 592 * the operation. 593 * 594 * @return The names of any privileges used during the course of processing 595 * the operation, or an empty list if no privileges were used or this 596 * is not included in the log message. 597 */ 598 @NotNull() 599 public List<String> getUsedPrivileges() 600 { 601 return usedPrivileges; 602 } 603 604 605 606 /** 607 * Retrieves the names of any privileges used during the course of processing 608 * the operation before an alternate authorization identity was assigned. 609 * 610 * @return The names of any privileges used during the course of processing 611 * the operation before an alternate authorization identity was 612 * assigned, or an empty list if no privileges were used or this is 613 * not included in the log message. 614 */ 615 @NotNull() 616 public List<String> getPreAuthorizationUsedPrivileges() 617 { 618 return preAuthZUsedPrivileges; 619 } 620 621 622 623 /** 624 * Retrieves the names of any privileges that would have been required for 625 * processing the operation but that the requester did not have. 626 * 627 * @return The names of any privileges that would have been required for 628 * processing the operation but that the requester did not have, or 629 * an empty list if there were no missing privileges or this is not 630 * included in the log message. 631 */ 632 @NotNull() 633 public List<String> getMissingPrivileges() 634 { 635 return missingPrivileges; 636 } 637 638 639 640 /** 641 * {@inheritDoc} 642 */ 643 @Override() 644 @NotNull() 645 public AccessLogMessageType getMessageType() 646 { 647 return AccessLogMessageType.RESULT; 648 } 649}