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