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