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