001/*
002 * Copyright 2008-2018 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2018 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.tasks;
022
023
024
025import java.util.ArrayList;
026import java.util.Arrays;
027import java.util.Collections;
028import java.util.Date;
029import java.util.LinkedHashMap;
030import java.util.List;
031import java.util.Map;
032
033import com.unboundid.ldap.sdk.Attribute;
034import com.unboundid.ldap.sdk.Entry;
035import com.unboundid.util.NotMutable;
036import com.unboundid.util.StaticUtils;
037import com.unboundid.util.ThreadSafety;
038import com.unboundid.util.ThreadSafetyLevel;
039
040import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
041import static com.unboundid.util.Validator.*;
042
043
044
045/**
046 * This class defines a Directory Server task that can be used to import LDIF
047 * content into a backend.
048 * <BR>
049 * <BLOCKQUOTE>
050 *   <B>NOTE:</B>  This class, and other classes within the
051 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
052 *   supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661
053 *   server products.  These classes provide support for proprietary
054 *   functionality or for external specifications that are not considered stable
055 *   or mature enough to be guaranteed to work in an interoperable way with
056 *   other types of LDAP servers.
057 * </BLOCKQUOTE>
058 * <BR>
059 * The properties that are available for use with this type of task include:
060 * <UL>
061 *   <LI>The paths (on the server system) to the LDIF files containing the data
062 *       to be imported.  At least one LDIF file path must be provided.</LI>
063 *   <LI>The backend ID for the backend into which the data should be
064 *       imported.  It may be omitted only if at least one include branch is
065 *       provided.</LI>
066 *   <LI>A flag that indicates whether to append to the existing data in the
067 *       backend rather than destroying any existing data before beginning the
068 *       import.</LI>
069 *   <LI>A flag that indicates whether to replace entries that already exist
070 *       when operating in append mode.</LI>
071 *   <LI>An optional path (on the server system) to a file to which the server
072 *       should write copies of any entries that are rejected, along with a
073 *       message explaining why they were rejected.</LI>
074 *   <LI>A flag that indicates whether to overwrite the reject file rather than
075 *       append to it if it already exists.</LI>
076 *   <LI>A flag that indicates whether to clear the entire contents of the
077 *       backend even if it has multiple base DNs but only a subset of them
078 *       were provided in the set of include branches.</LI>
079 *   <LI>An optional list of base DNs for branches to include in the
080 *       import.</LI>
081 *   <LI>An optional list of base DNs for branches to exclude from the
082 *       import.</LI>
083 *   <LI>An optional list of search filters that may be used to determine
084 *       whether an entry should be included in the import.</LI>
085 *   <LI>An optional list of search filters that may be used to determine
086 *       whether an entry should be excluded from the import.</LI>
087 *   <LI>An optional list of attributes that should be included in the entries
088 *       that are imported.</LI>
089 *   <LI>An optional list of attributes that should be excluded from the entries
090 *       that are imported.</LI>
091 *   <LI>A flag that indicates whether the LDIF data to import is
092 *       compressed.</LI>
093 *   <LI>A flag that indicates whether the LDIF data to import is
094 *       encrypted.</LI>
095 *   <LI>A flag that indicates whether to skip schema validation for the data
096 *       that is imported.</LI>
097 *   <LI>The path to a file containing a passphrase to use to generate the
098 *       encryption key.</LI>
099 * </UL>
100 */
101@NotMutable()
102@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
103public final class ImportTask
104       extends Task
105{
106  /**
107   * The fully-qualified name of the Java class that is used for the import
108   * task.
109   */
110  static final String IMPORT_TASK_CLASS =
111       "com.unboundid.directory.server.tasks.ImportTask";
112
113
114
115  /**
116   * The name of the attribute used to indicate whether to append to an existing
117   * database rather than overwriting its content.
118   */
119  private static final String ATTR_APPEND =
120       "ds-task-import-append";
121
122
123
124  /**
125   * The name of the attribute used to specify the backend ID for the backend
126   * into which to import the data.
127   */
128  private static final String ATTR_BACKEND_ID = "ds-task-import-backend-id";
129
130
131
132  /**
133   * The name of the attribute used to indicate whether to clear the entire
134   * backend when importing based on base DN.
135   */
136  private static final String ATTR_CLEAR_BACKEND =
137       "ds-task-import-clear-backend";
138
139
140
141  /**
142   * The name of the attribute used to specify the path to a file that contains
143   * the passphrase to use to generate the encryption key.
144   */
145  private static final String ATTR_ENCRYPTION_PASSPHRASE_FILE =
146       "ds-task-import-encryption-passphrase-file";
147
148
149
150  /**
151   * The name of the attribute used to specify the attributes to exclude from
152   * entries being imported.
153   */
154  private static final String ATTR_EXCLUDE_ATTRIBUTE =
155       "ds-task-import-exclude-attribute";
156
157
158
159  /**
160   * The name of the attribute used to specify the base DNs of branches to
161   * exclude from the import.
162   */
163  private static final String ATTR_EXCLUDE_BRANCH =
164       "ds-task-import-exclude-branch";
165
166
167
168  /**
169   * The name of the attribute used to specify the filters used to determine
170   * whether to exclude an entry from the import.
171   */
172  private static final String ATTR_EXCLUDE_FILTER =
173       "ds-task-import-exclude-filter";
174
175
176
177  /**
178   * The name of the attribute used to specify the attributes to include in
179   * entries being imported.
180   */
181  private static final String ATTR_INCLUDE_ATTRIBUTE =
182       "ds-task-import-include-attribute";
183
184
185
186  /**
187   * The name of the attribute used to specify the base DNs of branches to
188   * include in the import.
189   */
190  private static final String ATTR_INCLUDE_BRANCH =
191       "ds-task-import-include-branch";
192
193
194
195  /**
196   * The name of the attribute used to specify the filters used to determine
197   * whether to include an entry in the import.
198   */
199  private static final String ATTR_INCLUDE_FILTER =
200       "ds-task-import-include-filter";
201
202
203
204  /**
205   * The name of the attribute used to indicate whether the LDIF data is
206   * compressed.
207   */
208  private static final String ATTR_IS_COMPRESSED =
209       "ds-task-import-is-compressed";
210
211
212
213  /**
214   * The name of the attribute used to indicate whether the LDIF data is
215   * encrypted.
216   */
217  private static final String ATTR_IS_ENCRYPTED =
218       "ds-task-import-is-encrypted";
219
220
221
222  /**
223   * The name of the attribute used to specify the paths to the LDIF files to be
224   * imported.
225   */
226  private static final String ATTR_LDIF_FILE = "ds-task-import-ldif-file";
227
228
229
230  /**
231   * The name of the attribute used to indicate whether to overwrite an existing
232   * reject file.
233   */
234  private static final String ATTR_OVERWRITE_REJECTS =
235       "ds-task-import-overwrite-rejects";
236
237
238
239  /**
240   * The name of the attribute used to specify the path to the reject file.
241   */
242  private static final String ATTR_REJECT_FILE = "ds-task-import-reject-file";
243
244
245
246  /**
247   * The name of the attribute used to indicate whether to replace existing
248   * entries when appending to a database rather than overwriting it.
249   */
250  private static final String ATTR_REPLACE_EXISTING =
251       "ds-task-import-replace-existing";
252
253
254
255  /**
256   * The name of the attribute used to indicate whether to skip schema
257   * validation for the import.
258   */
259  private static final String ATTR_SKIP_SCHEMA_VALIDATION =
260       "ds-task-import-skip-schema-validation";
261
262
263
264  /**
265   * The name of the attribute used to indicate whether to strip illegal
266   * trailing spaces from LDIF records rather than rejecting those records.
267   */
268  private static final String ATTR_STRIP_TRAILING_SPACES =
269       "ds-task-import-strip-trailing-spaces";
270
271
272
273  /**
274   * The task property for the backend ID.
275   */
276  private static final TaskProperty PROPERTY_BACKEND_ID =
277       new TaskProperty(ATTR_BACKEND_ID, INFO_DISPLAY_NAME_BACKEND_ID.get(),
278                        INFO_DESCRIPTION_BACKEND_ID_IMPORT.get(), String.class,
279                        false, false, false);
280
281
282
283  /**
284   * The task property for the LDIF files.
285   */
286  private static final TaskProperty PROPERTY_LDIF_FILE =
287       new TaskProperty(ATTR_LDIF_FILE, INFO_DISPLAY_NAME_LDIF_FILE.get(),
288                        INFO_DESCRIPTION_LDIF_FILE_IMPORT.get(), String.class,
289                        true, true, false);
290
291
292
293  /**
294   * The task property for the append flag.
295   */
296  private static final TaskProperty PROPERTY_APPEND =
297       new TaskProperty(ATTR_APPEND, INFO_DISPLAY_NAME_APPEND_TO_DB.get(),
298                        INFO_DESCRIPTION_APPEND_TO_DB.get(), Boolean.class,
299                        false, false, true);
300
301
302
303  /**
304   * The task property for the replace existing flag.
305   */
306  private static final TaskProperty PROPERTY_REPLACE_EXISTING =
307       new TaskProperty(ATTR_REPLACE_EXISTING,
308                        INFO_DISPLAY_NAME_REPLACE_EXISTING.get(),
309                        INFO_DESCRIPTION_REPLACE_EXISTING.get(), Boolean.class,
310                        false, false, true);
311
312
313
314  /**
315   * The task property for the reject file.
316   */
317  private static final TaskProperty PROPERTY_REJECT_FILE =
318       new TaskProperty(ATTR_REJECT_FILE,
319                        INFO_DISPLAY_NAME_REJECT_FILE.get(),
320                        INFO_DESCRIPTION_REJECT_FILE.get(), String.class,
321                        false, false, false);
322
323
324
325  /**
326   * The task property for the overwrite rejects flag.
327   */
328  private static final TaskProperty PROPERTY_OVERWRITE_REJECTS =
329       new TaskProperty(ATTR_OVERWRITE_REJECTS,
330                        INFO_DISPLAY_NAME_OVERWRITE_REJECTS.get(),
331                        INFO_DESCRIPTION_OVERWRITE_REJECTS.get(), Boolean.class,
332                        false, false, true);
333
334
335
336  /**
337   * The task property for the clear backend flag.
338   */
339  private static final TaskProperty PROPERTY_CLEAR_BACKEND =
340       new TaskProperty(ATTR_CLEAR_BACKEND,
341                        INFO_DISPLAY_NAME_CLEAR_BACKEND.get(),
342                        INFO_DESCRIPTION_CLEAR_BACKEND.get(), Boolean.class,
343                        false, false, true);
344
345
346
347  /**
348   * The task property for the include branches.
349   */
350  private static final TaskProperty PROPERTY_INCLUDE_BRANCH =
351       new TaskProperty(ATTR_INCLUDE_BRANCH,
352                        INFO_DISPLAY_NAME_INCLUDE_BRANCH.get(),
353                        INFO_DESCRIPTION_INCLUDE_BRANCH_IMPORT.get(),
354                        String.class, false, true, true);
355
356
357
358  /**
359   * The task property for the exclude branches.
360   */
361  private static final TaskProperty PROPERTY_EXCLUDE_BRANCH =
362       new TaskProperty(ATTR_EXCLUDE_BRANCH,
363                        INFO_DISPLAY_NAME_EXCLUDE_BRANCH.get(),
364                        INFO_DESCRIPTION_EXCLUDE_BRANCH_IMPORT.get(),
365                        String.class, false, true, true);
366
367
368
369  /**
370   * The task property for the include filters.
371   */
372  private static final TaskProperty PROPERTY_INCLUDE_FILTER =
373       new TaskProperty(ATTR_INCLUDE_FILTER,
374                        INFO_DISPLAY_NAME_INCLUDE_FILTER.get(),
375                        INFO_DESCRIPTION_INCLUDE_FILTER_IMPORT.get(),
376                        String.class, false, true, true);
377
378
379
380  /**
381   * The task property for the exclude filters.
382   */
383  private static final TaskProperty PROPERTY_EXCLUDE_FILTER =
384       new TaskProperty(ATTR_EXCLUDE_FILTER,
385                        INFO_DISPLAY_NAME_EXCLUDE_FILTER.get(),
386                        INFO_DESCRIPTION_EXCLUDE_FILTER_IMPORT.get(),
387                        String.class, false, true, true);
388
389
390
391  /**
392   * The task property for the include attributes.
393   */
394  private static final TaskProperty PROPERTY_INCLUDE_ATTRIBUTE =
395       new TaskProperty(ATTR_INCLUDE_ATTRIBUTE,
396                        INFO_DISPLAY_NAME_INCLUDE_ATTRIBUTE.get(),
397                        INFO_DESCRIPTION_INCLUDE_ATTRIBUTE_IMPORT.get(),
398                        String.class, false, true, true);
399
400
401
402  /**
403   * The task property for the exclude attributes.
404   */
405  private static final TaskProperty PROPERTY_EXCLUDE_ATTRIBUTE =
406       new TaskProperty(ATTR_EXCLUDE_ATTRIBUTE,
407                        INFO_DISPLAY_NAME_EXCLUDE_ATTRIBUTE.get(),
408                        INFO_DESCRIPTION_EXCLUDE_ATTRIBUTE_IMPORT.get(),
409                        String.class, false, true, true);
410
411
412
413  /**
414   * The task property for the is compressed flag.
415   */
416  private static final TaskProperty PROPERTY_IS_COMPRESSED =
417       new TaskProperty(ATTR_IS_COMPRESSED,
418                        INFO_DISPLAY_NAME_IS_COMPRESSED_IMPORT.get(),
419                        INFO_DESCRIPTION_IS_COMPRESSED_IMPORT.get(),
420                        Boolean.class, false, false, false);
421
422
423
424  /**
425   * The task property for the is encrypted flag.
426   */
427  private static final TaskProperty PROPERTY_IS_ENCRYPTED =
428       new TaskProperty(ATTR_IS_ENCRYPTED,
429                        INFO_DISPLAY_NAME_IS_ENCRYPTED_IMPORT.get(),
430                        INFO_DESCRIPTION_IS_ENCRYPTED_IMPORT.get(),
431                        Boolean.class, false, false, false);
432
433
434
435  /**
436   * The task property that will be used for the encryption passphrase file.
437   */
438  private static final TaskProperty PROPERTY_ENCRYPTION_PASSPHRASE_FILE =
439       new TaskProperty(ATTR_ENCRYPTION_PASSPHRASE_FILE,
440            INFO_DISPLAY_NAME_ENCRYPTION_PASSPHRASE_FILE.get(),
441            INFO_DESCRIPTION_ENCRYPTION_PASSPHRASE_FILE.get(),
442            String.class, false, false, true);
443
444
445
446  /**
447   * The task property for the skip schema validation flag.
448   */
449  private static final TaskProperty PROPERTY_SKIP_SCHEMA_VALIDATION =
450       new TaskProperty(ATTR_SKIP_SCHEMA_VALIDATION,
451                        INFO_DISPLAY_NAME_SKIP_SCHEMA_VALIDATION.get(),
452                        INFO_DESCRIPTION_SKIP_SCHEMA_VALIDATION.get(),
453                        Boolean.class, false, false, false);
454
455
456
457  /**
458   * The task property for the strip trailing spaces flag.
459   */
460  private static final TaskProperty PROPERTY_STRIP_TRAILING_SPACES =
461       new TaskProperty(ATTR_STRIP_TRAILING_SPACES,
462                        INFO_DISPLAY_NAME_STRIP_TRAILING_SPACES.get(),
463                        INFO_DESCRIPTION_STRIP_TRAILING_SPACES.get(),
464                        Boolean.class, false, false, false);
465
466
467
468  /**
469   * The name of the object class used in import task entries.
470   */
471  private static final String OC_IMPORT_TASK = "ds-task-import";
472
473
474
475  /**
476   * The serial version UID for this serializable class.
477   */
478  private static final long serialVersionUID = 9114913680318281750L;
479
480
481
482  // Indicates whether to append to the database rather than overwriting it.
483  private final boolean append;
484
485  // Indicates whether to clear the entire backend when importing by base DN.
486  private final boolean clearBackend;
487
488  // Indicates whether the LDIF data is compressed.
489  private final boolean isCompressed;
490
491  // Indicates whether the LDIF data is encrypted.
492  private final boolean isEncrypted;
493
494  // Indicates whether to overwrite an existing reject file.
495  private final boolean overwriteRejects;
496
497  // Indicates whether to replace existing entries when appending to the DB.
498  private final boolean replaceExisting;
499
500  // Indicates whether to skip schema validation for the import.
501  private final boolean skipSchemaValidation;
502
503  // Indicates whether to strip illegal trailing spaces from LDIF records rather
504  // than rejecting them.
505  private final boolean stripTrailingSpaces;
506
507  // The set of exclude attributes for the import.
508  private final List<String> excludeAttributes;
509
510  // The set of exclude branches for the import.
511  private final List<String> excludeBranches;
512
513  // The set of exclude filters for the import.
514  private final List<String> excludeFilters;
515
516  // The set of include attributes for the import.
517  private final List<String> includeAttributes;
518
519  // The set of include branches for the import.
520  private final List<String> includeBranches;
521
522  // The set of include filters for the import.
523  private final List<String> includeFilters;
524
525  // The paths to the LDIF files to be imported.
526  private final List<String> ldifFiles;
527
528  // The backend ID of the backend to import.
529  private final String backendID;
530
531  // The path to a file containing the passphrase to use to generate the
532  // encryption key.
533  private final String encryptionPassphraseFile;
534
535  // The path to the reject file to write.
536  private final String rejectFile;
537
538
539
540  /**
541   * Creates a new uninitialized import task instance which should only be used
542   * for obtaining general information about this task, including the task name,
543   * description, and supported properties.  Attempts to use a task created with
544   * this constructor for any other reason will likely fail.
545   */
546  public ImportTask()
547  {
548    append = false;
549    clearBackend = false;
550    isCompressed = false;
551    isEncrypted = false;
552    overwriteRejects = false;
553    replaceExisting = false;
554    skipSchemaValidation = false;
555    stripTrailingSpaces = false;
556    encryptionPassphraseFile = null;
557    excludeAttributes = null;
558    excludeBranches = null;
559    excludeFilters = null;
560    includeAttributes = null;
561    includeBranches = null;
562    includeFilters = null;
563    ldifFiles = null;
564    backendID = null;
565    rejectFile = null;
566  }
567
568
569
570  /**
571   * Creates a new import task with the provided backend.  It will overwrite
572   * the contents of the backend with the data in the provided LDIF file.
573   *
574   * @param  taskID     The task ID to use for this task.  If it is {@code null}
575   *                    then a UUID will be generated for use as the task ID.
576   * @param  backendID  The backend ID of the backend into which the data should
577   *                    be imported.  It must not be {@code null}.
578   * @param  ldifFile   The path to the LDIF file containing the data to be
579   *                    imported.  It may be an absolute path or a path relative
580   *                    to the server install root.  It must not be
581   *                    {@code null}.
582   */
583  public ImportTask(final String taskID, final String backendID,
584                    final String ldifFile)
585  {
586    this(taskID, Arrays.asList(ldifFile), backendID, false, false, null, false,
587         true, null, null, null, null, null, null, false, false, false, null,
588         null, null, null, null);
589
590    ensureNotNull(ldifFile);
591  }
592
593
594
595  /**
596   * Creates a new import task with the provided information.
597   *
598   * @param  taskID                  The task ID to use for this task.  If it is
599   *                                 {@code null} then a UUID will be generated
600   *                                 for use as the task ID.
601   * @param  ldifFiles               The paths to the LDIF file containing the
602   *                                 data to be imported.  The paths may be
603   *                                 either absolute or relative to the server
604   *                                 install root.  It must not be {@code null}
605   *                                 or empty..
606   * @param  backendID               The backend ID of the backend into which
607   *                                 the data should be imported.  It may be
608   *                                 {@code null} only if one or more include
609   *                                 branches was specified.
610   * @param  append                  Indicates whether to append to the existing
611   *                                 data rather than overwriting it.
612   * @param  replaceExisting         Indicates whether to replace existing
613   *                                 entries when appending to the database.
614   * @param  rejectFile              The path to a file into which information
615   *                                 will be written about rejected entries.  It
616   *                                 may be {@code null} if no reject file is to
617   *                                 be maintained.
618   * @param  overwriteRejects        Indicates whether to overwrite an existing
619   *                                 rejects file rather than appending to it.
620   * @param  clearBackend            Indicates whether to clear data below all
621   *                                 base DNs in the backend.  It must be
622   *                                 {@code true} if the backend was specified
623   *                                 using a backend ID and no include branches
624   *                                 are specified and {@code append} is
625   *                                 {@code false}.  If include branches were
626   *                                 specified, or if data is being appended to
627   *                                 the backend, then it may be either
628   *                                 {@code true} or {@code false}.
629   * @param  includeBranches         The set of base DNs below which to import
630   *                                 the data.  It may be {@code null} or empty
631   *                                 if a backend ID was specified and data
632   *                                 should be imported below all base DNs
633   *                                 defined in the backend.  Otherwise, at
634   *                                 least one include branch must be provided,
635   *                                 and any data not under one of the include
636   *                                 branches will be excluded from the import.
637   *                                 All include branches must be within the
638   *                                 scope of the same backend.
639   * @param  excludeBranches         The set of base DNs to exclude from the
640   *                                 import.  It may be {@code null} or empty if
641   *                                 no data is to be excluded based on its
642   *                                 location.
643   * @param  includeFilters          The set of filters to use to determine
644   *                                 which entries should be included in the
645   *                                 import.  It may be {@code null} or empty if
646   *                                 no data is to be excluded based on its
647   *                                 content.
648   * @param  excludeFilters          The set of filters to use to determine
649   *                                 which entries should be excluded from the
650   *                                 import.  It may be {@code null} or empty if
651   *                                 no data is to be excluded based on its
652   *                                 content.
653   * @param  includeAttributes       The set of attributes to include in the
654   *                                 entries being imported.  It may be
655   *                                 {@code null} or empty if no attributes
656   *                                 should be excluded from the import.
657   * @param  excludeAttributes       The set of attributes to exclude from the
658   *                                 entries being imported.  It may be
659   *                                 {@code null} or empty if no attributes
660   *                                 should be excluded from the import.
661   * @param  isCompressed            Indicates whether the data in the LDIF
662   *                                 file(s) is compressed.
663   * @param  isEncrypted             Indicates whether the data in the LDIF
664   *                                 file(s) is encrypted.
665   * @param  skipSchemaValidation    Indicates whether to skip schema validation
666   *                                 during the import.
667   * @param  scheduledStartTime      The time that this task should start
668   *                                 running.
669   * @param  dependencyIDs           The list of task IDs that will be required
670   *                                 to complete before this task will be
671   *                                 eligible to start.
672   * @param  failedDependencyAction  Indicates what action should be taken if
673   *                                 any of the dependencies for this task do
674   *                                 not complete successfully.
675   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
676   *                                 that should be notified when this task
677   *                                 completes.
678   * @param  notifyOnError           The list of e-mail addresses of individuals
679   *                                 that should be notified if this task does
680   *                                 not complete successfully.
681   */
682  public ImportTask(final String taskID, final List<String> ldifFiles,
683                    final String backendID, final boolean append,
684                    final boolean replaceExisting, final String rejectFile,
685                    final boolean overwriteRejects, final boolean clearBackend,
686                    final List<String> includeBranches,
687                    final List<String> excludeBranches,
688                    final List<String> includeFilters,
689                    final List<String> excludeFilters,
690                    final List<String> includeAttributes,
691                    final List<String> excludeAttributes,
692                    final boolean isCompressed, final boolean isEncrypted,
693                    final boolean skipSchemaValidation,
694                    final Date scheduledStartTime,
695                    final List<String> dependencyIDs,
696                    final FailedDependencyAction failedDependencyAction,
697                    final List<String> notifyOnCompletion,
698                    final List<String> notifyOnError)
699  {
700    this(taskID, ldifFiles, backendID, append, replaceExisting, rejectFile,
701         overwriteRejects, clearBackend, includeBranches, excludeBranches,
702         includeFilters, excludeFilters, includeAttributes, excludeAttributes,
703         isCompressed, isEncrypted, skipSchemaValidation, false,
704         scheduledStartTime, dependencyIDs, failedDependencyAction,
705         notifyOnCompletion, notifyOnError);
706  }
707
708
709
710  /**
711   * Creates a new import task with the provided information.
712   *
713   * @param  taskID                  The task ID to use for this task.  If it is
714   *                                 {@code null} then a UUID will be generated
715   *                                 for use as the task ID.
716   * @param  ldifFiles               The paths to the LDIF file containing the
717   *                                 data to be imported.  The paths may be
718   *                                 either absolute or relative to the server
719   *                                 install root.  It must not be {@code null}
720   *                                 or empty..
721   * @param  backendID               The backend ID of the backend into which
722   *                                 the data should be imported.  It may be
723   *                                 {@code null} only if one or more include
724   *                                 branches was specified.
725   * @param  append                  Indicates whether to append to the existing
726   *                                 data rather than overwriting it.
727   * @param  replaceExisting         Indicates whether to replace existing
728   *                                 entries when appending to the database.
729   * @param  rejectFile              The path to a file into which information
730   *                                 will be written about rejected entries.  It
731   *                                 may be {@code null} if no reject file is to
732   *                                 be maintained.
733   * @param  overwriteRejects        Indicates whether to overwrite an existing
734   *                                 rejects file rather than appending to it.
735   * @param  clearBackend            Indicates whether to clear data below all
736   *                                 base DNs in the backend.  It must be
737   *                                 {@code true} if the backend was specified
738   *                                 using a backend ID and no include branches
739   *                                 are specified and {@code append} is
740   *                                 {@code false}.  If include branches were
741   *                                 specified, or if data is being appended to
742   *                                 the backend, then it may be either
743   *                                 {@code true} or {@code false}.
744   * @param  includeBranches         The set of base DNs below which to import
745   *                                 the data.  It may be {@code null} or empty
746   *                                 if a backend ID was specified and data
747   *                                 should be imported below all base DNs
748   *                                 defined in the backend.  Otherwise, at
749   *                                 least one include branch must be provided,
750   *                                 and any data not under one of the include
751   *                                 branches will be excluded from the import.
752   *                                 All include branches must be within the
753   *                                 scope of the same backend.
754   * @param  excludeBranches         The set of base DNs to exclude from the
755   *                                 import.  It may be {@code null} or empty if
756   *                                 no data is to be excluded based on its
757   *                                 location.
758   * @param  includeFilters          The set of filters to use to determine
759   *                                 which entries should be included in the
760   *                                 import.  It may be {@code null} or empty if
761   *                                 no data is to be excluded based on its
762   *                                 content.
763   * @param  excludeFilters          The set of filters to use to determine
764   *                                 which entries should be excluded from the
765   *                                 import.  It may be {@code null} or empty if
766   *                                 no data is to be excluded based on its
767   *                                 content.
768   * @param  includeAttributes       The set of attributes to include in the
769   *                                 entries being imported.  It may be
770   *                                 {@code null} or empty if no attributes
771   *                                 should be excluded from the import.
772   * @param  excludeAttributes       The set of attributes to exclude from the
773   *                                 entries being imported.  It may be
774   *                                 {@code null} or empty if no attributes
775   *                                 should be excluded from the import.
776   * @param  isCompressed            Indicates whether the data in the LDIF
777   *                                 file(s) is compressed.
778   * @param  isEncrypted             Indicates whether the data in the LDIF
779   *                                 file(s) is encrypted.
780   * @param  skipSchemaValidation    Indicates whether to skip schema validation
781   *                                 during the import.
782   * @param  stripTrailingSpaces     Indicates whether to strip illegal trailing
783   *                                 spaces found in LDIF records rather than
784   *                                 rejecting those records.
785   * @param  scheduledStartTime      The time that this task should start
786   *                                 running.
787   * @param  dependencyIDs           The list of task IDs that will be required
788   *                                 to complete before this task will be
789   *                                 eligible to start.
790   * @param  failedDependencyAction  Indicates what action should be taken if
791   *                                 any of the dependencies for this task do
792   *                                 not complete successfully.
793   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
794   *                                 that should be notified when this task
795   *                                 completes.
796   * @param  notifyOnError           The list of e-mail addresses of individuals
797   *                                 that should be notified if this task does
798   *                                 not complete successfully.
799   */
800  public ImportTask(final String taskID, final List<String> ldifFiles,
801                    final String backendID, final boolean append,
802                    final boolean replaceExisting, final String rejectFile,
803                    final boolean overwriteRejects, final boolean clearBackend,
804                    final List<String> includeBranches,
805                    final List<String> excludeBranches,
806                    final List<String> includeFilters,
807                    final List<String> excludeFilters,
808                    final List<String> includeAttributes,
809                    final List<String> excludeAttributes,
810                    final boolean isCompressed, final boolean isEncrypted,
811                    final boolean skipSchemaValidation,
812                    final boolean stripTrailingSpaces,
813                    final Date scheduledStartTime,
814                    final List<String> dependencyIDs,
815                    final FailedDependencyAction failedDependencyAction,
816                    final List<String> notifyOnCompletion,
817                    final List<String> notifyOnError)
818  {
819    this(taskID, ldifFiles, backendID, append, replaceExisting, rejectFile,
820         overwriteRejects, clearBackend, includeBranches, excludeBranches,
821         includeFilters, excludeFilters, includeAttributes, excludeAttributes,
822         isCompressed, isEncrypted, null, skipSchemaValidation,
823         stripTrailingSpaces, scheduledStartTime, dependencyIDs,
824         failedDependencyAction, notifyOnCompletion, notifyOnError);
825  }
826
827
828
829  /**
830   * Creates a new import task with the provided information.
831   *
832   * @param  taskID                    The task ID to use for this task.  If it
833   *                                   is {@code null} then a UUID will be
834   *                                   generated for use as the task ID.
835   * @param  ldifFiles                 The paths to the LDIF file containing the
836   *                                   data to be imported.  The paths may be
837   *                                   either absolute or relative to the server
838   *                                   install root.  It must not be
839   *                                   {@code null} or empty.
840   * @param  backendID                 The backend ID of the backend into which
841   *                                   the data should be imported.  It may be
842   *                                   {@code null} only if one or more include
843   *                                   branches was specified.
844   * @param  append                    Indicates whether to append to the
845   *                                   existing data rather than overwriting it.
846   * @param  replaceExisting           Indicates whether to replace existing
847   *                                   entries when appending to the database.
848   * @param  rejectFile                The path to a file into which
849   *                                   information will be written about
850   *                                   rejected entries.  It may be {@code null}
851   *                                   if no reject file is to be maintained.
852   * @param  overwriteRejects          Indicates whether to overwrite an
853   *                                   existing rejects file rather than
854   *                                   appending to it.
855   * @param  clearBackend              Indicates whether to clear data below all
856   *                                   base DNs in the backend.  It must be
857   *                                   {@code true} if the backend was specified
858   *                                   using a backend ID and no include
859   *                                   branches are specified and {@code append}
860   *                                   is {@code false}.  If include branches
861   *                                   were specified, or if data is being
862   *                                   appended to the backend, then it may be
863   *                                   either {@code true} or {@code false}.
864   * @param  includeBranches           The set of base DNs below which to import
865   *                                   the data.  It may be {@code null} or
866   *                                   empty if a backend ID was specified and
867   *                                   data should be imported below all base
868   *                                   DNs defined in the backend.  Otherwise,
869   *                                   at least one include branch must be
870   *                                   provided, and any data not under one of
871   *                                   the include branches will be excluded
872   *                                   from the import.  All include branches
873   *                                   must be within the scope of the same
874   *                                   backend.
875   * @param  excludeBranches           The set of base DNs to exclude from the
876   *                                   import.  It may be {@code null} or empty
877   *                                   if no data is to be excluded based on its
878   *                                   location.
879   * @param  includeFilters            The set of filters to use to determine
880   *                                   which entries should be included in the
881   *                                   import.  It may be {@code null} or empty
882   *                                   if no data is to be excluded based on its
883   *                                   content.
884   * @param  excludeFilters            The set of filters to use to determine
885   *                                   which entries should be excluded from the
886   *                                   import.  It may be {@code null} or empty
887   *                                   if no data is to be excluded based on its
888   *                                   content.
889   * @param  includeAttributes         The set of attributes to include in the
890   *                                   entries being imported.  It may be
891   *                                   {@code null} or empty if no attributes
892   *                                   should be excluded from the import.
893   * @param  excludeAttributes         The set of attributes to exclude from the
894   *                                   entries being imported.  It may be
895   *                                   {@code null} or empty if no attributes
896   *                                   should be excluded from the import.
897   * @param  isCompressed              Indicates whether the data in the LDIF
898   *                                   file(s) is compressed.
899   * @param  isEncrypted               Indicates whether the data in the LDIF
900   *                                   file(s) is encrypted.
901   * @param  encryptionPassphraseFile  The path to a file containing the
902   *                                   passphrase to use to generate the
903   *                                   encryption key.  It amy be {@code null}
904   *                                   if the backup is not to be encrypted, or
905   *                                   if the key should be obtained in some
906   *                                   other way.
907   * @param  skipSchemaValidation      Indicates whether to skip schema
908   *                                   validation during the import.
909   * @param  stripTrailingSpaces       Indicates whether to strip illegal
910   *                                   trailing spaces found in LDIF records
911   *                                   rather than rejecting those records.
912   * @param  scheduledStartTime        The time that this task should start
913   *                                   running.
914   * @param  dependencyIDs             The list of task IDs that will be
915   *                                   required to complete before this task
916   *                                   will be eligible to start.
917   * @param  failedDependencyAction    Indicates what action should be taken if
918   *                                   any of the dependencies for this task do
919   *                                   not complete successfully.
920   * @param  notifyOnCompletion        The list of e-mail addresses of
921   *                                   individuals that should be notified when
922   *                                   this task completes.
923   * @param  notifyOnError             The list of e-mail addresses of
924   *                                   individuals that should be notified if
925   *                                   this task does not complete successfully.
926   */
927  public ImportTask(final String taskID, final List<String> ldifFiles,
928                    final String backendID, final boolean append,
929                    final boolean replaceExisting, final String rejectFile,
930                    final boolean overwriteRejects, final boolean clearBackend,
931                    final List<String> includeBranches,
932                    final List<String> excludeBranches,
933                    final List<String> includeFilters,
934                    final List<String> excludeFilters,
935                    final List<String> includeAttributes,
936                    final List<String> excludeAttributes,
937                    final boolean isCompressed, final boolean isEncrypted,
938                    final String encryptionPassphraseFile,
939                    final boolean skipSchemaValidation,
940                    final boolean stripTrailingSpaces,
941                    final Date scheduledStartTime,
942                    final List<String> dependencyIDs,
943                    final FailedDependencyAction failedDependencyAction,
944                    final List<String> notifyOnCompletion,
945                    final List<String> notifyOnError)
946  {
947    super(taskID, IMPORT_TASK_CLASS, scheduledStartTime,
948          dependencyIDs, failedDependencyAction, notifyOnCompletion,
949          notifyOnError);
950
951    ensureNotNull(ldifFiles);
952    ensureFalse(ldifFiles.isEmpty(),
953                "ImportTask.ldifFiles must not be empty.");
954    ensureFalse((backendID == null) &&
955                ((includeBranches == null) || includeBranches.isEmpty()));
956    ensureTrue(clearBackend || append ||
957                ((includeBranches != null) && (! includeBranches.isEmpty())));
958
959    this.ldifFiles = Collections.unmodifiableList(ldifFiles);
960    this.backendID = backendID;
961    this.append = append;
962    this.replaceExisting = replaceExisting;
963    this.rejectFile = rejectFile;
964    this.overwriteRejects = overwriteRejects;
965    this.clearBackend = clearBackend;
966    this.isCompressed = isCompressed;
967    this.isEncrypted = isEncrypted;
968    this.encryptionPassphraseFile = encryptionPassphraseFile;
969    this.skipSchemaValidation = skipSchemaValidation;
970    this.stripTrailingSpaces = stripTrailingSpaces;
971
972    if (includeBranches == null)
973    {
974      this.includeBranches = Collections.emptyList();
975    }
976    else
977    {
978      this.includeBranches = Collections.unmodifiableList(includeBranches);
979    }
980
981    if (excludeBranches == null)
982    {
983      this.excludeBranches = Collections.emptyList();
984    }
985    else
986    {
987      this.excludeBranches = Collections.unmodifiableList(excludeBranches);
988    }
989
990    if (includeFilters == null)
991    {
992      this.includeFilters = Collections.emptyList();
993    }
994    else
995    {
996      this.includeFilters = Collections.unmodifiableList(includeFilters);
997    }
998
999    if (excludeFilters == null)
1000    {
1001      this.excludeFilters = Collections.emptyList();
1002    }
1003    else
1004    {
1005      this.excludeFilters = Collections.unmodifiableList(excludeFilters);
1006    }
1007
1008    if (includeAttributes == null)
1009    {
1010      this.includeAttributes = Collections.emptyList();
1011    }
1012    else
1013    {
1014      this.includeAttributes = Collections.unmodifiableList(includeAttributes);
1015    }
1016
1017    if (excludeAttributes == null)
1018    {
1019      this.excludeAttributes = Collections.emptyList();
1020    }
1021    else
1022    {
1023      this.excludeAttributes = Collections.unmodifiableList(excludeAttributes);
1024    }
1025  }
1026
1027
1028
1029  /**
1030   * Creates a new import task from the provided entry.
1031   *
1032   * @param  entry  The entry to use to create this import task.
1033   *
1034   * @throws  TaskException  If the provided entry cannot be parsed as an import
1035   *                         task entry.
1036   */
1037  public ImportTask(final Entry entry)
1038         throws TaskException
1039  {
1040    super(entry);
1041
1042
1043    // Get the set of LDIF files.  It must be present.
1044    final String[] files = entry.getAttributeValues(ATTR_LDIF_FILE);
1045    if ((files == null) || (files.length == 0))
1046    {
1047      throw new TaskException(ERR_IMPORT_TASK_NO_LDIF.get(getTaskEntryDN()));
1048    }
1049    else
1050    {
1051      ldifFiles = Collections.unmodifiableList(Arrays.asList(files));
1052    }
1053
1054
1055    // Get the backend ID.  It may be absent.
1056    backendID = entry.getAttributeValue(ATTR_BACKEND_ID);
1057
1058
1059    // Get the append flag.  It may be absent.
1060    append = parseBooleanValue(entry, ATTR_APPEND, false);
1061
1062
1063    // Get the replaceExisting flag.  It may be absent.
1064    replaceExisting = parseBooleanValue(entry, ATTR_REPLACE_EXISTING, false);
1065
1066
1067    // Get the reject file.  It may be absent.
1068    rejectFile = entry.getAttributeValue(ATTR_REJECT_FILE);
1069
1070
1071    // Get the overwriteRejects flag.  It may be absent.
1072    overwriteRejects = parseBooleanValue(entry, ATTR_OVERWRITE_REJECTS, false);
1073
1074
1075    // Get the clearBackend flag.  It may be absent.
1076    clearBackend = parseBooleanValue(entry, ATTR_CLEAR_BACKEND, false);
1077
1078
1079    // Get the list of include branches.  It may be absent.
1080    includeBranches = parseStringList(entry, ATTR_INCLUDE_BRANCH);
1081
1082
1083    // Get the list of exclude branches.  It may be absent.
1084    excludeBranches = parseStringList(entry, ATTR_EXCLUDE_BRANCH);
1085
1086
1087    // Get the list of include filters.  It may be absent.
1088    includeFilters = parseStringList(entry, ATTR_INCLUDE_FILTER);
1089
1090
1091    // Get the list of exclude filters.  It may be absent.
1092    excludeFilters = parseStringList(entry, ATTR_EXCLUDE_FILTER);
1093
1094
1095    // Get the list of include attributes.  It may be absent.
1096    includeAttributes = parseStringList(entry, ATTR_INCLUDE_ATTRIBUTE);
1097
1098
1099    // Get the list of exclude attributes.  It may be absent.
1100    excludeAttributes = parseStringList(entry, ATTR_EXCLUDE_ATTRIBUTE);
1101
1102
1103    // Get the isCompressed flag.  It may be absent.
1104    isCompressed = parseBooleanValue(entry, ATTR_IS_COMPRESSED, false);
1105
1106
1107    // Get the isEncrypted flag.  It may be absent.
1108    isEncrypted = parseBooleanValue(entry, ATTR_IS_ENCRYPTED, false);
1109
1110
1111    // Get the path to the encryption passphrase file.  It may be absent.
1112    encryptionPassphraseFile =
1113         entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE);
1114
1115
1116    // Get the skipSchemaValidation flag.  It may be absent.
1117    skipSchemaValidation = parseBooleanValue(entry, ATTR_SKIP_SCHEMA_VALIDATION,
1118                                             false);
1119
1120
1121    // Get the stripTrailingSpaces flag.  It may be absent.
1122    stripTrailingSpaces = parseBooleanValue(entry, ATTR_STRIP_TRAILING_SPACES,
1123                                            false);
1124  }
1125
1126
1127
1128  /**
1129   * Creates a new import task from the provided set of task properties.
1130   *
1131   * @param  properties  The set of task properties and their corresponding
1132   *                     values to use for the task.  It must not be
1133   *                     {@code null}.
1134   *
1135   * @throws  TaskException  If the provided set of properties cannot be used to
1136   *                         create a valid import task.
1137   */
1138  public ImportTask(final Map<TaskProperty,List<Object>> properties)
1139         throws TaskException
1140  {
1141    super(IMPORT_TASK_CLASS, properties);
1142
1143    boolean  a  = false;
1144    boolean  c  = false;
1145    boolean  cB = true;
1146    boolean  e  = false;
1147    boolean  o  = false;
1148    boolean  r  = false;
1149    boolean  ss = false;
1150    boolean  st = false;
1151    String   b  = null;
1152    String   pF = null;
1153    String   rF = null;
1154    String[] eA = StaticUtils.NO_STRINGS;
1155    String[] eB = StaticUtils.NO_STRINGS;
1156    String[] eF = StaticUtils.NO_STRINGS;
1157    String[] iA = StaticUtils.NO_STRINGS;
1158    String[] iB = StaticUtils.NO_STRINGS;
1159    String[] iF = StaticUtils.NO_STRINGS;
1160    String[] l  = StaticUtils.NO_STRINGS;
1161
1162    for (final Map.Entry<TaskProperty,List<Object>> entry :
1163         properties.entrySet())
1164    {
1165      final TaskProperty p = entry.getKey();
1166      final String attrName = p.getAttributeName();
1167      final List<Object> values = entry.getValue();
1168
1169      if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID))
1170      {
1171        b = parseString(p, values, b);
1172      }
1173      else if (attrName.equalsIgnoreCase(ATTR_LDIF_FILE))
1174      {
1175        l = parseStrings(p, values, l);
1176      }
1177      else if (attrName.equalsIgnoreCase(ATTR_APPEND))
1178      {
1179        a = parseBoolean(p, values, a);
1180      }
1181      else if (attrName.equalsIgnoreCase(ATTR_REPLACE_EXISTING))
1182      {
1183        r = parseBoolean(p, values, r);
1184      }
1185      else if (attrName.equalsIgnoreCase(ATTR_REJECT_FILE))
1186      {
1187        rF = parseString(p, values, rF);
1188      }
1189      else if (attrName.equalsIgnoreCase(ATTR_OVERWRITE_REJECTS))
1190      {
1191        o = parseBoolean(p, values, o);
1192      }
1193      else if (attrName.equalsIgnoreCase(ATTR_CLEAR_BACKEND))
1194      {
1195        cB = parseBoolean(p, values, cB);
1196      }
1197      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_BRANCH))
1198      {
1199        iB = parseStrings(p, values, iB);
1200      }
1201      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_BRANCH))
1202      {
1203        eB = parseStrings(p, values, eB);
1204      }
1205      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_FILTER))
1206      {
1207        iF = parseStrings(p, values, iF);
1208      }
1209      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_FILTER))
1210      {
1211        eF = parseStrings(p, values, eF);
1212      }
1213      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_ATTRIBUTE))
1214      {
1215        iA = parseStrings(p, values, iA);
1216      }
1217      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_ATTRIBUTE))
1218      {
1219        eA = parseStrings(p, values, eA);
1220      }
1221      else if (attrName.equalsIgnoreCase(ATTR_IS_COMPRESSED))
1222      {
1223        c = parseBoolean(p, values, c);
1224      }
1225      else if (attrName.equalsIgnoreCase(ATTR_IS_ENCRYPTED))
1226      {
1227        e = parseBoolean(p, values, e);
1228      }
1229      else if (attrName.equalsIgnoreCase(ATTR_ENCRYPTION_PASSPHRASE_FILE))
1230      {
1231        pF = parseString(p, values, pF);
1232      }
1233      else if (attrName.equalsIgnoreCase(ATTR_SKIP_SCHEMA_VALIDATION))
1234      {
1235        ss = parseBoolean(p, values, ss);
1236      }
1237      else if (attrName.equalsIgnoreCase(ATTR_STRIP_TRAILING_SPACES))
1238      {
1239        st = parseBoolean(p, values, st);
1240      }
1241    }
1242
1243    if ((b == null) && (iB.length == 0))
1244    {
1245      throw new TaskException(
1246                     ERR_IMPORT_TASK_NO_BACKEND_ID_OR_INCLUDE_BRANCHES.get(
1247                          getTaskEntryDN()));
1248    }
1249
1250    if (l == null)
1251    {
1252      throw new TaskException(ERR_IMPORT_TASK_NO_LDIF.get(
1253                                   getTaskEntryDN()));
1254    }
1255
1256    backendID = b;
1257    ldifFiles = Collections.unmodifiableList(Arrays.asList(l));
1258    append = a;
1259    replaceExisting = r;
1260    rejectFile = rF;
1261    overwriteRejects = o;
1262    clearBackend = cB;
1263    includeAttributes = Collections.unmodifiableList(Arrays.asList(iA));
1264    excludeAttributes = Collections.unmodifiableList(Arrays.asList(eA));
1265    includeBranches = Collections.unmodifiableList(Arrays.asList(iB));
1266    excludeBranches = Collections.unmodifiableList(Arrays.asList(eB));
1267    includeFilters = Collections.unmodifiableList(Arrays.asList(iF));
1268    excludeFilters = Collections.unmodifiableList(Arrays.asList(eF));
1269    isCompressed = c;
1270    isEncrypted = e;
1271    encryptionPassphraseFile = pF;
1272    skipSchemaValidation = ss;
1273    stripTrailingSpaces = st;
1274  }
1275
1276
1277
1278  /**
1279   * {@inheritDoc}
1280   */
1281  @Override()
1282  public String getTaskName()
1283  {
1284    return INFO_TASK_NAME_IMPORT.get();
1285  }
1286
1287
1288
1289  /**
1290   * {@inheritDoc}
1291   */
1292  @Override()
1293  public String getTaskDescription()
1294  {
1295    return INFO_TASK_DESCRIPTION_IMPORT.get();
1296  }
1297
1298
1299
1300  /**
1301   * Retrieves the paths to the LDIF files containing the data to be imported.
1302   * The paths may be absolute or relative to the server root.
1303   *
1304   * @return  The paths to the LDIF files containing the data to be imported.
1305   */
1306  public List<String> getLDIFFiles()
1307  {
1308    return ldifFiles;
1309  }
1310
1311
1312
1313  /**
1314   * Retrieves the backend ID of the backend into which the data should be
1315   * imported.
1316   *
1317   * @return  The backend ID of the backend into which the data should be
1318   *          imported, or {@code null} if no backend ID was specified and the
1319   *          backend will be identified from the include branches.
1320   */
1321  public String getBackendID()
1322  {
1323    return backendID;
1324  }
1325
1326
1327
1328  /**
1329   * Indicates whether the import should append to the data in the backend
1330   * rather than clearing the backend before performing the import.
1331   *
1332   * @return  {@code true} if the contents of the existing backend should be
1333   *          retained and the new data appended to it, or {@code false} if the
1334   *          existing content should be cleared prior to performing the import.
1335   */
1336  public boolean append()
1337  {
1338    return append;
1339  }
1340
1341
1342
1343  /**
1344   * Indicates whether to replace existing entries when appending data to the
1345   * backend.  This is only applicable if {@code append()} returns {@code true}.
1346   *
1347   * @return  {@code true} if entries already present in the backend should be
1348   *          replaced if that entry is also present in the LDIF file, or
1349   *          {@code false} if entries already present in the backend should be
1350   *          retained and the corresponding entry contained in the LDIF should
1351   *          be skipped.
1352   */
1353  public boolean replaceExistingEntries()
1354  {
1355    return replaceExisting;
1356  }
1357
1358
1359
1360  /**
1361   * Retrieves the path to a file to which rejected entries should be written.
1362   *
1363   * @return  The path to a file to which rejected entries should be written, or
1364   *          {@code null} if a rejected entries file should not be maintained.
1365   */
1366  public String getRejectFile()
1367  {
1368    return rejectFile;
1369  }
1370
1371
1372
1373  /**
1374   * Indicates whether an existing reject file should be overwritten rather than
1375   * appending to it.
1376   *
1377   * @return  {@code true} if an existing reject file should be overwritten, or
1378   *          {@code false} if the server should append to it.
1379   */
1380  public boolean overwriteRejectFile()
1381  {
1382    return overwriteRejects;
1383  }
1384
1385
1386
1387  /**
1388   * Indicates whether data below all base DNs defined in the backend should be
1389   * cleared before performing the import.  This is not applicable if the import
1390   * is to append to the backend, or if the backend only has a single base DN.
1391   *
1392   * @return  {@code true} if data below all base DNs in the backend should be
1393   *          cleared, or {@code false} if only data below the base DNs that
1394   *          correspond to the configured include branches should be cleared.
1395   */
1396  public boolean clearBackend()
1397  {
1398    return clearBackend;
1399  }
1400
1401
1402
1403  /**
1404   * Retrieves the list of base DNs for branches that should be included in the
1405   * import.
1406   *
1407   * @return  The set of base DNs for branches that should be included in the
1408   *          import, or an empty list if data should be imported from all base
1409   *          DNs in the associated backend.
1410   */
1411  public List<String> getIncludeBranches()
1412  {
1413    return includeBranches;
1414  }
1415
1416
1417
1418  /**
1419   * Retrieves the list of base DNs of branches that should be excluded from the
1420   * import.
1421   *
1422   * @return  The list of base DNs of branches that should be excluded from the
1423   *          import, or an empty list if no entries should be excluded from the
1424   *          import based on their location.
1425   */
1426  public List<String> getExcludeBranches()
1427  {
1428    return excludeBranches;
1429  }
1430
1431
1432
1433  /**
1434   * Retrieves the list of search filters that may be used to identify which
1435   * entries should be included in the import.
1436   *
1437   * @return  The list of search filters that may be used to identify which
1438   *          entries should be included in the import, or an empty list if no
1439   *          entries should be excluded from the import based on their content.
1440   */
1441  public List<String> getIncludeFilters()
1442  {
1443    return includeFilters;
1444  }
1445
1446
1447
1448  /**
1449   * Retrieves the list of search filters that may be used to identify which
1450   * entries should be excluded from the import.
1451   *
1452   * @return  The list of search filters that may be used to identify which
1453   *          entries should be excluded from the import, or an empty list if no
1454   *          entries should be excluded from the import based on their content.
1455   */
1456  public List<String> getExcludeFilters()
1457  {
1458    return excludeFilters;
1459  }
1460
1461
1462
1463  /**
1464   * Retrieves the list of attributes that should be included in the imported
1465   * entries.
1466   *
1467   * @return  The list of attributes that should be included in the imported
1468   *          entries, or an empty list if no attributes should be excluded.
1469   */
1470  public List<String> getIncludeAttributes()
1471  {
1472    return includeAttributes;
1473  }
1474
1475
1476
1477  /**
1478   * Retrieves the list of attributes that should be excluded from the imported
1479   * entries.
1480   *
1481   * @return  The list of attributes that should be excluded from the imported
1482   *          entries, or an empty list if no attributes should be excluded.
1483   */
1484  public List<String> getExcludeAttributes()
1485  {
1486    return excludeAttributes;
1487  }
1488
1489
1490
1491  /**
1492   * Indicates whether the LDIF data to import is compressed.
1493   *
1494   * @return  {@code true} if the LDIF data to import is compressed, or
1495   *          {@code false} if not.
1496   */
1497  public boolean isCompressed()
1498  {
1499    return isCompressed;
1500  }
1501
1502
1503
1504  /**
1505   * Indicates whether the LDIF data to import is encrypted.
1506   *
1507   * @return  {@code true} if the LDIF data to import is encrypted, or
1508   *          {@code false} if not.
1509   */
1510  public boolean isEncrypted()
1511  {
1512    return isEncrypted;
1513  }
1514
1515
1516
1517  /**
1518   * Retrieves the path to a file that contains the passphrase to use to
1519   * generate the encryption key.
1520   *
1521   * @return  The path to a file that contains the passphrase to use to
1522   *          generate the encryption key, or {@code null} if the LDIF file is
1523   *          not encrypted or if the encryption key should be obtained through
1524   *          some other means.
1525   */
1526  public String getEncryptionPassphraseFile()
1527  {
1528    return encryptionPassphraseFile;
1529  }
1530
1531
1532
1533  /**
1534   * Indicates whether the server should skip schema validation processing when
1535   * performing the import.
1536   *
1537   * @return  {@code true} if the server should skip schema validation
1538   *          processing when performing the import, or {@code false} if not.
1539   */
1540  public boolean skipSchemaValidation()
1541  {
1542    return skipSchemaValidation;
1543  }
1544
1545
1546
1547  /**
1548   * Indicates whether the server should strip off any illegal trailing spaces
1549   * found in LDIF records rather than rejecting those records.
1550   *
1551   * @return  {@code true} if the server should strip off any illegal trailing
1552   *          spaces found in LDIF records, or {@code false} if it should reject
1553   *          any records containing illegal trailing spaces.
1554   */
1555  public boolean stripTrailingSpaces()
1556  {
1557    return stripTrailingSpaces;
1558  }
1559
1560
1561
1562  /**
1563   * {@inheritDoc}
1564   */
1565  @Override()
1566  protected List<String> getAdditionalObjectClasses()
1567  {
1568    return Arrays.asList(OC_IMPORT_TASK);
1569  }
1570
1571
1572
1573  /**
1574   * {@inheritDoc}
1575   */
1576  @Override()
1577  protected List<Attribute> getAdditionalAttributes()
1578  {
1579    final ArrayList<Attribute> attrs = new ArrayList<Attribute>(20);
1580
1581    attrs.add(new Attribute(ATTR_LDIF_FILE, ldifFiles));
1582    attrs.add(new Attribute(ATTR_APPEND, String.valueOf(append)));
1583    attrs.add(new Attribute(ATTR_REPLACE_EXISTING,
1584                            String.valueOf(replaceExisting)));
1585    attrs.add(new Attribute(ATTR_OVERWRITE_REJECTS,
1586                            String.valueOf(overwriteRejects)));
1587    attrs.add(new Attribute(ATTR_CLEAR_BACKEND, String.valueOf(clearBackend)));
1588    attrs.add(new Attribute(ATTR_IS_COMPRESSED, String.valueOf(isCompressed)));
1589    attrs.add(new Attribute(ATTR_IS_ENCRYPTED, String.valueOf(isEncrypted)));
1590    attrs.add(new Attribute(ATTR_SKIP_SCHEMA_VALIDATION,
1591                            String.valueOf(skipSchemaValidation)));
1592
1593    if (stripTrailingSpaces)
1594    {
1595      attrs.add(new Attribute(ATTR_STRIP_TRAILING_SPACES,
1596           String.valueOf(stripTrailingSpaces)));
1597    }
1598
1599    if (backendID != null)
1600    {
1601      attrs.add(new Attribute(ATTR_BACKEND_ID, backendID));
1602    }
1603
1604    if (rejectFile != null)
1605    {
1606      attrs.add(new Attribute(ATTR_REJECT_FILE, rejectFile));
1607    }
1608
1609    if (! includeBranches.isEmpty())
1610    {
1611      attrs.add(new Attribute(ATTR_INCLUDE_BRANCH, includeBranches));
1612    }
1613
1614    if (! excludeBranches.isEmpty())
1615    {
1616      attrs.add(new Attribute(ATTR_EXCLUDE_BRANCH, excludeBranches));
1617    }
1618
1619    if (! includeAttributes.isEmpty())
1620    {
1621      attrs.add(new Attribute(ATTR_INCLUDE_ATTRIBUTE, includeAttributes));
1622    }
1623
1624    if (! excludeAttributes.isEmpty())
1625    {
1626      attrs.add(new Attribute(ATTR_EXCLUDE_ATTRIBUTE, excludeAttributes));
1627    }
1628
1629    if (! includeFilters.isEmpty())
1630    {
1631      attrs.add(new Attribute(ATTR_INCLUDE_FILTER, includeFilters));
1632    }
1633
1634    if (! excludeFilters.isEmpty())
1635    {
1636      attrs.add(new Attribute(ATTR_EXCLUDE_FILTER, excludeFilters));
1637    }
1638
1639    if (encryptionPassphraseFile != null)
1640    {
1641      attrs.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE,
1642           encryptionPassphraseFile));
1643    }
1644
1645    return attrs;
1646  }
1647
1648
1649
1650  /**
1651   * {@inheritDoc}
1652   */
1653  @Override()
1654  public List<TaskProperty> getTaskSpecificProperties()
1655  {
1656    final List<TaskProperty> propList = Arrays.asList(
1657         PROPERTY_BACKEND_ID,
1658         PROPERTY_LDIF_FILE,
1659         PROPERTY_APPEND,
1660         PROPERTY_REPLACE_EXISTING,
1661         PROPERTY_REJECT_FILE,
1662         PROPERTY_OVERWRITE_REJECTS,
1663         PROPERTY_CLEAR_BACKEND,
1664         PROPERTY_INCLUDE_BRANCH,
1665         PROPERTY_EXCLUDE_BRANCH,
1666         PROPERTY_INCLUDE_FILTER,
1667         PROPERTY_EXCLUDE_FILTER,
1668         PROPERTY_INCLUDE_ATTRIBUTE,
1669         PROPERTY_EXCLUDE_ATTRIBUTE,
1670         PROPERTY_IS_COMPRESSED,
1671         PROPERTY_IS_ENCRYPTED,
1672         PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1673         PROPERTY_SKIP_SCHEMA_VALIDATION,
1674         PROPERTY_STRIP_TRAILING_SPACES);
1675
1676    return Collections.unmodifiableList(propList);
1677  }
1678
1679
1680
1681  /**
1682   * {@inheritDoc}
1683   */
1684  @Override()
1685  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
1686  {
1687    final LinkedHashMap<TaskProperty,List<Object>> props =
1688         new LinkedHashMap<TaskProperty,List<Object>>();
1689
1690    if (backendID == null)
1691    {
1692      props.put(PROPERTY_BACKEND_ID, Collections.emptyList());
1693    }
1694    else
1695    {
1696      props.put(PROPERTY_BACKEND_ID,
1697                Collections.<Object>unmodifiableList(Arrays.asList(backendID)));
1698    }
1699
1700    props.put(PROPERTY_LDIF_FILE,
1701              Collections.<Object>unmodifiableList(ldifFiles));
1702
1703    props.put(PROPERTY_APPEND,
1704              Collections.<Object>unmodifiableList(Arrays.asList(append)));
1705
1706    props.put(PROPERTY_REPLACE_EXISTING,
1707              Collections.<Object>unmodifiableList(Arrays.asList(
1708                   replaceExisting)));
1709
1710    if (rejectFile == null)
1711    {
1712      props.put(PROPERTY_REJECT_FILE, Collections.emptyList());
1713    }
1714    else
1715    {
1716      props.put(PROPERTY_REJECT_FILE,
1717                Collections.<Object>unmodifiableList(Arrays.asList(
1718                     rejectFile)));
1719    }
1720
1721    props.put(PROPERTY_OVERWRITE_REJECTS,
1722              Collections.<Object>unmodifiableList(Arrays.asList(
1723                   overwriteRejects)));
1724
1725    props.put(PROPERTY_CLEAR_BACKEND,
1726              Collections.<Object>unmodifiableList(Arrays.asList(
1727                   clearBackend)));
1728
1729    props.put(PROPERTY_INCLUDE_BRANCH,
1730              Collections.<Object>unmodifiableList(includeBranches));
1731
1732    props.put(PROPERTY_EXCLUDE_BRANCH,
1733              Collections.<Object>unmodifiableList(excludeBranches));
1734
1735    props.put(PROPERTY_INCLUDE_FILTER,
1736              Collections.<Object>unmodifiableList(includeFilters));
1737
1738    props.put(PROPERTY_EXCLUDE_FILTER,
1739              Collections.<Object>unmodifiableList(excludeFilters));
1740
1741    props.put(PROPERTY_INCLUDE_ATTRIBUTE,
1742              Collections.<Object>unmodifiableList(includeAttributes));
1743
1744    props.put(PROPERTY_EXCLUDE_ATTRIBUTE,
1745              Collections.<Object>unmodifiableList(excludeAttributes));
1746
1747    props.put(PROPERTY_IS_COMPRESSED,
1748              Collections.<Object>unmodifiableList(Arrays.asList(
1749                   isCompressed)));
1750
1751    props.put(PROPERTY_IS_ENCRYPTED,
1752              Collections.<Object>unmodifiableList(Arrays.asList(
1753                   isEncrypted)));
1754
1755    if (encryptionPassphraseFile == null)
1756    {
1757      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, Collections.emptyList());
1758    }
1759    else
1760    {
1761      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1762         Collections.<Object>unmodifiableList(Arrays.asList(
1763              encryptionPassphraseFile)));
1764    }
1765
1766    props.put(PROPERTY_SKIP_SCHEMA_VALIDATION,
1767              Collections.<Object>unmodifiableList(Arrays.asList(
1768                   skipSchemaValidation)));
1769
1770    props.put(PROPERTY_STRIP_TRAILING_SPACES,
1771              Collections.<Object>unmodifiableList(Arrays.asList(
1772                   stripTrailingSpaces)));
1773
1774    props.putAll(super.getTaskPropertyValues());
1775    return Collections.unmodifiableMap(props);
1776  }
1777}