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