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