001/* 002 * Copyright 2010-2024 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2010-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) 2010-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.extensions; 037 038 039 040import java.util.ArrayList; 041import java.util.Collections; 042import java.util.EnumSet; 043import java.util.Iterator; 044import java.util.List; 045import java.util.Set; 046 047import com.unboundid.asn1.ASN1Boolean; 048import com.unboundid.asn1.ASN1Element; 049import com.unboundid.asn1.ASN1Enumerated; 050import com.unboundid.asn1.ASN1Integer; 051import com.unboundid.asn1.ASN1Long; 052import com.unboundid.asn1.ASN1OctetString; 053import com.unboundid.asn1.ASN1Sequence; 054import com.unboundid.asn1.ASN1Set; 055import com.unboundid.ldap.sdk.ChangeType; 056import com.unboundid.ldap.sdk.Control; 057import com.unboundid.ldap.sdk.ExtendedRequest; 058import com.unboundid.ldap.sdk.ExtendedResult; 059import com.unboundid.ldap.sdk.IntermediateResponseListener; 060import com.unboundid.ldap.sdk.LDAPConnection; 061import com.unboundid.ldap.sdk.LDAPException; 062import com.unboundid.ldap.sdk.ResultCode; 063import com.unboundid.util.Debug; 064import com.unboundid.util.NotMutable; 065import com.unboundid.util.NotNull; 066import com.unboundid.util.Nullable; 067import com.unboundid.util.StaticUtils; 068import com.unboundid.util.ThreadSafety; 069import com.unboundid.util.ThreadSafetyLevel; 070import com.unboundid.util.Validator; 071 072import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 073 074 075 076/** 077 * This class provides an implementation of an extended request which may be 078 * used to retrieve a batch of changes from a Directory Server. 079 * <BR> 080 * <BLOCKQUOTE> 081 * <B>NOTE:</B> This class, and other classes within the 082 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 083 * supported for use against Ping Identity, UnboundID, and 084 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 085 * for proprietary functionality or for external specifications that are not 086 * considered stable or mature enough to be guaranteed to work in an 087 * interoperable way with other types of LDAP servers. 088 * </BLOCKQUOTE> 089 * <BR> 090 * The changelog batch request value is encoded as follows: 091 * <PRE> 092 * ChangelogBatchRequest ::= SEQUENCE { 093 * startingPoint CHOICE { 094 * resumeWithToken [0] OCTET STRING, 095 * resumeWithCSN [1] OCTET STRING, 096 * beginningOfChangelog [2] NULL, 097 * endOfChangelog [3] NULL, 098 * changeTime [4] OCTET STRING, 099 * ... }, 100 * maxChanges INTEGER (0 .. maxInt), 101 * maxTimeMillis [0] INTEGER DEFAULT 0, 102 * waitForMaxChanges [1] BOOLEAN DEFAULT FALSE, 103 * includeBase [2] SEQUENCE OF LDAPDN OPTIONAL, 104 * excludeBase [3] SEQUENCE OF LDAPDN OPTIONAL, 105 * changeTypes [4] SET OF ENUMERATED { 106 * add (0), 107 * delete (1), 108 * modify (2), 109 * modifyDN (3) } OPTIONAL, 110 * continueOnMissingChanges [5] BOOLEAN DEFAULT FALSE, 111 * pareEntriesForUserDN [6] LDAPDN OPTIONAL, 112 * changeSelectionCriteria [7] CHOICE { 113 * anyAttributes [1] SEQUENCE OF LDAPString, 114 * allAttributes [2] SEQUENCE OF LDAPString, 115 * ignoreAttributes [3] SEQUENCE { 116 * ignoreAttributes SEQUENCE OF LDAPString 117 * ignoreOperationalAttributes BOOLEAN, 118 * ... }, 119 * notificationDestination [4] OCTET STRING, 120 * ... } OPTIONAL, 121 * includeSoftDeletedEntryMods [8] BOOLEAN DEFAULT FALSE, 122 * includeSoftDeletedEntryDeletes [9] BOOLEAN DEFAULT FALSE, 123 * ... } 124 * </PRE> 125 * <BR><BR> 126 * <H2>Example</H2> 127 * The following example demonstrates the use of the get changelog batch to 128 * iterate across all entries in the changelog. It will operate in an infinite 129 * loop, starting at the beginning of the changelog and then reading 1000 130 * entries at a time until all entries have been read. Once the end of the 131 * changelog has been reached, it will continue looking for changes, waiting for 132 * up to 5 seconds for new changes to arrive. 133 * <PRE> 134 * ChangelogBatchStartingPoint startingPoint = 135 * new BeginningOfChangelogStartingPoint(); 136 * while (true) 137 * { 138 * GetChangelogBatchExtendedRequest request = 139 * new GetChangelogBatchExtendedRequest(startingPoint, 1000, 5000L); 140 * 141 * GetChangelogBatchExtendedResult result = 142 * (GetChangelogBatchExtendedResult) 143 * connection.processExtendedOperation(request); 144 * List<ChangelogEntryIntermediateResponse> changelogEntries = 145 * result.getChangelogEntries(); 146 * 147 * startingPoint = new ResumeWithTokenStartingPoint(result.getResumeToken()); 148 * } 149 * </PRE> 150 */ 151@NotMutable() 152@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 153public final class GetChangelogBatchExtendedRequest 154 extends ExtendedRequest 155{ 156 /** 157 * The OID (1.3.6.1.4.1.30221.2.6.10) for the get changelog batch extended 158 * request. 159 */ 160 @NotNull public static final String GET_CHANGELOG_BATCH_REQUEST_OID = 161 "1.3.6.1.4.1.30221.2.6.10"; 162 163 164 165 /** 166 * The BER type for the maxTimeMillis element. 167 */ 168 private static final byte TYPE_MAX_TIME = (byte) 0x80; 169 170 171 172 /** 173 * The BER type for the returnOnAvailableChanges element. 174 */ 175 private static final byte TYPE_WAIT_FOR_MAX_CHANGES = (byte) 0x81; 176 177 178 179 /** 180 * The BER type for the includeBase element. 181 */ 182 private static final byte TYPE_INCLUDE_BASE = (byte) 0xA2; 183 184 185 186 /** 187 * The BER type for the excludeBase element. 188 */ 189 private static final byte TYPE_EXCLUDE_BASE = (byte) 0xA3; 190 191 192 193 /** 194 * The BER type for the changeTypes element. 195 */ 196 private static final byte TYPE_CHANGE_TYPES = (byte) 0xA4; 197 198 199 200 /** 201 * The BER type for the continueOnMissingChanges element. 202 */ 203 private static final byte TYPE_CONTINUE_ON_MISSING_CHANGES = (byte) 0x85; 204 205 206 207 /** 208 * The BER type for the pareEntriesForUserDN element. 209 */ 210 private static final byte TYPE_PARE_ENTRIES_FOR_USER_DN = (byte) 0x86; 211 212 213 214 /** 215 * The BER type for the includeSoftDeletedEntryMods element. 216 */ 217 private static final byte TYPE_INCLUDE_SOFT_DELETED_ENTRY_MODS = (byte) 0x88; 218 219 220 221 /** 222 * The BER type for the includeSoftDeletedEntryDeletes element. 223 */ 224 private static final byte TYPE_INCLUDE_SOFT_DELETED_ENTRY_DELETES = 225 (byte) 0x89; 226 227 228 229 /** 230 * The value for a change type of add. 231 */ 232 private static final int CHANGE_TYPE_ADD = 0; 233 234 235 236 /** 237 * The value for a change type of delete. 238 */ 239 private static final int CHANGE_TYPE_DELETE = 1; 240 241 242 243 /** 244 * The value for a change type of modify. 245 */ 246 private static final int CHANGE_TYPE_MODIFY = 2; 247 248 249 250 /** 251 * The value for a change type of modify DN. 252 */ 253 private static final int CHANGE_TYPE_MODIFY_DN = 3; 254 255 256 257 /** 258 * The serial version UID for this serializable class. 259 */ 260 private static final long serialVersionUID = 3270898150012821635L; 261 262 263 264 // Indicates whether to attempt to return changes even if the start point 265 // references changes which may have already been purged from the changelog. 266 private final boolean continueOnMissingChanges; 267 268 // Indicates whether deletes to soft-deleted entries should be included in the 269 // result set. 270 private final boolean includeSoftDeletedEntryDeletes; 271 272 // Indicates whether modifications of soft-deleted entries should be included 273 // in the result set. 274 private final boolean includeSoftDeletedEntryMods; 275 276 // Indicates whether the server should wait for up to the specified time limit 277 // for up to the the maximum number of changes to be returned, or whether it 278 // should return as soon as there are any results available. 279 private final boolean waitForMaxChanges; 280 281 // The change selection criteria for the request, if any. 282 @Nullable private final ChangelogBatchChangeSelectionCriteria 283 changeSelectionCriteria; 284 285 // The starting point for the batch of changes to retrieve. 286 @NotNull private final ChangelogBatchStartingPoint startingPoint; 287 288 // The entry listener for this request. 289 @Nullable private final ChangelogEntryListener entryListener; 290 291 // The maximum number of changes to retrieve in the batch. 292 private final int maxChanges; 293 294 // The list of base DNs for entries to exclude from the results. 295 @NotNull private final List<String> excludeBaseDNs; 296 297 // The list of base DNs for entries to include in the results. 298 @NotNull private final List<String> includeBaseDNs; 299 300 // The maximum length of time in milliseconds to wait for changes to become 301 // available. 302 private final long maxWaitTimeMillis; 303 304 // The set of change types for changes to include in the results. 305 @NotNull private final Set<ChangeType> changeTypes; 306 307 // The DN of a user for whom to pare down the contents of changelog entries 308 // based on access control and sensitive attribute restrictions, if defined. 309 @Nullable private final String pareEntriesForUserDN; 310 311 312 313 /** 314 * Creates a new get changelog batch extended request with the provided 315 * information. It will include all changes processed anywhere in the server, 316 * and will request that the result be returned as soon as any changes are 317 * available. 318 * 319 * @param startingPoint An object which indicates the starting point for 320 * the batch of changes to retrieve. It must not 321 * be {@code null}. 322 * @param maxChanges The maximum number of changes that should be 323 * retrieved before the server should return the 324 * corresponding extended result. A value less 325 * than or equal to zero may be used to indicate 326 * that the server should not return any entries 327 * but should just return a result containing a 328 * token which represents the starting point. 329 * @param maxWaitTimeMillis The maximum length of time in milliseconds to 330 * wait for changes. A value less than or equal to 331 * zero indicates that there should not be any wait 332 * and the result should be returned as soon as all 333 * immediately-available changes (up to the 334 * specified maximum count) have been returned. 335 * @param controls The set of controls to include in the request. 336 * It may be {@code null} or empty if there should 337 * be no controls. 338 */ 339 public GetChangelogBatchExtendedRequest( 340 @NotNull final ChangelogBatchStartingPoint startingPoint, 341 final int maxChanges, final long maxWaitTimeMillis, 342 @Nullable final Control... controls) 343 { 344 this(null, startingPoint, maxChanges, maxWaitTimeMillis, false, null, null, 345 null, false, null, null, false, false, controls); 346 } 347 348 349 350 /** 351 * Creates a new get changelog batch extended request with the provided 352 * information. It will include all changes processed anywhere in the server, 353 * and will request that the result be returned as soon as any changes are 354 * available. 355 * 356 * @param entryListener The listener that will be notified of any 357 * changelog entries (or other types of 358 * intermediate response) returned during the 359 * course of processing this request. It may be 360 * {@code null} if changelog entries should be 361 * collected and made available in the extended 362 * result. 363 * @param startingPoint An object which indicates the starting point for 364 * the batch of changes to retrieve. It must not 365 * be {@code null}. 366 * @param maxChanges The maximum number of changes that should be 367 * retrieved before the server should return the 368 * corresponding extended result. A value less 369 * than or equal to zero may be used to indicate 370 * that the server should not return any entries 371 * but should just return a result containing a 372 * token which represents the starting point. 373 * @param maxWaitTimeMillis The maximum length of time in milliseconds to 374 * wait for changes. A value less than or equal to 375 * zero indicates that there should not be any wait 376 * and the result should be returned as soon as all 377 * immediately-available changes (up to the 378 * specified maximum count) have been returned. 379 * @param controls The set of controls to include in the request. 380 * It may be {@code null} or empty if there should 381 * be no controls. 382 */ 383 public GetChangelogBatchExtendedRequest( 384 @Nullable final ChangelogEntryListener entryListener, 385 @NotNull final ChangelogBatchStartingPoint startingPoint, 386 final int maxChanges, final long maxWaitTimeMillis, 387 @Nullable final Control... controls) 388 { 389 this(entryListener, startingPoint, maxChanges, maxWaitTimeMillis, false, 390 null, null, null, false, null, null, false, false, controls); 391 } 392 393 394 395 /** 396 * Creates a new get changelog batch extended request with the provided 397 * information. 398 * 399 * @param startingPoint An object which indicates the starting 400 * point for the batch of changes to 401 * retrieve. It must not be {@code null}. 402 * @param maxChanges The maximum number of changes that should 403 * be retrieved before the server should 404 * return the corresponding extended result. 405 * A value less than or equal to zero may be 406 * used to indicate that the server should 407 * not return any entries but should just 408 * return a result containing a token which 409 * represents the starting point. 410 * @param maxWaitTimeMillis The maximum length of time in 411 * milliseconds to wait for changes. A 412 * value less than or equal to zero 413 * indicates that there should not be any 414 * wait and the result should be returned as 415 * soon as all immediately-available changes 416 * (up to the specified maximum count) have 417 * been returned. 418 * @param waitForMaxChanges Indicates whether the server should wait 419 * for up to the maximum length of time for 420 * up to the maximum number of changes to be 421 * returned. If this is {@code false}, then 422 * the result will be returned as soon as 423 * any changes are available (after sending 424 * those changes), even if the number of 425 * available changes is less than 426 * {@code maxChanges}. Otherwise, the 427 * result will not be returned until either 428 * the maximum number of changes have been 429 * returned or the maximum wait time has 430 * elapsed. 431 * @param includeBaseDNs A list of base DNs for entries to include 432 * in the set of changes to be returned. 433 * @param excludeBaseDNs A list of base DNs for entries to exclude 434 * from the set of changes to be returned. 435 * @param changeTypes The types of changes that should be 436 * returned. If this is {@code null} or 437 * empty, then all change types will be 438 * included. 439 * @param continueOnMissingChanges Indicates whether the server should make 440 * a best-effort attempt to return changes 441 * even if the starting point represents a 442 * point that is before the first available 443 * change in the changelog and therefore the 444 * results returned may be missing changes. 445 * @param controls The set of controls to include in the 446 * request. It may be {@code null} or empty 447 * if there should be no controls. 448 */ 449 public GetChangelogBatchExtendedRequest( 450 @NotNull final ChangelogBatchStartingPoint startingPoint, 451 final int maxChanges, final long maxWaitTimeMillis, 452 final boolean waitForMaxChanges, 453 @Nullable final List<String> includeBaseDNs, 454 @Nullable final List<String> excludeBaseDNs, 455 @Nullable final Set<ChangeType> changeTypes, 456 final boolean continueOnMissingChanges, 457 @Nullable final Control... controls) 458 { 459 this(null, startingPoint, maxChanges, maxWaitTimeMillis, waitForMaxChanges, 460 includeBaseDNs, excludeBaseDNs, changeTypes, continueOnMissingChanges, 461 null, null, false, false, controls); 462 } 463 464 465 466 /** 467 * Creates a new get changelog batch extended request with the provided 468 * information. 469 * 470 * @param entryListener The listener that will be notified of any 471 * changelog entries (or other types of 472 * intermediate response) returned during 473 * the course of processing this request. 474 * It may be {@code null} if changelog 475 * entries should be collected and made 476 * available in the extended result. 477 * @param startingPoint An object which indicates the starting 478 * point for the batch of changes to 479 * retrieve. It must not be {@code null}. 480 * @param maxChanges The maximum number of changes that should 481 * be retrieved before the server should 482 * return the corresponding extended result. 483 * A value less than or equal to zero may be 484 * used to indicate that the server should 485 * not return any entries but should just 486 * return a result containing a token which 487 * represents the starting point. 488 * @param maxWaitTimeMillis The maximum length of time in 489 * milliseconds to wait for changes. A 490 * value less than or equal to zero 491 * indicates that there should not be any 492 * wait and the result should be returned as 493 * soon as all immediately-available changes 494 * (up to the specified maximum count) have 495 * been returned. 496 * @param waitForMaxChanges Indicates whether the server should wait 497 * for up to the maximum length of time for 498 * up to the maximum number of changes to be 499 * returned. If this is {@code false}, then 500 * the result will be returned as soon as 501 * any changes are available (after sending 502 * those changes), even if the number of 503 * available changes is less than 504 * {@code maxChanges}. Otherwise, the 505 * result will not be returned until either 506 * the maximum number of changes have been 507 * returned or the maximum wait time has 508 * elapsed. 509 * @param includeBaseDNs A list of base DNs for entries to include 510 * in the set of changes to be returned. 511 * @param excludeBaseDNs A list of base DNs for entries to exclude 512 * from the set of changes to be returned. 513 * @param changeTypes The types of changes that should be 514 * returned. If this is {@code null} or 515 * empty, then all change types will be 516 * included. 517 * @param continueOnMissingChanges Indicates whether the server should make 518 * a best-effort attempt to return changes 519 * even if the starting point represents a 520 * point that is before the first available 521 * change in the changelog and therefore the 522 * results returned may be missing changes. 523 * @param controls The set of controls to include in the 524 * request. It may be {@code null} or empty 525 * if there should be no controls. 526 */ 527 public GetChangelogBatchExtendedRequest( 528 @Nullable final ChangelogEntryListener entryListener, 529 @NotNull final ChangelogBatchStartingPoint startingPoint, 530 final int maxChanges, final long maxWaitTimeMillis, 531 final boolean waitForMaxChanges, 532 @Nullable final List<String> includeBaseDNs, 533 @Nullable final List<String> excludeBaseDNs, 534 @Nullable final Set<ChangeType> changeTypes, 535 final boolean continueOnMissingChanges, 536 @Nullable final Control... controls) 537 { 538 this(entryListener, startingPoint, maxChanges, maxWaitTimeMillis, 539 waitForMaxChanges, includeBaseDNs, excludeBaseDNs, changeTypes, 540 continueOnMissingChanges, null, null, false, false, controls); 541 } 542 543 544 545 /** 546 * Creates a new get changelog batch extended request with the provided 547 * information. 548 * 549 * @param entryListener The listener that will be notified of any 550 * changelog entries (or other types of 551 * intermediate response) returned during 552 * the course of processing this request. 553 * It may be {@code null} if changelog 554 * entries should be collected and made 555 * available in the extended result. 556 * @param startingPoint An object which indicates the starting 557 * point for the batch of changes to 558 * retrieve. It must not be {@code null}. 559 * @param maxChanges The maximum number of changes that should 560 * be retrieved before the server should 561 * return the corresponding extended result. 562 * A value less than or equal to zero may be 563 * used to indicate that the server should 564 * not return any entries but should just 565 * return a result containing a token which 566 * represents the starting point. 567 * @param maxWaitTimeMillis The maximum length of time in 568 * milliseconds to wait for changes. A 569 * value less than or equal to zero 570 * indicates that there should not be any 571 * wait and the result should be returned as 572 * soon as all immediately-available changes 573 * (up to the specified maximum count) have 574 * been returned. 575 * @param waitForMaxChanges Indicates whether the server should wait 576 * for up to the maximum length of time for 577 * up to the maximum number of changes to be 578 * returned. If this is {@code false}, then 579 * the result will be returned as soon as 580 * any changes are available (after sending 581 * those changes), even if the number of 582 * available changes is less than 583 * {@code maxChanges}. Otherwise, the 584 * result will not be returned until either 585 * the maximum number of changes have been 586 * returned or the maximum wait time has 587 * elapsed. 588 * @param includeBaseDNs A list of base DNs for entries to include 589 * in the set of changes to be returned. 590 * @param excludeBaseDNs A list of base DNs for entries to exclude 591 * from the set of changes to be returned. 592 * @param changeTypes The types of changes that should be 593 * returned. If this is {@code null} or 594 * empty, then all change types will be 595 * included. 596 * @param continueOnMissingChanges Indicates whether the server should make 597 * a best-effort attempt to return changes 598 * even if the starting point represents a 599 * point that is before the first available 600 * change in the changelog and therefore the 601 * results returned may be missing changes. 602 * @param pareEntriesForUserDN The DN of a user for whom to pare down 603 * the contents of changelog entries based 604 * on the access control and sensitive 605 * attribute restrictions defined for that 606 * user. It may be {@code null} if 607 * changelog entries should not be pared 608 * down for any user, an empty string if 609 * changelog entries should be pared down to 610 * what is available to anonymous users, or 611 * a user DN to pare down entries for the 612 * specified user. 613 * @param changeSelectionCriteria The optional criteria to use to pare down 614 * the changelog entries that should be 615 * returned. It may be {@code null} if all 616 * changelog entries should be returned. 617 * @param controls The set of controls to include in the 618 * request. It may be {@code null} or empty 619 * if there should be no controls. 620 */ 621 public GetChangelogBatchExtendedRequest( 622 @Nullable final ChangelogEntryListener entryListener, 623 @NotNull final ChangelogBatchStartingPoint startingPoint, 624 final int maxChanges, final long maxWaitTimeMillis, 625 final boolean waitForMaxChanges, 626 @Nullable final List<String> includeBaseDNs, 627 @Nullable final List<String> excludeBaseDNs, 628 @Nullable final Set<ChangeType> changeTypes, 629 final boolean continueOnMissingChanges, 630 @Nullable final String pareEntriesForUserDN, 631 @Nullable final ChangelogBatchChangeSelectionCriteria 632 changeSelectionCriteria, 633 @Nullable final Control... controls) 634 { 635 this(entryListener, startingPoint, maxChanges, maxWaitTimeMillis, 636 waitForMaxChanges, includeBaseDNs, excludeBaseDNs, changeTypes, 637 continueOnMissingChanges, pareEntriesForUserDN, 638 changeSelectionCriteria, false, false, controls); 639 } 640 641 642 643 /** 644 * Creates a new get changelog batch extended request with the provided 645 * information. 646 * 647 * @param entryListener The listener that will be notified 648 * of any changelog entries (or other 649 * types of intermediate response) 650 * returned during the course of 651 * processing this request. It may be 652 * {@code null} if changelog entries 653 * should be collected and made 654 * available in the extended result. 655 * @param startingPoint An object which indicates the 656 * starting point for the batch of 657 * changes to retrieve. It must not 658 * be {@code null}. 659 * @param maxChanges The maximum number of changes that 660 * should be retrieved before the 661 * server should return the 662 * corresponding extended result. A 663 * value less than or equal to zero 664 * may be used to indicate that the 665 * server should not return any 666 * entries but should just return a 667 * result containing a token which 668 * represents the starting point. 669 * @param maxWaitTimeMillis The maximum length of time in 670 * milliseconds to wait for changes. 671 * A value less than or equal to zero 672 * indicates that there should not be 673 * any wait and the result should be 674 * returned as soon as all 675 * immediately-available changes (up 676 * to the specified maximum count) 677 * have been returned. 678 * @param waitForMaxChanges Indicates whether the server should 679 * wait for up to the maximum length 680 * of time for up to the maximum 681 * number of changes to be returned. 682 * If this is {@code false}, then the 683 * result will be returned as soon as 684 * any changes are available (after 685 * sending those changes), even if the 686 * number of available changes is less 687 * than {@code maxChanges}. 688 * Otherwise, the result will not be 689 * returned until either the maximum 690 * number of changes have been 691 * returned or the maximum wait time 692 * has elapsed. 693 * @param includeBaseDNs A list of base DNs for entries to 694 * include in the set of changes to be 695 * returned. 696 * @param excludeBaseDNs A list of base DNs for entries to 697 * exclude from the set of changes to 698 * be returned. 699 * @param changeTypes The types of changes that should be 700 * returned. If this is {@code null} 701 * or empty, then all change types 702 * will be included. 703 * @param continueOnMissingChanges Indicates whether the server should 704 * make a best-effort attempt to 705 * return changes even if the starting 706 * point represents a point that is 707 * before the first available change 708 * in the changelog and therefore the 709 * results returned may be missing 710 * changes. 711 * @param pareEntriesForUserDN The DN of a user for whom to pare 712 * down the contents of changelog 713 * entries based on the access control 714 * and sensitive attribute 715 * restrictions defined for that user. 716 * It may be {@code null} if changelog 717 * entries should not be pared down 718 * for any user, an empty string if 719 * changelog entries should be pared 720 * down to what is available to 721 * anonymous users, or a user DN to 722 * pare down entries for the specified 723 * user. 724 * @param changeSelectionCriteria The optional criteria to use to 725 * pare down the changelog entries 726 * that should be returned. It may be 727 * {@code null} if all changelog 728 * entries should be returned. 729 * @param includeSoftDeletedEntryMods Indicates whether to include 730 * changelog entries that represent 731 * changes to soft-deleted entries. 732 * @param includeSoftDeletedEntryDeletes Indicates whether to include 733 * changelog entries that represent 734 * deletes of soft-deleted entries. 735 * @param controls The set of controls to include in 736 * the request. It may be 737 * {@code null} or empty if there 738 * should be no controls. 739 */ 740 public GetChangelogBatchExtendedRequest( 741 @Nullable final ChangelogEntryListener entryListener, 742 @NotNull final ChangelogBatchStartingPoint startingPoint, 743 final int maxChanges, final long maxWaitTimeMillis, 744 final boolean waitForMaxChanges, 745 @Nullable final List<String> includeBaseDNs, 746 @Nullable final List<String> excludeBaseDNs, 747 @Nullable final Set<ChangeType> changeTypes, 748 final boolean continueOnMissingChanges, 749 @Nullable final String pareEntriesForUserDN, 750 @Nullable final ChangelogBatchChangeSelectionCriteria 751 changeSelectionCriteria, 752 final boolean includeSoftDeletedEntryMods, 753 final boolean includeSoftDeletedEntryDeletes, 754 @Nullable final Control... controls) 755 { 756 super(GET_CHANGELOG_BATCH_REQUEST_OID, 757 encodeValue(startingPoint, maxChanges, maxWaitTimeMillis, 758 waitForMaxChanges, includeBaseDNs, excludeBaseDNs, changeTypes, 759 continueOnMissingChanges, pareEntriesForUserDN, 760 changeSelectionCriteria, includeSoftDeletedEntryMods, 761 includeSoftDeletedEntryDeletes), 762 controls); 763 764 this.entryListener = entryListener; 765 this.startingPoint = startingPoint; 766 this.maxWaitTimeMillis = maxWaitTimeMillis; 767 this.waitForMaxChanges = waitForMaxChanges; 768 this.continueOnMissingChanges = continueOnMissingChanges; 769 this.pareEntriesForUserDN = pareEntriesForUserDN; 770 this.changeSelectionCriteria = changeSelectionCriteria; 771 this.includeSoftDeletedEntryMods = includeSoftDeletedEntryMods; 772 this.includeSoftDeletedEntryDeletes = includeSoftDeletedEntryDeletes; 773 774 if (maxChanges <= 0) 775 { 776 this.maxChanges = 0; 777 } 778 else 779 { 780 this.maxChanges = maxChanges; 781 } 782 783 if (includeBaseDNs == null) 784 { 785 this.includeBaseDNs = Collections.emptyList(); 786 } 787 else 788 { 789 this.includeBaseDNs = Collections.unmodifiableList(includeBaseDNs); 790 } 791 792 if (excludeBaseDNs == null) 793 { 794 this.excludeBaseDNs = Collections.emptyList(); 795 } 796 else 797 { 798 this.excludeBaseDNs = Collections.unmodifiableList(excludeBaseDNs); 799 } 800 801 if ((changeTypes == null) || changeTypes.isEmpty()) 802 { 803 this.changeTypes = 804 Collections.unmodifiableSet(EnumSet.allOf(ChangeType.class)); 805 } 806 else 807 { 808 this.changeTypes = Collections.unmodifiableSet(changeTypes); 809 } 810 } 811 812 813 814 /** 815 * Creates a new get changelog batch extended request from the provided 816 * generic extended request. 817 * 818 * @param extendedRequest The generic extended request to be decoded as a 819 * get changelog batch extended request. 820 * 821 * @throws LDAPException If the provided generic request cannot be decoded 822 * as a get changelog batch extended request. 823 */ 824 public GetChangelogBatchExtendedRequest( 825 @NotNull final ExtendedRequest extendedRequest) 826 throws LDAPException 827 { 828 super(extendedRequest.getOID(), extendedRequest.getValue(), 829 extendedRequest.getControls()); 830 831 final ASN1OctetString value = extendedRequest.getValue(); 832 if (value == null) 833 { 834 throw new LDAPException(ResultCode.DECODING_ERROR, 835 ERR_GET_CHANGELOG_BATCH_REQ_NO_VALUE.get()); 836 } 837 838 final ASN1Sequence valueSequence; 839 try 840 { 841 valueSequence = ASN1Sequence.decodeAsSequence(value.getValue()); 842 } 843 catch (final Exception e) 844 { 845 Debug.debugException(e); 846 throw new LDAPException(ResultCode.DECODING_ERROR, 847 ERR_GET_CHANGELOG_BATCH_REQ_VALUE_NOT_SEQUENCE.get( 848 StaticUtils.getExceptionMessage(e)), e); 849 } 850 851 final ASN1Element[] elements = valueSequence.elements(); 852 if (elements.length < 2) 853 { 854 throw new LDAPException(ResultCode.DECODING_ERROR, 855 ERR_GET_CHANGELOG_BATCH_REQ_TOO_FEW_ELEMENTS.get()); 856 } 857 858 try 859 { 860 startingPoint = ChangelogBatchStartingPoint.decode(elements[0]); 861 862 final int mc = ASN1Integer.decodeAsInteger(elements[1]).intValue(); 863 if (mc > 0) 864 { 865 maxChanges = mc; 866 } 867 else 868 { 869 maxChanges = 0; 870 } 871 872 boolean waitForMax = false; 873 long maxTime = 0L; 874 List<String> includeBase = Collections.emptyList(); 875 List<String> excludeBase = Collections.emptyList(); 876 Set<ChangeType> types = 877 Collections.unmodifiableSet(EnumSet.allOf(ChangeType.class)); 878 boolean continueOnMissing = false; 879 String pareForDN = null; 880 ChangelogBatchChangeSelectionCriteria changeCriteria = null; 881 boolean includeSDMods = false; 882 boolean includeSDDeletes = false; 883 884 for (int i=2; i < elements.length; i++) 885 { 886 switch (elements[i].getType()) 887 { 888 case TYPE_MAX_TIME: 889 maxTime = ASN1Long.decodeAsLong(elements[i]).longValue(); 890 if (maxTime < 0L) 891 { 892 maxTime = 0L; 893 } 894 break; 895 896 case TYPE_WAIT_FOR_MAX_CHANGES: 897 waitForMax = 898 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 899 break; 900 901 case TYPE_INCLUDE_BASE: 902 final ASN1Element[] includeElements = 903 ASN1Sequence.decodeAsSequence(elements[i]).elements(); 904 final ArrayList<String> includeList = 905 new ArrayList<>(includeElements.length); 906 for (final ASN1Element e : includeElements) 907 { 908 includeList.add( 909 ASN1OctetString.decodeAsOctetString(e).stringValue()); 910 } 911 includeBase = Collections.unmodifiableList(includeList); 912 break; 913 914 case TYPE_EXCLUDE_BASE: 915 final ASN1Element[] excludeElements = 916 ASN1Sequence.decodeAsSequence(elements[i]).elements(); 917 final ArrayList<String> excludeList = 918 new ArrayList<>(excludeElements.length); 919 for (final ASN1Element e : excludeElements) 920 { 921 excludeList.add( 922 ASN1OctetString.decodeAsOctetString(e).stringValue()); 923 } 924 excludeBase = Collections.unmodifiableList(excludeList); 925 break; 926 927 case TYPE_CHANGE_TYPES: 928 final EnumSet<ChangeType> ctSet = EnumSet.noneOf(ChangeType.class); 929 for (final ASN1Element e : 930 ASN1Set.decodeAsSet(elements[i]).elements()) 931 { 932 final int v = ASN1Enumerated.decodeAsEnumerated(e).intValue(); 933 switch (v) 934 { 935 case CHANGE_TYPE_ADD: 936 ctSet.add(ChangeType.ADD); 937 break; 938 case CHANGE_TYPE_DELETE: 939 ctSet.add(ChangeType.DELETE); 940 break; 941 case CHANGE_TYPE_MODIFY: 942 ctSet.add(ChangeType.MODIFY); 943 break; 944 case CHANGE_TYPE_MODIFY_DN: 945 ctSet.add(ChangeType.MODIFY_DN); 946 break; 947 default: 948 throw new LDAPException(ResultCode.DECODING_ERROR, 949 ERR_GET_CHANGELOG_BATCH_REQ_VALUE_UNRECOGNIZED_CT.get( 950 v)); 951 } 952 } 953 types = Collections.unmodifiableSet(ctSet); 954 break; 955 956 case TYPE_CONTINUE_ON_MISSING_CHANGES: 957 continueOnMissing = 958 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 959 break; 960 961 case TYPE_PARE_ENTRIES_FOR_USER_DN: 962 pareForDN = 963 ASN1OctetString.decodeAsOctetString(elements[i]).stringValue(); 964 break; 965 966 case ChangelogBatchChangeSelectionCriteria.TYPE_SELECTION_CRITERIA: 967 changeCriteria = 968 ChangelogBatchChangeSelectionCriteria.decode(elements[i]); 969 break; 970 971 case TYPE_INCLUDE_SOFT_DELETED_ENTRY_MODS: 972 includeSDMods = 973 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 974 break; 975 976 case TYPE_INCLUDE_SOFT_DELETED_ENTRY_DELETES: 977 includeSDDeletes = 978 ASN1Boolean.decodeAsBoolean(elements[i]).booleanValue(); 979 break; 980 981 default: 982 throw new LDAPException(ResultCode.DECODING_ERROR, 983 ERR_GET_CHANGELOG_BATCH_REQ_VALUE_UNRECOGNIZED_TYPE.get( 984 StaticUtils.toHex(elements[i].getType()))); 985 } 986 } 987 988 entryListener = null; 989 maxWaitTimeMillis = maxTime; 990 waitForMaxChanges = waitForMax; 991 includeBaseDNs = includeBase; 992 excludeBaseDNs = excludeBase; 993 changeTypes = types; 994 continueOnMissingChanges = continueOnMissing; 995 pareEntriesForUserDN = pareForDN; 996 changeSelectionCriteria = changeCriteria; 997 includeSoftDeletedEntryMods = includeSDMods; 998 includeSoftDeletedEntryDeletes = includeSDDeletes; 999 } 1000 catch (final LDAPException le) 1001 { 1002 Debug.debugException(le); 1003 throw le; 1004 } 1005 catch (final Exception e) 1006 { 1007 Debug.debugException(e); 1008 throw new LDAPException(ResultCode.DECODING_ERROR, 1009 ERR_GET_CHANGELOG_BATCH_REQ_ERROR_DECODING_VALUE.get( 1010 StaticUtils.getExceptionMessage(e)), e); 1011 } 1012 } 1013 1014 1015 1016 /** 1017 * Encodes the value for this extended request using the provided information. 1018 * 1019 * @param startingPoint An object which indicates the 1020 * starting point for the batch of 1021 * changes to retrieve. It must not 1022 * be {@code null}. 1023 * @param maxChanges The maximum number of changes that 1024 * should be retrieved before the 1025 * server should return the 1026 * corresponding extended result. A 1027 * value less than or equal to zero 1028 * may be used to indicate that the 1029 * server should not return any 1030 * entries but should just return a 1031 * result containing a token which 1032 * represents the starting point. 1033 * @param maxWaitTimeMillis The maximum length of time in 1034 * milliseconds to wait for changes. 1035 * A value less than or equal to zero 1036 * indicates that there should not be 1037 * any wait and the result should be 1038 * returned as soon as all 1039 * immediately-available changes (up 1040 * to the specified maximum count) 1041 * have been returned. 1042 * @param waitForMaxChanges Indicates whether the server should 1043 * wait for up to the maximum length 1044 * of time for up to the maximum 1045 * number of changes to be returned. 1046 * If this is {@code false}, then the 1047 * result will be returned as soon as 1048 * any changes are available (after 1049 * sending those changes), even if the 1050 * number of available changes is less 1051 * than {@code maxChanges}. 1052 * Otherwise, the result will not be 1053 * returned until either the maximum 1054 * number of changes have been 1055 * returned or the maximum wait time 1056 * has elapsed. 1057 * @param includeBaseDNs A list of base DNs for entries to 1058 * include in the set of changes to be 1059 * returned. 1060 * @param excludeBaseDNs A list of base DNs for entries to 1061 * exclude from the set of changes to 1062 * be returned. 1063 * @param changeTypes The types of changes that should be 1064 * returned. If this is {@code null} 1065 * or empty, then all change types 1066 * will be included. 1067 * @param continueOnMissingChanges Indicates whether the server should 1068 * make a best-effort attempt to 1069 * return changes even if the starting 1070 * point represents a point that is 1071 * before the first available change 1072 * in the changelog and therefore the 1073 * results returned may be missing 1074 * changes. 1075 * @param pareEntriesForUserDN The DN of a user for whom to pare 1076 * down the contents of changelog 1077 * entries based on the access control 1078 * and sensitive attribute 1079 * restrictions defined for that user. 1080 * It may be {@code null} if changelog 1081 * entries should not be pared down 1082 * for any user, an empty string if 1083 * changelog entries should be pared 1084 * down to what is available to 1085 * anonymous users, or a user DN to 1086 * pare down entries for the specified 1087 * user. 1088 * @param changeSelectionCriteria The optional criteria to use to 1089 * pare down the changelog entries 1090 * that should be returned. It may be 1091 * {@code null} if all changelog 1092 * entries should be returned. 1093 * @param includeSoftDeletedEntryMods Indicates whether to include 1094 * changelog entries that represent 1095 * changes to soft-deleted entries. 1096 * @param includeSoftDeletedEntryDeletes Indicates whether to include 1097 * changelog entries that represent 1098 * deletes of soft-deleted entries. 1099 * 1100 * @return The value for the extended request. 1101 */ 1102 @NotNull() 1103 private static ASN1OctetString encodeValue( 1104 @NotNull final ChangelogBatchStartingPoint startingPoint, 1105 final int maxChanges, final long maxWaitTimeMillis, 1106 final boolean waitForMaxChanges, 1107 @Nullable final List<String> includeBaseDNs, 1108 @Nullable final List<String> excludeBaseDNs, 1109 @Nullable final Set<ChangeType> changeTypes, 1110 final boolean continueOnMissingChanges, 1111 @Nullable final String pareEntriesForUserDN, 1112 @Nullable final ChangelogBatchChangeSelectionCriteria 1113 changeSelectionCriteria, 1114 final boolean includeSoftDeletedEntryMods, 1115 final boolean includeSoftDeletedEntryDeletes) 1116 { 1117 Validator.ensureNotNull(startingPoint); 1118 1119 final ArrayList<ASN1Element> elements = new ArrayList<>(12); 1120 1121 elements.add(startingPoint.encode()); 1122 1123 if (maxChanges > 0) 1124 { 1125 elements.add(new ASN1Integer(maxChanges)); 1126 } 1127 else 1128 { 1129 elements.add(new ASN1Integer(0)); 1130 } 1131 1132 if (maxWaitTimeMillis > 0L) 1133 { 1134 elements.add(new ASN1Long(TYPE_MAX_TIME, maxWaitTimeMillis)); 1135 } 1136 1137 if (waitForMaxChanges) 1138 { 1139 elements.add(new ASN1Boolean(TYPE_WAIT_FOR_MAX_CHANGES, true)); 1140 } 1141 1142 if ((includeBaseDNs != null) && (! includeBaseDNs.isEmpty())) 1143 { 1144 final ArrayList<ASN1Element> l = new ArrayList<>(includeBaseDNs.size()); 1145 for (final String s : includeBaseDNs) 1146 { 1147 l.add(new ASN1OctetString(s)); 1148 } 1149 elements.add(new ASN1Sequence(TYPE_INCLUDE_BASE, l)); 1150 } 1151 1152 if ((excludeBaseDNs != null) && (! excludeBaseDNs.isEmpty())) 1153 { 1154 final ArrayList<ASN1Element> l = new ArrayList<>(excludeBaseDNs.size()); 1155 for (final String s : excludeBaseDNs) 1156 { 1157 l.add(new ASN1OctetString(s)); 1158 } 1159 elements.add(new ASN1Sequence(TYPE_EXCLUDE_BASE, l)); 1160 } 1161 1162 if ((changeTypes != null) && (! changeTypes.isEmpty()) && 1163 (! changeTypes.equals(EnumSet.allOf(ChangeType.class)))) 1164 { 1165 final ArrayList<ASN1Element> l = new ArrayList<>(changeTypes.size()); 1166 for (final ChangeType t : changeTypes) 1167 { 1168 switch (t) 1169 { 1170 case ADD: 1171 l.add(new ASN1Enumerated(CHANGE_TYPE_ADD)); 1172 break; 1173 case DELETE: 1174 l.add(new ASN1Enumerated(CHANGE_TYPE_DELETE)); 1175 break; 1176 case MODIFY: 1177 l.add(new ASN1Enumerated(CHANGE_TYPE_MODIFY)); 1178 break; 1179 case MODIFY_DN: 1180 l.add(new ASN1Enumerated(CHANGE_TYPE_MODIFY_DN)); 1181 break; 1182 } 1183 } 1184 elements.add(new ASN1Set(TYPE_CHANGE_TYPES, l)); 1185 } 1186 1187 if (continueOnMissingChanges) 1188 { 1189 elements.add(new ASN1Boolean(TYPE_CONTINUE_ON_MISSING_CHANGES, true)); 1190 } 1191 1192 if (pareEntriesForUserDN != null) 1193 { 1194 elements.add(new ASN1OctetString(TYPE_PARE_ENTRIES_FOR_USER_DN, 1195 pareEntriesForUserDN)); 1196 } 1197 1198 if (changeSelectionCriteria != null) 1199 { 1200 elements.add(changeSelectionCriteria.encode()); 1201 } 1202 1203 if (includeSoftDeletedEntryMods) 1204 { 1205 elements.add(new ASN1Boolean(TYPE_INCLUDE_SOFT_DELETED_ENTRY_MODS, true)); 1206 } 1207 1208 if (includeSoftDeletedEntryDeletes) 1209 { 1210 elements.add(new ASN1Boolean(TYPE_INCLUDE_SOFT_DELETED_ENTRY_DELETES, 1211 true)); 1212 } 1213 1214 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 1215 } 1216 1217 1218 1219 /** 1220 * Retrieves the starting point for the batch of changes to retrieve. 1221 * 1222 * @return The starting point for the batch of changes to retrieve. 1223 */ 1224 @NotNull() 1225 public ChangelogBatchStartingPoint getStartingPoint() 1226 { 1227 return startingPoint; 1228 } 1229 1230 1231 1232 /** 1233 * Retrieves the maximum number of changes that should be returned before the 1234 * operation completes. A value of zero indicates that the server should not 1235 * return any entries but should just return a result containing a token which 1236 * represents the starting point. 1237 * 1238 * @return The maximum number of changes that should be returned before the 1239 * operation completes. 1240 */ 1241 public int getMaxChanges() 1242 { 1243 return maxChanges; 1244 } 1245 1246 1247 1248 /** 1249 * Retrieves the maximum length of time in milliseconds that the server should 1250 * wait for changes to become available before returning the corresponding 1251 * extended result to the client. A value of zero indicates that the server 1252 * should return only those results which are immediately available without 1253 * waiting. 1254 * 1255 * @return The maximum length of time in milliseconds that the server should 1256 * wait for changes to become available, or 0 if the server should 1257 * not wait at all. 1258 */ 1259 public long getMaxWaitTimeMillis() 1260 { 1261 return maxWaitTimeMillis; 1262 } 1263 1264 1265 1266 /** 1267 * Indicates whether the server should wait for up to the maximum length of 1268 * time for up to the maximum number of changes to be returned before sending 1269 * the extended result. 1270 * 1271 * @return {@code false} if the server should return the corresponding 1272 * extended result as soon as any changes are available (after 1273 * sending those available changes), or {@code true} if the result 1274 * should not be returned until either the maximum number of changes 1275 * have been returned or the maximum wait time has elapsed. 1276 */ 1277 public boolean waitForMaxChanges() 1278 { 1279 return waitForMaxChanges; 1280 } 1281 1282 1283 1284 /** 1285 * Retrieves a list of base DNs below which the server should return 1286 * information about changes that have been processed. If any include base 1287 * DNs are specified, then the server should return only changes to entries 1288 * which reside at or below one of the include base DNs and not at or below 1289 * any of the exclude base DNs. If no include or exclude base DNs are 1290 * defined, then the server should return information about changes processed 1291 * anywhere within the DIT. 1292 * 1293 * @return A list of the include base DNs for changes to retrieve, or an 1294 * empty list if there are none. 1295 */ 1296 @NotNull() 1297 public List<String> getIncludeBaseDNs() 1298 { 1299 return includeBaseDNs; 1300 } 1301 1302 1303 1304 /** 1305 * Retrieves a list of base DNs below which the server should exclude 1306 * information about changes processed. If any exclude base DNs are 1307 * specified, then the server should not return changes to entries which 1308 * reside at or below any of the exclude base DNs, even if they are also below 1309 * an include base DN (and as such, the request should not include any exclude 1310 * base DNs which are at or below any include base DNs). If no include or 1311 * exclude base DNs are defined, then the server should return information 1312 * about changes processed anywhere within the DIT. 1313 * 1314 * @return A list of the exclude base DNs for changes to retrieve, or an 1315 * empty list if there are none. 1316 */ 1317 @NotNull() 1318 public List<String> getExcludeBaseDNs() 1319 { 1320 return excludeBaseDNs; 1321 } 1322 1323 1324 1325 /** 1326 * Retrieves the set of change types for changes to be returned to the client. 1327 * 1328 * @return The set of change types for changes to be returned to the client. 1329 */ 1330 @NotNull() 1331 public Set<ChangeType> getChangeTypes() 1332 { 1333 return changeTypes; 1334 } 1335 1336 1337 1338 /** 1339 * Indicates whether the server should make a best-effort attempt to return 1340 * changes to the client even if the starting point represents a time before 1341 * the start of the changelog and there may be missing changes. 1342 * 1343 * @return {@code true} if the server should attempt to return as many 1344 * changes as possible even if some may be missing, or {@code false} 1345 * if the server should return an error if there may be missing 1346 * changes. 1347 */ 1348 public boolean continueOnMissingChanges() 1349 { 1350 return continueOnMissingChanges; 1351 } 1352 1353 1354 1355 /** 1356 * Retrieves the possibly-empty DN of the user for whom changelog entries 1357 * should be pared based on access control and sensitive attribute 1358 * restrictions, if defined. 1359 * 1360 * @return The possibly-empty DN of the user form whom changelog entries 1361 * should be pared based on access control and sensitive attribute 1362 * restrictions, or {@code null} if changelog entries should not be 1363 * pared based for any user. 1364 */ 1365 @Nullable() 1366 public String getPareEntriesForUserDN() 1367 { 1368 return pareEntriesForUserDN; 1369 } 1370 1371 1372 1373 /** 1374 * Retrieves the change selection criteria for this get changelog batch 1375 * extended request, if defined. 1376 * 1377 * @return The change selection criteria for this get changelog batch 1378 * extended request, or {@code null} if none is defined. 1379 */ 1380 @Nullable() 1381 public ChangelogBatchChangeSelectionCriteria getChangeSelectionCriteria() 1382 { 1383 return changeSelectionCriteria; 1384 } 1385 1386 1387 1388 /** 1389 * Indicates whether to include changes that represent modifications to 1390 * soft-deleted entries. 1391 * 1392 * @return {@code true} if the result set should include modifications to 1393 * soft-deleted entries, or {@code false} if not. 1394 */ 1395 public boolean includeSoftDeletedEntryMods() 1396 { 1397 return includeSoftDeletedEntryMods; 1398 } 1399 1400 1401 1402 /** 1403 * Indicates whether to include changes that represent deletes of soft-deleted 1404 * entries. 1405 * 1406 * @return {@code true} if the result set should include deletes of 1407 * soft-deleted entries, or {@code false} if not. 1408 */ 1409 public boolean includeSoftDeletedEntryDeletes() 1410 { 1411 return includeSoftDeletedEntryDeletes; 1412 } 1413 1414 1415 1416 /** 1417 * Retrieves the changelog entry listener that will be used for this request, 1418 * if applicable. 1419 * 1420 * @return The changelog entry listener that will be used for this request, 1421 * or {@code null} if the entries will be made available in the 1422 * extended result. 1423 */ 1424 @Nullable() 1425 public ChangelogEntryListener getEntryListener() 1426 { 1427 return entryListener; 1428 } 1429 1430 1431 1432 /** 1433 * {@inheritDoc} 1434 */ 1435 @Override() 1436 @NotNull() 1437 public GetChangelogBatchExtendedResult process( 1438 @NotNull final LDAPConnection connection, final int depth) 1439 throws LDAPException 1440 { 1441 final IntermediateResponseListener l = getIntermediateResponseListener(); 1442 if (l != null) 1443 { 1444 throw new LDAPException(ResultCode.PARAM_ERROR, 1445 ERR_GET_CHANGELOG_BATCH_REQ_IR_LISTENER_NOT_ALLOWED.get()); 1446 } 1447 1448 final GetChangelogBatchIntermediateResponseListener listener; 1449 if (entryListener == null) 1450 { 1451 listener = new GetChangelogBatchIntermediateResponseListener( 1452 new DefaultChangelogEntryListener(this)); 1453 } 1454 else 1455 { 1456 listener = 1457 new GetChangelogBatchIntermediateResponseListener(entryListener); 1458 } 1459 1460 setIntermediateResponseListener(listener); 1461 1462 ExtendedResult r; 1463 try 1464 { 1465 r = super.process(connection, depth); 1466 } 1467 catch (final LDAPException le) 1468 { 1469 Debug.debugException(le); 1470 1471 r = new ExtendedResult(getLastMessageID(), le.getResultCode(), 1472 le.getDiagnosticMessage(), le.getMatchedDN(), le.getReferralURLs(), 1473 null, null, le.getResponseControls()); 1474 } 1475 finally 1476 { 1477 setIntermediateResponseListener(null); 1478 } 1479 1480 if (entryListener == null) 1481 { 1482 final DefaultChangelogEntryListener defaultEntryListener = 1483 (DefaultChangelogEntryListener) listener.getEntryListener(); 1484 return new GetChangelogBatchExtendedResult(r, 1485 defaultEntryListener.getEntryList()); 1486 } 1487 else 1488 { 1489 return new GetChangelogBatchExtendedResult(r, listener.getEntryCount()); 1490 } 1491 } 1492 1493 1494 1495 /** 1496 * {@inheritDoc}. 1497 */ 1498 @Override() 1499 @NotNull() 1500 public GetChangelogBatchExtendedRequest duplicate() 1501 { 1502 return duplicate(getControls()); 1503 } 1504 1505 1506 1507 /** 1508 * {@inheritDoc}. 1509 */ 1510 @Override() 1511 @NotNull() 1512 public GetChangelogBatchExtendedRequest duplicate( 1513 @Nullable final Control[] controls) 1514 { 1515 final GetChangelogBatchExtendedRequest r = 1516 new GetChangelogBatchExtendedRequest(entryListener, startingPoint, 1517 maxChanges, maxWaitTimeMillis, waitForMaxChanges, includeBaseDNs, 1518 excludeBaseDNs, changeTypes, continueOnMissingChanges, 1519 pareEntriesForUserDN, changeSelectionCriteria, 1520 includeSoftDeletedEntryMods, includeSoftDeletedEntryDeletes, 1521 controls); 1522 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 1523 r.setIntermediateResponseListener(getIntermediateResponseListener()); 1524 r.setReferralDepth(getReferralDepth()); 1525 r.setReferralConnector(getReferralConnectorInternal()); 1526 return r; 1527 } 1528 1529 1530 1531 /** 1532 * {@inheritDoc} 1533 */ 1534 @Override() 1535 @NotNull() 1536 public String getExtendedRequestName() 1537 { 1538 return INFO_GET_CHANGELOG_BATCH_REQ_NAME.get(); 1539 } 1540 1541 1542 1543 /** 1544 * {@inheritDoc} 1545 */ 1546 @Override() 1547 public void toString(@NotNull final StringBuilder buffer) 1548 { 1549 buffer.append("GetChangelogBatchExtendedRequest(startingPoint="); 1550 startingPoint.toString(buffer); 1551 1552 buffer.append(", maxChanges="); 1553 buffer.append(maxChanges); 1554 buffer.append(", maxWaitTimeMillis="); 1555 buffer.append(maxWaitTimeMillis); 1556 buffer.append(", waitForMaxChanges="); 1557 buffer.append(waitForMaxChanges); 1558 buffer.append(", includeBase={"); 1559 1560 final Iterator<String> includeIterator = includeBaseDNs.iterator(); 1561 while (includeIterator.hasNext()) 1562 { 1563 buffer.append('"'); 1564 buffer.append(includeIterator.next()); 1565 buffer.append('"'); 1566 if (includeIterator.hasNext()) 1567 { 1568 buffer.append(", "); 1569 } 1570 } 1571 1572 buffer.append("}, excludeBase={"); 1573 1574 final Iterator<String> excludeIterator = excludeBaseDNs.iterator(); 1575 while (excludeIterator.hasNext()) 1576 { 1577 buffer.append('"'); 1578 buffer.append(excludeIterator.next()); 1579 buffer.append('"'); 1580 if (excludeIterator.hasNext()) 1581 { 1582 buffer.append(", "); 1583 } 1584 } 1585 1586 buffer.append("}, changeTypes={"); 1587 1588 final Iterator<ChangeType> typeIterator = changeTypes.iterator(); 1589 while (typeIterator.hasNext()) 1590 { 1591 buffer.append(typeIterator.next().getName()); 1592 if (typeIterator.hasNext()) 1593 { 1594 buffer.append(", "); 1595 } 1596 } 1597 1598 buffer.append("}, continueOnMissingChanges="); 1599 buffer.append(continueOnMissingChanges); 1600 1601 if (pareEntriesForUserDN != null) 1602 { 1603 buffer.append(", pareEntriesForUserDN='"); 1604 buffer.append(pareEntriesForUserDN); 1605 buffer.append('\''); 1606 } 1607 1608 if (changeSelectionCriteria != null) 1609 { 1610 buffer.append(", changeSelectionCriteria="); 1611 changeSelectionCriteria.toString(buffer); 1612 } 1613 1614 buffer.append(", includeSoftDeletedEntryMods="); 1615 buffer.append(includeSoftDeletedEntryMods); 1616 buffer.append(", includeSoftDeletedEntryDeletes="); 1617 buffer.append(includeSoftDeletedEntryDeletes); 1618 1619 final Control[] controls = getControls(); 1620 if (controls.length > 0) 1621 { 1622 buffer.append(", controls={"); 1623 for (int i=0; i < controls.length; i++) 1624 { 1625 if (i > 0) 1626 { 1627 buffer.append(", "); 1628 } 1629 1630 buffer.append(controls[i]); 1631 } 1632 buffer.append('}'); 1633 } 1634 1635 buffer.append(')'); 1636 } 1637}