001/* 002 * Copyright 2009-2018 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2018 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.ldap.sdk.unboundidds.controls.AssuredReplicationLocalLevel; 032import com.unboundid.ldap.sdk.unboundidds.controls. 033 AssuredReplicationRemoteLevel; 034import com.unboundid.util.NotExtensible; 035import com.unboundid.util.NotMutable; 036import com.unboundid.util.ThreadSafety; 037import com.unboundid.util.ThreadSafetyLevel; 038 039 040 041/** 042 * This class provides a data structure that holds information about a log 043 * message that may appear in the Directory Server access log about the result 044 * of an add operation processed by the Directory Server. 045 * <BR> 046 * <BLOCKQUOTE> 047 * <B>NOTE:</B> This class, and other classes within the 048 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 049 * supported for use against Ping Identity, UnboundID, and 050 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 051 * for proprietary functionality or for external specifications that are not 052 * considered stable or mature enough to be guaranteed to work in an 053 * interoperable way with other types of LDAP servers. 054 * </BLOCKQUOTE> 055 */ 056@NotExtensible() 057@NotMutable() 058@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 059public class AddResultAccessLogMessage 060 extends AddRequestAccessLogMessage 061 implements OperationResultAccessLogMessage 062{ 063 /** 064 * The serial version UID for this serializable class. 065 */ 066 private static final long serialVersionUID = -6660463102516326216L; 067 068 069 070 // The assured replication level to use for local servers. 071 private final AssuredReplicationLocalLevel assuredReplicationLocalLevel; 072 073 // The assured replication level to use for remote servers. 074 private final AssuredReplicationRemoteLevel assuredReplicationRemoteLevel; 075 076 // Indicates whether the response was known to be delayed by replication 077 // assurance processing. 078 private final Boolean responseDelayedByAssurance; 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 port of the backend server to which the request has been forwarded. 091 private final Integer targetPort; 092 093 // The list of indexes for which keys near the index entry limit were accessed 094 // while processing the operation. 095 private final List<String> indexesWithKeysAccessedNearEntryLimit; 096 097 // The list of indexes for which keys over the index entry limit were accessed 098 // while processing the operation. 099 private final List<String> indexesWithKeysAccessedOverEntryLimit; 100 101 // The list of privileges required for processing the operation that the 102 // requester did not have. 103 private final List<String> missingPrivileges; 104 105 // The list of privileges used during the course of processing the operation 106 // before an alternate authorization identity was assigned. 107 private final List<String> preAuthZUsedPrivileges; 108 109 // The list of referral URLs for the operation. 110 private final List<String> referralURLs; 111 112 // The list of response control OIDs for the operation. 113 private final List<String> responseControlOIDs; 114 115 // The list of servers accessed while processing the operation. 116 private final List<String> serversAccessed; 117 118 // The list of privileges used during the course of processing the operation. 119 private final List<String> usedPrivileges; 120 121 // The assured replication timeout, in milliseconds. 122 private final Long assuredReplicationTimeoutMillis; 123 124 // The number of intermediate response messages returned to the client. 125 private final Long intermediateResponsesReturned; 126 127 // The result code for the operation. 128 private final ResultCode resultCode; 129 130 // Additional information about the operation result. 131 private final String additionalInformation; 132 133 // The alternate authorization DN for the operation. 134 private final String authzDN; 135 136 // The diagnostic message for the operation. 137 private final String diagnosticMessage; 138 139 // The intermediate client result for the operation. 140 private final String intermediateClientResult; 141 142 // The matched DN for the operation. 143 private final String matchedDN; 144 145 // The replication change ID for the operation. 146 private final String replicationChangeID; 147 148 // The address of the backend server to which the request has been forwarded. 149 private final String targetHost; 150 151 // The protocol used to forward the request to the backend server. 152 private final String targetProtocol; 153 154 // The DN of the soft-deleted entry from which the resulting entry was 155 // undeleted. 156 private final String undeleteFromDN; 157 158 159 160 /** 161 * Creates a new add result access log message from the provided message 162 * string. 163 * 164 * @param s The string to be parsed as an add result access log message. 165 * 166 * @throws LogException If the provided string cannot be parsed as a valid 167 * log message. 168 */ 169 public AddResultAccessLogMessage(final String s) 170 throws LogException 171 { 172 this(new LogMessage(s)); 173 } 174 175 176 177 /** 178 * Creates a new add result access log message from the provided message 179 * string. 180 * 181 * @param m The log message to be parsed as an add result access log 182 * message. 183 */ 184 public AddResultAccessLogMessage(final LogMessage m) 185 { 186 super(m); 187 188 diagnosticMessage = getNamedValue("message"); 189 additionalInformation = getNamedValue("additionalInfo"); 190 matchedDN = getNamedValue("matchedDN"); 191 processingTime = getNamedValueAsDouble("etime"); 192 queueTime = getNamedValueAsDouble("qtime"); 193 intermediateClientResult = getNamedValue("from"); 194 authzDN = getNamedValue("authzDN"); 195 replicationChangeID = getNamedValue("replicationChangeID"); 196 targetHost = getNamedValue("targetHost"); 197 targetPort = getNamedValueAsInteger("targetPort"); 198 targetProtocol = getNamedValue("targetProtocol"); 199 undeleteFromDN = getNamedValue("undeleteFromDN"); 200 201 intermediateResponsesReturned = 202 getNamedValueAsLong("intermediateResponsesReturned"); 203 204 final Integer rcInteger = getNamedValueAsInteger("resultCode"); 205 if (rcInteger == null) 206 { 207 resultCode = null; 208 } 209 else 210 { 211 resultCode = ResultCode.valueOf(rcInteger); 212 } 213 214 final String refStr = getNamedValue("referralURLs"); 215 if ((refStr == null) || refStr.isEmpty()) 216 { 217 referralURLs = Collections.emptyList(); 218 } 219 else 220 { 221 final LinkedList<String> refs = new LinkedList<>(); 222 int startPos = 0; 223 while (true) 224 { 225 final int commaPos = refStr.indexOf(",ldap", startPos); 226 if (commaPos < 0) 227 { 228 refs.add(refStr.substring(startPos)); 229 break; 230 } 231 else 232 { 233 refs.add(refStr.substring(startPos, commaPos)); 234 startPos = commaPos+1; 235 } 236 } 237 referralURLs = Collections.unmodifiableList(refs); 238 } 239 240 final String controlStr = getNamedValue("responseControls"); 241 if (controlStr == null) 242 { 243 responseControlOIDs = Collections.emptyList(); 244 } 245 else 246 { 247 final LinkedList<String> controlList = new LinkedList<>(); 248 final StringTokenizer t = new StringTokenizer(controlStr, ","); 249 while (t.hasMoreTokens()) 250 { 251 controlList.add(t.nextToken()); 252 } 253 responseControlOIDs = Collections.unmodifiableList(controlList); 254 } 255 256 final String serversAccessedStr = getNamedValue("serversAccessed"); 257 if ((serversAccessedStr == null) || serversAccessedStr.isEmpty()) 258 { 259 serversAccessed = Collections.emptyList(); 260 } 261 else 262 { 263 final LinkedList<String> servers = new LinkedList<>(); 264 final StringTokenizer tokenizer = 265 new StringTokenizer(serversAccessedStr, ","); 266 while (tokenizer.hasMoreTokens()) 267 { 268 servers.add(tokenizer.nextToken()); 269 } 270 serversAccessed = Collections.unmodifiableList(servers); 271 } 272 273 uncachedDataAccessed = getNamedValueAsBoolean("uncachedDataAccessed"); 274 275 276 final String localLevelStr = getNamedValue("localAssuranceLevel"); 277 if (localLevelStr == null) 278 { 279 assuredReplicationLocalLevel = null; 280 } 281 else 282 { 283 assuredReplicationLocalLevel = 284 AssuredReplicationLocalLevel.valueOf(localLevelStr); 285 } 286 287 final String remoteLevelStr = getNamedValue("remoteAssuranceLevel"); 288 if (remoteLevelStr == null) 289 { 290 assuredReplicationRemoteLevel = null; 291 } 292 else 293 { 294 assuredReplicationRemoteLevel = 295 AssuredReplicationRemoteLevel.valueOf(remoteLevelStr); 296 } 297 298 assuredReplicationTimeoutMillis = 299 getNamedValueAsLong("assuranceTimeoutMillis"); 300 responseDelayedByAssurance = 301 getNamedValueAsBoolean("responseDelayedByAssurance"); 302 303 final String usedPrivilegesStr = getNamedValue("usedPrivileges"); 304 if ((usedPrivilegesStr == null) || usedPrivilegesStr.isEmpty()) 305 { 306 usedPrivileges = Collections.emptyList(); 307 } 308 else 309 { 310 final LinkedList<String> privileges = new LinkedList<>(); 311 final StringTokenizer tokenizer = 312 new StringTokenizer(usedPrivilegesStr, ","); 313 while (tokenizer.hasMoreTokens()) 314 { 315 privileges.add(tokenizer.nextToken()); 316 } 317 usedPrivileges = Collections.unmodifiableList(privileges); 318 } 319 320 final String preAuthZUsedPrivilegesStr = 321 getNamedValue("preAuthZUsedPrivileges"); 322 if ((preAuthZUsedPrivilegesStr == null) || 323 preAuthZUsedPrivilegesStr.isEmpty()) 324 { 325 preAuthZUsedPrivileges = Collections.emptyList(); 326 } 327 else 328 { 329 final LinkedList<String> privileges = new LinkedList<>(); 330 final StringTokenizer tokenizer = 331 new StringTokenizer(preAuthZUsedPrivilegesStr, ","); 332 while (tokenizer.hasMoreTokens()) 333 { 334 privileges.add(tokenizer.nextToken()); 335 } 336 preAuthZUsedPrivileges = Collections.unmodifiableList(privileges); 337 } 338 339 final String missingPrivilegesStr = getNamedValue("missingPrivileges"); 340 if ((missingPrivilegesStr == null) || missingPrivilegesStr.isEmpty()) 341 { 342 missingPrivileges = Collections.emptyList(); 343 } 344 else 345 { 346 final LinkedList<String> privileges = new LinkedList<>(); 347 final StringTokenizer tokenizer = 348 new StringTokenizer(missingPrivilegesStr, ","); 349 while (tokenizer.hasMoreTokens()) 350 { 351 privileges.add(tokenizer.nextToken()); 352 } 353 missingPrivileges = Collections.unmodifiableList(privileges); 354 } 355 356 final String indexesNearLimitStr = 357 getNamedValue("indexesWithKeysAccessedNearEntryLimit"); 358 if ((indexesNearLimitStr == null) || indexesNearLimitStr.isEmpty()) 359 { 360 indexesWithKeysAccessedNearEntryLimit = Collections.emptyList(); 361 } 362 else 363 { 364 final LinkedList<String> indexes = new LinkedList<>(); 365 final StringTokenizer tokenizer = 366 new StringTokenizer(indexesNearLimitStr, ","); 367 while (tokenizer.hasMoreTokens()) 368 { 369 indexes.add(tokenizer.nextToken()); 370 } 371 indexesWithKeysAccessedNearEntryLimit = 372 Collections.unmodifiableList(indexes); 373 } 374 375 final String indexesOverLimitStr = 376 getNamedValue("indexesWithKeysAccessedExceedingEntryLimit"); 377 if ((indexesOverLimitStr == null) || indexesOverLimitStr.isEmpty()) 378 { 379 indexesWithKeysAccessedOverEntryLimit = Collections.emptyList(); 380 } 381 else 382 { 383 final LinkedList<String> indexes = new LinkedList<>(); 384 final StringTokenizer tokenizer = 385 new StringTokenizer(indexesOverLimitStr, ","); 386 while (tokenizer.hasMoreTokens()) 387 { 388 indexes.add(tokenizer.nextToken()); 389 } 390 indexesWithKeysAccessedOverEntryLimit = 391 Collections.unmodifiableList(indexes); 392 } 393 } 394 395 396 397 /** 398 * Retrieves the result code for the operation. 399 * 400 * @return The result code for the operation, or {@code null} if it is not 401 * included in the log message. 402 */ 403 @Override() 404 public ResultCode getResultCode() 405 { 406 return resultCode; 407 } 408 409 410 411 /** 412 * Retrieves the diagnostic message for the operation. 413 * 414 * @return The diagnostic message for the operation, or {@code null} if it is 415 * not included in the log message. 416 */ 417 @Override() 418 public String getDiagnosticMessage() 419 { 420 return diagnosticMessage; 421 } 422 423 424 425 /** 426 * Retrieves a message with additional information about the result of the 427 * operation. 428 * 429 * @return A message with additional information about the result of the 430 * operation, or {@code null} if it is not included in the log 431 * message. 432 */ 433 @Override() 434 public String getAdditionalInformation() 435 { 436 return additionalInformation; 437 } 438 439 440 441 /** 442 * Retrieves the matched DN for the operation. 443 * 444 * @return The matched DN for the operation, or {@code null} if it is not 445 * included in the log message. 446 */ 447 @Override() 448 public String getMatchedDN() 449 { 450 return matchedDN; 451 } 452 453 454 455 /** 456 * Retrieves the list of referral URLs for the operation. 457 * 458 * @return The list of referral URLs for the operation, or an empty list if 459 * it is not included in the log message. 460 */ 461 @Override() 462 public List<String> getReferralURLs() 463 { 464 return referralURLs; 465 } 466 467 468 469 /** 470 * Retrieves the number of intermediate response messages returned in the 471 * course of processing the operation. 472 * 473 * @return The number of intermediate response messages returned to the 474 * client in the course of processing the operation, or {@code null} 475 * if it is not included in the log message. 476 */ 477 @Override() 478 public Long getIntermediateResponsesReturned() 479 { 480 return intermediateResponsesReturned; 481 } 482 483 484 485 /** 486 * Retrieves the length of time in milliseconds required to process the 487 * operation. 488 * 489 * @return The length of time in milliseconds required to process the 490 * operation, or {@code null} if it is not included in the log 491 * message. 492 */ 493 @Override() 494 public Double getProcessingTimeMillis() 495 { 496 return processingTime; 497 } 498 499 500 501 /** 502 * Retrieves the length of time in milliseconds the operation was required to 503 * wait on the work queue. 504 * 505 * @return The length of time in milliseconds the operation was required to 506 * wait on the work queue, or {@code null} if it is not included in 507 * the log message. 508 */ 509 @Override() 510 public Double getQueueTimeMillis() 511 { 512 return queueTime; 513 } 514 515 516 517 /** 518 * Retrieves the OIDs of any response controls contained in the log message. 519 * 520 * @return The OIDs of any response controls contained in the log message, or 521 * an empty list if it is not included in the log message. 522 */ 523 @Override() 524 public List<String> getResponseControlOIDs() 525 { 526 return responseControlOIDs; 527 } 528 529 530 531 /** 532 * Retrieves a list of the additional servers that were accessed in the course 533 * of processing the operation. For example, if the access log message is 534 * from a Directory Proxy Server instance, then this may contain a list of the 535 * backend servers used to process the operation. 536 * 537 * @return A list of the additional servers that were accessed in the course 538 * of processing the operation, or an empty list if it is not 539 * included in the log message. 540 */ 541 @Override() 542 public List<String> getServersAccessed() 543 { 544 return serversAccessed; 545 } 546 547 548 549 /** 550 * Indicates whether the server accessed any uncached data in the course of 551 * processing the operation. 552 * 553 * @return {@code true} if the server was known to access uncached data in 554 * the course of processing the operation, {@code false} if the 555 * server was known not to access uncached data, or {@code null} if 556 * it is not included in the log message (and the server likely did 557 * not access uncached data). 558 */ 559 public Boolean getUncachedDataAccessed() 560 { 561 return uncachedDataAccessed; 562 } 563 564 565 566 /** 567 * Retrieves the content of the intermediate client result for the 568 * operation. 569 * 570 * @return The content of the intermediate client result for the operation, 571 * or {@code null} if it is not included in the log message. 572 */ 573 @Override() 574 public String getIntermediateClientResult() 575 { 576 return intermediateClientResult; 577 } 578 579 580 581 /** 582 * Retrieves the alternate authorization DN for the operation. 583 * 584 * @return The alternate authorization DN for the operation, or {@code null} 585 * if it is not included in the log message. 586 */ 587 public String getAlternateAuthorizationDN() 588 { 589 return authzDN; 590 } 591 592 593 594 /** 595 * Retrieves the replication change ID for the operation, if available. 596 * 597 * @return The replication change ID for the operation, or {@code null} if it 598 * is not included in the log message. 599 */ 600 public String getReplicationChangeID() 601 { 602 return replicationChangeID; 603 } 604 605 606 607 /** 608 * Retrieves the address of the backend server to which the request has been 609 * forwarded. 610 * 611 * @return The address of the backend server to which the request has been 612 * forwarded, or {@code null} if it is not included in the log 613 * message. 614 */ 615 public String getTargetHost() 616 { 617 return targetHost; 618 } 619 620 621 622 /** 623 * Retrieves the port of the backend server to which the request has been 624 * forwarded. 625 * 626 * @return The port of the backend server to which the request has been 627 * forwarded, or {@code null} if it is not included in the log 628 * message. 629 */ 630 public Integer getTargetPort() 631 { 632 return targetPort; 633 } 634 635 636 637 /** 638 * Retrieves the protocol used to forward the request to the backend server. 639 * 640 * @return The protocol used to forward the request to the backend server, or 641 * {@code null} if it is not included in the log message. 642 */ 643 public String getTargetProtocol() 644 { 645 return targetProtocol; 646 } 647 648 649 650 /** 651 * Retrieves the DN of the soft-deleted entry from which the contents of the 652 * added entry were obtained, if it was an undelete rather than a normal add. 653 * 654 * @return The DN of the soft-deleted entry from which the contents of the 655 * added entry were obtained, or {@code null} if it is not included 656 * in the log message (e.g., because the operation was a normal add 657 * rather than an undelete). 658 */ 659 public String getUndeleteFromDN() 660 { 661 return undeleteFromDN; 662 } 663 664 665 666 /** 667 * Retrieves the local level that will be used for assured replication 668 * processing, if available. 669 * 670 * @return The local level that will be used for assured replication 671 * processing, or {@code null} if this is not included in the log 672 * message (e.g., because assured replication will not be performed 673 * for the operation). 674 */ 675 public AssuredReplicationLocalLevel getAssuredReplicationLocalLevel() 676 { 677 return assuredReplicationLocalLevel; 678 } 679 680 681 682 /** 683 * Retrieves the remote level that will be used for assured replication 684 * processing, if available. 685 * 686 * @return The remote level that will be used for assured replication 687 * processing, or {@code null} if this is not included in the log 688 * message (e.g., because assured replication will not be performed 689 * for the operation). 690 */ 691 public AssuredReplicationRemoteLevel getAssuredReplicationRemoteLevel() 692 { 693 return assuredReplicationRemoteLevel; 694 } 695 696 697 698 /** 699 * Retrieves the maximum length of time in milliseconds that the server will 700 * delay the response to the client while waiting for the replication 701 * assurance requirement to be satisfied. 702 * 703 * @return The maximum length of time in milliseconds that the server will 704 * delay the response to the client while waiting for the replication 705 * assurance requirement to be satisfied, or {@code null} if this is 706 * not included in the log message (e.g., because assured replication 707 * will not be performed for the operation). 708 */ 709 public Long getAssuredReplicationTimeoutMillis() 710 { 711 return assuredReplicationTimeoutMillis; 712 } 713 714 715 716 /** 717 * Indicates whether the operation response to the client will be delayed 718 * until replication assurance has been satisfied or the timeout has occurred. 719 * 720 * @return {@code true} if the operation response to the client will be 721 * delayed until replication assurance has been satisfied, 722 * {@code false} if the response will not be delayed by assurance 723 * processing, or {@code null} if this was not included in the 724 * log message (e.g., because assured replication will not be 725 * performed for the operation) 726 */ 727 public Boolean getResponseDelayedByAssurance() 728 { 729 return responseDelayedByAssurance; 730 } 731 732 733 734 /** 735 * Retrieves the names of any privileges used during the course of processing 736 * the operation. 737 * 738 * @return The names of any privileges used during the course of processing 739 * the operation, or an empty list if no privileges were used or this 740 * is not included in the log message. 741 */ 742 public List<String> getUsedPrivileges() 743 { 744 return usedPrivileges; 745 } 746 747 748 749 /** 750 * Retrieves the names of any privileges used during the course of processing 751 * the operation before an alternate authorization identity was assigned. 752 * 753 * @return The names of any privileges used during the course of processing 754 * the operation before an alternate authorization identity was 755 * assigned, or an empty list if no privileges were used or this is 756 * not included in the log message. 757 */ 758 public List<String> getPreAuthorizationUsedPrivileges() 759 { 760 return preAuthZUsedPrivileges; 761 } 762 763 764 765 /** 766 * Retrieves the names of any privileges that would have been required for 767 * processing the operation but that the requester did not have. 768 * 769 * @return The names of any privileges that would have been required for 770 * processing the operation but that the requester did not have, or 771 * an empty list if there were no missing privileges or this is not 772 * included in the log message. 773 */ 774 public List<String> getMissingPrivileges() 775 { 776 return missingPrivileges; 777 } 778 779 780 781 /** 782 * Retrieves the names of any indexes for which one or more keys near 783 * (typically, within 80% of) the index entry limit were accessed while 784 * processing the operation. 785 * 786 * @return The names of any indexes for which one or more keys near the index 787 * entry limit were accessed while processing the operation, or an 788 * empty list if no such index keys were accessed, or if this is not 789 * included in the log message. 790 */ 791 public List<String> getIndexesWithKeysAccessedNearEntryLimit() 792 { 793 return indexesWithKeysAccessedNearEntryLimit; 794 } 795 796 797 798 /** 799 * Retrieves the names of any indexes for which one or more keys over the 800 * index entry limit were accessed while processing the operation. 801 * 802 * @return The names of any indexes for which one or more keys over the index 803 * entry limit were accessed while processing the operation, or an 804 * empty list if no such index keys were accessed, or if this is not 805 * included in the log message. 806 */ 807 public List<String> getIndexesWithKeysAccessedOverEntryLimit() 808 { 809 return indexesWithKeysAccessedOverEntryLimit; 810 } 811 812 813 814 /** 815 * {@inheritDoc} 816 */ 817 @Override() 818 public AccessLogMessageType getMessageType() 819 { 820 return AccessLogMessageType.RESULT; 821 } 822}