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