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 }