001/*
002 * Copyright 2008-2019 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright (C) 2015-2019 Ping Identity Corporation
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021package com.unboundid.ldap.sdk.unboundidds.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;
039import com.unboundid.util.Validator;
040
041import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
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
053 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
054 *   for proprietary functionality or for external specifications that are not
055 *   considered stable or mature enough to be guaranteed to work in an
056 *   interoperable way with 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, Collections.singletonList(ldifFile), backendID, false, false,
587         null, false, true, null, null, null, null, null, null, false, false,
588         false, null, null, null, null, null);
589
590    Validator.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    this(taskID, ldifFiles, backendID, append, replaceExisting, rejectFile,
948         overwriteRejects, clearBackend, includeBranches, excludeBranches,
949         includeFilters, excludeFilters, includeAttributes,
950         excludeAttributes, isCompressed, isEncrypted,
951         encryptionPassphraseFile, skipSchemaValidation, stripTrailingSpaces,
952         scheduledStartTime, dependencyIDs, failedDependencyAction, null,
953         notifyOnCompletion, null, notifyOnError, null, null, null);
954  }
955
956
957
958  /**
959   * Creates a new import task with the provided information.
960   *
961   * @param  taskID                    The task ID to use for this task.  If it
962   *                                   is {@code null} then a UUID will be
963   *                                   generated for use as the task ID.
964   * @param  ldifFiles                 The paths to the LDIF file containing the
965   *                                   data to be imported.  The paths may be
966   *                                   either absolute or relative to the server
967   *                                   install root.  It must not be
968   *                                   {@code null} or empty.
969   * @param  backendID                 The backend ID of the backend into which
970   *                                   the data should be imported.  It may be
971   *                                   {@code null} only if one or more include
972   *                                   branches was specified.
973   * @param  append                    Indicates whether to append to the
974   *                                   existing data rather than overwriting it.
975   * @param  replaceExisting           Indicates whether to replace existing
976   *                                   entries when appending to the database.
977   * @param  rejectFile                The path to a file into which
978   *                                   information will be written about
979   *                                   rejected entries.  It may be {@code null}
980   *                                   if no reject file is to be maintained.
981   * @param  overwriteRejects          Indicates whether to overwrite an
982   *                                   existing rejects file rather than
983   *                                   appending to it.
984   * @param  clearBackend              Indicates whether to clear data below all
985   *                                   base DNs in the backend.  It must be
986   *                                   {@code true} if the backend was specified
987   *                                   using a backend ID and no include
988   *                                   branches are specified and {@code append}
989   *                                   is {@code false}.  If include branches
990   *                                   were specified, or if data is being
991   *                                   appended to the backend, then it may be
992   *                                   either {@code true} or {@code false}.
993   * @param  includeBranches           The set of base DNs below which to import
994   *                                   the data.  It may be {@code null} or
995   *                                   empty if a backend ID was specified and
996   *                                   data should be imported below all base
997   *                                   DNs defined in the backend.  Otherwise,
998   *                                   at least one include branch must be
999   *                                   provided, and any data not under one of
1000   *                                   the include branches will be excluded
1001   *                                   from the import.  All include branches
1002   *                                   must be within the scope of the same
1003   *                                   backend.
1004   * @param  excludeBranches           The set of base DNs to exclude from the
1005   *                                   import.  It may be {@code null} or empty
1006   *                                   if no data is to be excluded based on its
1007   *                                   location.
1008   * @param  includeFilters            The set of filters to use to determine
1009   *                                   which entries should be included in the
1010   *                                   import.  It may be {@code null} or empty
1011   *                                   if no data is to be excluded based on its
1012   *                                   content.
1013   * @param  excludeFilters            The set of filters to use to determine
1014   *                                   which entries should be excluded from the
1015   *                                   import.  It may be {@code null} or empty
1016   *                                   if no data is to be excluded based on its
1017   *                                   content.
1018   * @param  includeAttributes         The set of attributes to include in the
1019   *                                   entries being imported.  It may be
1020   *                                   {@code null} or empty if no attributes
1021   *                                   should be excluded from the import.
1022   * @param  excludeAttributes         The set of attributes to exclude from the
1023   *                                   entries being imported.  It may be
1024   *                                   {@code null} or empty if no attributes
1025   *                                   should be excluded from the import.
1026   * @param  isCompressed              Indicates whether the data in the LDIF
1027   *                                   file(s) is compressed.
1028   * @param  isEncrypted               Indicates whether the data in the LDIF
1029   *                                   file(s) is encrypted.
1030   * @param  encryptionPassphraseFile  The path to a file containing the
1031   *                                   passphrase to use to generate the
1032   *                                   encryption key.  It amy be {@code null}
1033   *                                   if the backup is not to be encrypted, or
1034   *                                   if the key should be obtained in some
1035   *                                   other way.
1036   * @param  skipSchemaValidation      Indicates whether to skip schema
1037   *                                   validation during the import.
1038   * @param  stripTrailingSpaces       Indicates whether to strip illegal
1039   *                                   trailing spaces found in LDIF records
1040   *                                   rather than rejecting those records.
1041   * @param  scheduledStartTime        The time that this task should start
1042   *                                   running.
1043   * @param  dependencyIDs             The list of task IDs that will be
1044   *                                   required to complete before this task
1045   *                                   will be eligible to start.
1046   * @param  failedDependencyAction    Indicates what action should be taken if
1047   *                                   any of the dependencies for this task do
1048   *                                   not complete successfully.
1049   * @param  notifyOnStart             The list of e-mail addresses of
1050   *                                   individuals that should be notified when
1051   *                                   this task starts running.
1052   * @param  notifyOnCompletion        The list of e-mail addresses of
1053   *                                   individuals that should be notified when
1054   *                                   this task completes.
1055   * @param  notifyOnSuccess           The list of e-mail addresses of
1056   *                                   individuals that should be notified if
1057   *                                   this task completes successfully.
1058   * @param  notifyOnError             The list of e-mail addresses of
1059   *                                   individuals that should be notified if
1060   *                                   this task does not complete successfully.
1061   * @param  alertOnStart              Indicates whether the server should send
1062   *                                   an alert notification when this task
1063   *                                   starts.
1064   * @param  alertOnSuccess            Indicates whether the server should send
1065   *                                   an alert notification if this task
1066   *                                   completes successfully.
1067   * @param  alertOnError              Indicates whether the server should send
1068   *                                   an alert notification if this task fails
1069   *                                   to complete successfully.
1070   */
1071  public ImportTask(final String taskID, final List<String> ldifFiles,
1072                    final String backendID, final boolean append,
1073                    final boolean replaceExisting, final String rejectFile,
1074                    final boolean overwriteRejects, final boolean clearBackend,
1075                    final List<String> includeBranches,
1076                    final List<String> excludeBranches,
1077                    final List<String> includeFilters,
1078                    final List<String> excludeFilters,
1079                    final List<String> includeAttributes,
1080                    final List<String> excludeAttributes,
1081                    final boolean isCompressed, final boolean isEncrypted,
1082                    final String encryptionPassphraseFile,
1083                    final boolean skipSchemaValidation,
1084                    final boolean stripTrailingSpaces,
1085                    final Date scheduledStartTime,
1086                    final List<String> dependencyIDs,
1087                    final FailedDependencyAction failedDependencyAction,
1088                    final List<String> notifyOnStart,
1089                    final List<String> notifyOnCompletion,
1090                    final List<String> notifyOnSuccess,
1091                    final List<String> notifyOnError,
1092                    final Boolean alertOnStart, final Boolean alertOnSuccess,
1093                    final Boolean alertOnError)
1094  {
1095    super(taskID, IMPORT_TASK_CLASS, scheduledStartTime,
1096         dependencyIDs, failedDependencyAction, notifyOnStart,
1097         notifyOnCompletion, notifyOnSuccess, notifyOnError, alertOnStart,
1098         alertOnSuccess, alertOnError);
1099
1100    Validator.ensureNotNull(ldifFiles);
1101    Validator.ensureFalse(ldifFiles.isEmpty(),
1102         "ImportTask.ldifFiles must not be empty.");
1103    Validator.ensureFalse((backendID == null) &&
1104         ((includeBranches == null) || includeBranches.isEmpty()));
1105    Validator.ensureTrue(clearBackend || append ||
1106         ((includeBranches != null) && (! includeBranches.isEmpty())));
1107
1108    this.ldifFiles = Collections.unmodifiableList(ldifFiles);
1109    this.backendID = backendID;
1110    this.append = append;
1111    this.replaceExisting = replaceExisting;
1112    this.rejectFile = rejectFile;
1113    this.overwriteRejects = overwriteRejects;
1114    this.clearBackend = clearBackend;
1115    this.isCompressed = isCompressed;
1116    this.isEncrypted = isEncrypted;
1117    this.encryptionPassphraseFile = encryptionPassphraseFile;
1118    this.skipSchemaValidation = skipSchemaValidation;
1119    this.stripTrailingSpaces = stripTrailingSpaces;
1120
1121    if (includeBranches == null)
1122    {
1123      this.includeBranches = Collections.emptyList();
1124    }
1125    else
1126    {
1127      this.includeBranches = Collections.unmodifiableList(includeBranches);
1128    }
1129
1130    if (excludeBranches == null)
1131    {
1132      this.excludeBranches = Collections.emptyList();
1133    }
1134    else
1135    {
1136      this.excludeBranches = Collections.unmodifiableList(excludeBranches);
1137    }
1138
1139    if (includeFilters == null)
1140    {
1141      this.includeFilters = Collections.emptyList();
1142    }
1143    else
1144    {
1145      this.includeFilters = Collections.unmodifiableList(includeFilters);
1146    }
1147
1148    if (excludeFilters == null)
1149    {
1150      this.excludeFilters = Collections.emptyList();
1151    }
1152    else
1153    {
1154      this.excludeFilters = Collections.unmodifiableList(excludeFilters);
1155    }
1156
1157    if (includeAttributes == null)
1158    {
1159      this.includeAttributes = Collections.emptyList();
1160    }
1161    else
1162    {
1163      this.includeAttributes = Collections.unmodifiableList(includeAttributes);
1164    }
1165
1166    if (excludeAttributes == null)
1167    {
1168      this.excludeAttributes = Collections.emptyList();
1169    }
1170    else
1171    {
1172      this.excludeAttributes = Collections.unmodifiableList(excludeAttributes);
1173    }
1174  }
1175
1176
1177
1178  /**
1179   * Creates a new import task from the provided entry.
1180   *
1181   * @param  entry  The entry to use to create this import task.
1182   *
1183   * @throws  TaskException  If the provided entry cannot be parsed as an import
1184   *                         task entry.
1185   */
1186  public ImportTask(final Entry entry)
1187         throws TaskException
1188  {
1189    super(entry);
1190
1191
1192    // Get the set of LDIF files.  It must be present.
1193    final String[] files = entry.getAttributeValues(ATTR_LDIF_FILE);
1194    if ((files == null) || (files.length == 0))
1195    {
1196      throw new TaskException(ERR_IMPORT_TASK_NO_LDIF.get(getTaskEntryDN()));
1197    }
1198    else
1199    {
1200      ldifFiles = Collections.unmodifiableList(Arrays.asList(files));
1201    }
1202
1203
1204    // Get the backend ID.  It may be absent.
1205    backendID = entry.getAttributeValue(ATTR_BACKEND_ID);
1206
1207
1208    // Get the append flag.  It may be absent.
1209    append = parseBooleanValue(entry, ATTR_APPEND, false);
1210
1211
1212    // Get the replaceExisting flag.  It may be absent.
1213    replaceExisting = parseBooleanValue(entry, ATTR_REPLACE_EXISTING, false);
1214
1215
1216    // Get the reject file.  It may be absent.
1217    rejectFile = entry.getAttributeValue(ATTR_REJECT_FILE);
1218
1219
1220    // Get the overwriteRejects flag.  It may be absent.
1221    overwriteRejects = parseBooleanValue(entry, ATTR_OVERWRITE_REJECTS, false);
1222
1223
1224    // Get the clearBackend flag.  It may be absent.
1225    clearBackend = parseBooleanValue(entry, ATTR_CLEAR_BACKEND, false);
1226
1227
1228    // Get the list of include branches.  It may be absent.
1229    includeBranches = parseStringList(entry, ATTR_INCLUDE_BRANCH);
1230
1231
1232    // Get the list of exclude branches.  It may be absent.
1233    excludeBranches = parseStringList(entry, ATTR_EXCLUDE_BRANCH);
1234
1235
1236    // Get the list of include filters.  It may be absent.
1237    includeFilters = parseStringList(entry, ATTR_INCLUDE_FILTER);
1238
1239
1240    // Get the list of exclude filters.  It may be absent.
1241    excludeFilters = parseStringList(entry, ATTR_EXCLUDE_FILTER);
1242
1243
1244    // Get the list of include attributes.  It may be absent.
1245    includeAttributes = parseStringList(entry, ATTR_INCLUDE_ATTRIBUTE);
1246
1247
1248    // Get the list of exclude attributes.  It may be absent.
1249    excludeAttributes = parseStringList(entry, ATTR_EXCLUDE_ATTRIBUTE);
1250
1251
1252    // Get the isCompressed flag.  It may be absent.
1253    isCompressed = parseBooleanValue(entry, ATTR_IS_COMPRESSED, false);
1254
1255
1256    // Get the isEncrypted flag.  It may be absent.
1257    isEncrypted = parseBooleanValue(entry, ATTR_IS_ENCRYPTED, false);
1258
1259
1260    // Get the path to the encryption passphrase file.  It may be absent.
1261    encryptionPassphraseFile =
1262         entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE);
1263
1264
1265    // Get the skipSchemaValidation flag.  It may be absent.
1266    skipSchemaValidation = parseBooleanValue(entry, ATTR_SKIP_SCHEMA_VALIDATION,
1267                                             false);
1268
1269
1270    // Get the stripTrailingSpaces flag.  It may be absent.
1271    stripTrailingSpaces = parseBooleanValue(entry, ATTR_STRIP_TRAILING_SPACES,
1272                                            false);
1273  }
1274
1275
1276
1277  /**
1278   * Creates a new import task from the provided set of task properties.
1279   *
1280   * @param  properties  The set of task properties and their corresponding
1281   *                     values to use for the task.  It must not be
1282   *                     {@code null}.
1283   *
1284   * @throws  TaskException  If the provided set of properties cannot be used to
1285   *                         create a valid import task.
1286   */
1287  public ImportTask(final Map<TaskProperty,List<Object>> properties)
1288         throws TaskException
1289  {
1290    super(IMPORT_TASK_CLASS, properties);
1291
1292    boolean  a  = false;
1293    boolean  c  = false;
1294    boolean  cB = true;
1295    boolean  e  = false;
1296    boolean  o  = false;
1297    boolean  r  = false;
1298    boolean  ss = false;
1299    boolean  st = false;
1300    String   b  = null;
1301    String   pF = null;
1302    String   rF = null;
1303    String[] eA = StaticUtils.NO_STRINGS;
1304    String[] eB = StaticUtils.NO_STRINGS;
1305    String[] eF = StaticUtils.NO_STRINGS;
1306    String[] iA = StaticUtils.NO_STRINGS;
1307    String[] iB = StaticUtils.NO_STRINGS;
1308    String[] iF = StaticUtils.NO_STRINGS;
1309    String[] l  = StaticUtils.NO_STRINGS;
1310
1311    for (final Map.Entry<TaskProperty,List<Object>> entry :
1312         properties.entrySet())
1313    {
1314      final TaskProperty p = entry.getKey();
1315      final String attrName = p.getAttributeName();
1316      final List<Object> values = entry.getValue();
1317
1318      if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID))
1319      {
1320        b = parseString(p, values, b);
1321      }
1322      else if (attrName.equalsIgnoreCase(ATTR_LDIF_FILE))
1323      {
1324        l = parseStrings(p, values, l);
1325      }
1326      else if (attrName.equalsIgnoreCase(ATTR_APPEND))
1327      {
1328        a = parseBoolean(p, values, a);
1329      }
1330      else if (attrName.equalsIgnoreCase(ATTR_REPLACE_EXISTING))
1331      {
1332        r = parseBoolean(p, values, r);
1333      }
1334      else if (attrName.equalsIgnoreCase(ATTR_REJECT_FILE))
1335      {
1336        rF = parseString(p, values, rF);
1337      }
1338      else if (attrName.equalsIgnoreCase(ATTR_OVERWRITE_REJECTS))
1339      {
1340        o = parseBoolean(p, values, o);
1341      }
1342      else if (attrName.equalsIgnoreCase(ATTR_CLEAR_BACKEND))
1343      {
1344        cB = parseBoolean(p, values, cB);
1345      }
1346      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_BRANCH))
1347      {
1348        iB = parseStrings(p, values, iB);
1349      }
1350      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_BRANCH))
1351      {
1352        eB = parseStrings(p, values, eB);
1353      }
1354      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_FILTER))
1355      {
1356        iF = parseStrings(p, values, iF);
1357      }
1358      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_FILTER))
1359      {
1360        eF = parseStrings(p, values, eF);
1361      }
1362      else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_ATTRIBUTE))
1363      {
1364        iA = parseStrings(p, values, iA);
1365      }
1366      else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_ATTRIBUTE))
1367      {
1368        eA = parseStrings(p, values, eA);
1369      }
1370      else if (attrName.equalsIgnoreCase(ATTR_IS_COMPRESSED))
1371      {
1372        c = parseBoolean(p, values, c);
1373      }
1374      else if (attrName.equalsIgnoreCase(ATTR_IS_ENCRYPTED))
1375      {
1376        e = parseBoolean(p, values, e);
1377      }
1378      else if (attrName.equalsIgnoreCase(ATTR_ENCRYPTION_PASSPHRASE_FILE))
1379      {
1380        pF = parseString(p, values, pF);
1381      }
1382      else if (attrName.equalsIgnoreCase(ATTR_SKIP_SCHEMA_VALIDATION))
1383      {
1384        ss = parseBoolean(p, values, ss);
1385      }
1386      else if (attrName.equalsIgnoreCase(ATTR_STRIP_TRAILING_SPACES))
1387      {
1388        st = parseBoolean(p, values, st);
1389      }
1390    }
1391
1392    if ((b == null) && (iB.length == 0))
1393    {
1394      throw new TaskException(
1395                     ERR_IMPORT_TASK_NO_BACKEND_ID_OR_INCLUDE_BRANCHES.get(
1396                          getTaskEntryDN()));
1397    }
1398
1399    if (l == null)
1400    {
1401      throw new TaskException(ERR_IMPORT_TASK_NO_LDIF.get(
1402                                   getTaskEntryDN()));
1403    }
1404
1405    backendID = b;
1406    ldifFiles = Collections.unmodifiableList(Arrays.asList(l));
1407    append = a;
1408    replaceExisting = r;
1409    rejectFile = rF;
1410    overwriteRejects = o;
1411    clearBackend = cB;
1412    includeAttributes = Collections.unmodifiableList(Arrays.asList(iA));
1413    excludeAttributes = Collections.unmodifiableList(Arrays.asList(eA));
1414    includeBranches = Collections.unmodifiableList(Arrays.asList(iB));
1415    excludeBranches = Collections.unmodifiableList(Arrays.asList(eB));
1416    includeFilters = Collections.unmodifiableList(Arrays.asList(iF));
1417    excludeFilters = Collections.unmodifiableList(Arrays.asList(eF));
1418    isCompressed = c;
1419    isEncrypted = e;
1420    encryptionPassphraseFile = pF;
1421    skipSchemaValidation = ss;
1422    stripTrailingSpaces = st;
1423  }
1424
1425
1426
1427  /**
1428   * {@inheritDoc}
1429   */
1430  @Override()
1431  public String getTaskName()
1432  {
1433    return INFO_TASK_NAME_IMPORT.get();
1434  }
1435
1436
1437
1438  /**
1439   * {@inheritDoc}
1440   */
1441  @Override()
1442  public String getTaskDescription()
1443  {
1444    return INFO_TASK_DESCRIPTION_IMPORT.get();
1445  }
1446
1447
1448
1449  /**
1450   * Retrieves the paths to the LDIF files containing the data to be imported.
1451   * The paths may be absolute or relative to the server root.
1452   *
1453   * @return  The paths to the LDIF files containing the data to be imported.
1454   */
1455  public List<String> getLDIFFiles()
1456  {
1457    return ldifFiles;
1458  }
1459
1460
1461
1462  /**
1463   * Retrieves the backend ID of the backend into which the data should be
1464   * imported.
1465   *
1466   * @return  The backend ID of the backend into which the data should be
1467   *          imported, or {@code null} if no backend ID was specified and the
1468   *          backend will be identified from the include branches.
1469   */
1470  public String getBackendID()
1471  {
1472    return backendID;
1473  }
1474
1475
1476
1477  /**
1478   * Indicates whether the import should append to the data in the backend
1479   * rather than clearing the backend before performing the import.
1480   *
1481   * @return  {@code true} if the contents of the existing backend should be
1482   *          retained and the new data appended to it, or {@code false} if the
1483   *          existing content should be cleared prior to performing the import.
1484   */
1485  public boolean append()
1486  {
1487    return append;
1488  }
1489
1490
1491
1492  /**
1493   * Indicates whether to replace existing entries when appending data to the
1494   * backend.  This is only applicable if {@code append()} returns {@code true}.
1495   *
1496   * @return  {@code true} if entries already present in the backend should be
1497   *          replaced if that entry is also present in the LDIF file, or
1498   *          {@code false} if entries already present in the backend should be
1499   *          retained and the corresponding entry contained in the LDIF should
1500   *          be skipped.
1501   */
1502  public boolean replaceExistingEntries()
1503  {
1504    return replaceExisting;
1505  }
1506
1507
1508
1509  /**
1510   * Retrieves the path to a file to which rejected entries should be written.
1511   *
1512   * @return  The path to a file to which rejected entries should be written, or
1513   *          {@code null} if a rejected entries file should not be maintained.
1514   */
1515  public String getRejectFile()
1516  {
1517    return rejectFile;
1518  }
1519
1520
1521
1522  /**
1523   * Indicates whether an existing reject file should be overwritten rather than
1524   * appending to it.
1525   *
1526   * @return  {@code true} if an existing reject file should be overwritten, or
1527   *          {@code false} if the server should append to it.
1528   */
1529  public boolean overwriteRejectFile()
1530  {
1531    return overwriteRejects;
1532  }
1533
1534
1535
1536  /**
1537   * Indicates whether data below all base DNs defined in the backend should be
1538   * cleared before performing the import.  This is not applicable if the import
1539   * is to append to the backend, or if the backend only has a single base DN.
1540   *
1541   * @return  {@code true} if data below all base DNs in the backend should be
1542   *          cleared, or {@code false} if only data below the base DNs that
1543   *          correspond to the configured include branches should be cleared.
1544   */
1545  public boolean clearBackend()
1546  {
1547    return clearBackend;
1548  }
1549
1550
1551
1552  /**
1553   * Retrieves the list of base DNs for branches that should be included in the
1554   * import.
1555   *
1556   * @return  The set of base DNs for branches that should be included in the
1557   *          import, or an empty list if data should be imported from all base
1558   *          DNs in the associated backend.
1559   */
1560  public List<String> getIncludeBranches()
1561  {
1562    return includeBranches;
1563  }
1564
1565
1566
1567  /**
1568   * Retrieves the list of base DNs of branches that should be excluded from the
1569   * import.
1570   *
1571   * @return  The list of base DNs of branches that should be excluded from the
1572   *          import, or an empty list if no entries should be excluded from the
1573   *          import based on their location.
1574   */
1575  public List<String> getExcludeBranches()
1576  {
1577    return excludeBranches;
1578  }
1579
1580
1581
1582  /**
1583   * Retrieves the list of search filters that may be used to identify which
1584   * entries should be included in the import.
1585   *
1586   * @return  The list of search filters that may be used to identify which
1587   *          entries should be included in the import, or an empty list if no
1588   *          entries should be excluded from the import based on their content.
1589   */
1590  public List<String> getIncludeFilters()
1591  {
1592    return includeFilters;
1593  }
1594
1595
1596
1597  /**
1598   * Retrieves the list of search filters that may be used to identify which
1599   * entries should be excluded from the import.
1600   *
1601   * @return  The list of search filters that may be used to identify which
1602   *          entries should be excluded from the import, or an empty list if no
1603   *          entries should be excluded from the import based on their content.
1604   */
1605  public List<String> getExcludeFilters()
1606  {
1607    return excludeFilters;
1608  }
1609
1610
1611
1612  /**
1613   * Retrieves the list of attributes that should be included in the imported
1614   * entries.
1615   *
1616   * @return  The list of attributes that should be included in the imported
1617   *          entries, or an empty list if no attributes should be excluded.
1618   */
1619  public List<String> getIncludeAttributes()
1620  {
1621    return includeAttributes;
1622  }
1623
1624
1625
1626  /**
1627   * Retrieves the list of attributes that should be excluded from the imported
1628   * entries.
1629   *
1630   * @return  The list of attributes that should be excluded from the imported
1631   *          entries, or an empty list if no attributes should be excluded.
1632   */
1633  public List<String> getExcludeAttributes()
1634  {
1635    return excludeAttributes;
1636  }
1637
1638
1639
1640  /**
1641   * Indicates whether the LDIF data to import is compressed.
1642   *
1643   * @return  {@code true} if the LDIF data to import is compressed, or
1644   *          {@code false} if not.
1645   */
1646  public boolean isCompressed()
1647  {
1648    return isCompressed;
1649  }
1650
1651
1652
1653  /**
1654   * Indicates whether the LDIF data to import is encrypted.
1655   *
1656   * @return  {@code true} if the LDIF data to import is encrypted, or
1657   *          {@code false} if not.
1658   */
1659  public boolean isEncrypted()
1660  {
1661    return isEncrypted;
1662  }
1663
1664
1665
1666  /**
1667   * Retrieves the path to a file that contains the passphrase to use to
1668   * generate the encryption key.
1669   *
1670   * @return  The path to a file that contains the passphrase to use to
1671   *          generate the encryption key, or {@code null} if the LDIF file is
1672   *          not encrypted or if the encryption key should be obtained through
1673   *          some other means.
1674   */
1675  public String getEncryptionPassphraseFile()
1676  {
1677    return encryptionPassphraseFile;
1678  }
1679
1680
1681
1682  /**
1683   * Indicates whether the server should skip schema validation processing when
1684   * performing the import.
1685   *
1686   * @return  {@code true} if the server should skip schema validation
1687   *          processing when performing the import, or {@code false} if not.
1688   */
1689  public boolean skipSchemaValidation()
1690  {
1691    return skipSchemaValidation;
1692  }
1693
1694
1695
1696  /**
1697   * Indicates whether the server should strip off any illegal trailing spaces
1698   * found in LDIF records rather than rejecting those records.
1699   *
1700   * @return  {@code true} if the server should strip off any illegal trailing
1701   *          spaces found in LDIF records, or {@code false} if it should reject
1702   *          any records containing illegal trailing spaces.
1703   */
1704  public boolean stripTrailingSpaces()
1705  {
1706    return stripTrailingSpaces;
1707  }
1708
1709
1710
1711  /**
1712   * {@inheritDoc}
1713   */
1714  @Override()
1715  protected List<String> getAdditionalObjectClasses()
1716  {
1717    return Collections.singletonList(OC_IMPORT_TASK);
1718  }
1719
1720
1721
1722  /**
1723   * {@inheritDoc}
1724   */
1725  @Override()
1726  protected List<Attribute> getAdditionalAttributes()
1727  {
1728    final ArrayList<Attribute> attrs = new ArrayList<>(20);
1729
1730    attrs.add(new Attribute(ATTR_LDIF_FILE, ldifFiles));
1731    attrs.add(new Attribute(ATTR_APPEND, String.valueOf(append)));
1732    attrs.add(new Attribute(ATTR_REPLACE_EXISTING,
1733                            String.valueOf(replaceExisting)));
1734    attrs.add(new Attribute(ATTR_OVERWRITE_REJECTS,
1735                            String.valueOf(overwriteRejects)));
1736    attrs.add(new Attribute(ATTR_CLEAR_BACKEND, String.valueOf(clearBackend)));
1737    attrs.add(new Attribute(ATTR_IS_COMPRESSED, String.valueOf(isCompressed)));
1738    attrs.add(new Attribute(ATTR_IS_ENCRYPTED, String.valueOf(isEncrypted)));
1739    attrs.add(new Attribute(ATTR_SKIP_SCHEMA_VALIDATION,
1740                            String.valueOf(skipSchemaValidation)));
1741
1742    if (stripTrailingSpaces)
1743    {
1744      attrs.add(new Attribute(ATTR_STRIP_TRAILING_SPACES,
1745           String.valueOf(stripTrailingSpaces)));
1746    }
1747
1748    if (backendID != null)
1749    {
1750      attrs.add(new Attribute(ATTR_BACKEND_ID, backendID));
1751    }
1752
1753    if (rejectFile != null)
1754    {
1755      attrs.add(new Attribute(ATTR_REJECT_FILE, rejectFile));
1756    }
1757
1758    if (! includeBranches.isEmpty())
1759    {
1760      attrs.add(new Attribute(ATTR_INCLUDE_BRANCH, includeBranches));
1761    }
1762
1763    if (! excludeBranches.isEmpty())
1764    {
1765      attrs.add(new Attribute(ATTR_EXCLUDE_BRANCH, excludeBranches));
1766    }
1767
1768    if (! includeAttributes.isEmpty())
1769    {
1770      attrs.add(new Attribute(ATTR_INCLUDE_ATTRIBUTE, includeAttributes));
1771    }
1772
1773    if (! excludeAttributes.isEmpty())
1774    {
1775      attrs.add(new Attribute(ATTR_EXCLUDE_ATTRIBUTE, excludeAttributes));
1776    }
1777
1778    if (! includeFilters.isEmpty())
1779    {
1780      attrs.add(new Attribute(ATTR_INCLUDE_FILTER, includeFilters));
1781    }
1782
1783    if (! excludeFilters.isEmpty())
1784    {
1785      attrs.add(new Attribute(ATTR_EXCLUDE_FILTER, excludeFilters));
1786    }
1787
1788    if (encryptionPassphraseFile != null)
1789    {
1790      attrs.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE,
1791           encryptionPassphraseFile));
1792    }
1793
1794    return attrs;
1795  }
1796
1797
1798
1799  /**
1800   * {@inheritDoc}
1801   */
1802  @Override()
1803  public List<TaskProperty> getTaskSpecificProperties()
1804  {
1805    final List<TaskProperty> propList = Arrays.asList(
1806         PROPERTY_BACKEND_ID,
1807         PROPERTY_LDIF_FILE,
1808         PROPERTY_APPEND,
1809         PROPERTY_REPLACE_EXISTING,
1810         PROPERTY_REJECT_FILE,
1811         PROPERTY_OVERWRITE_REJECTS,
1812         PROPERTY_CLEAR_BACKEND,
1813         PROPERTY_INCLUDE_BRANCH,
1814         PROPERTY_EXCLUDE_BRANCH,
1815         PROPERTY_INCLUDE_FILTER,
1816         PROPERTY_EXCLUDE_FILTER,
1817         PROPERTY_INCLUDE_ATTRIBUTE,
1818         PROPERTY_EXCLUDE_ATTRIBUTE,
1819         PROPERTY_IS_COMPRESSED,
1820         PROPERTY_IS_ENCRYPTED,
1821         PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1822         PROPERTY_SKIP_SCHEMA_VALIDATION,
1823         PROPERTY_STRIP_TRAILING_SPACES);
1824
1825    return Collections.unmodifiableList(propList);
1826  }
1827
1828
1829
1830  /**
1831   * {@inheritDoc}
1832   */
1833  @Override()
1834  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
1835  {
1836    final LinkedHashMap<TaskProperty,List<Object>> props =
1837         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
1838
1839    if (backendID == null)
1840    {
1841      props.put(PROPERTY_BACKEND_ID, Collections.emptyList());
1842    }
1843    else
1844    {
1845      props.put(PROPERTY_BACKEND_ID,
1846                Collections.<Object>singletonList(backendID));
1847    }
1848
1849    props.put(PROPERTY_LDIF_FILE,
1850              Collections.<Object>unmodifiableList(ldifFiles));
1851
1852    props.put(PROPERTY_APPEND,
1853              Collections.<Object>singletonList(append));
1854
1855    props.put(PROPERTY_REPLACE_EXISTING,
1856              Collections.<Object>singletonList(replaceExisting));
1857
1858    if (rejectFile == null)
1859    {
1860      props.put(PROPERTY_REJECT_FILE, Collections.emptyList());
1861    }
1862    else
1863    {
1864      props.put(PROPERTY_REJECT_FILE,
1865                Collections.<Object>singletonList(rejectFile));
1866    }
1867
1868    props.put(PROPERTY_OVERWRITE_REJECTS,
1869              Collections.<Object>singletonList(overwriteRejects));
1870
1871    props.put(PROPERTY_CLEAR_BACKEND,
1872              Collections.<Object>singletonList(clearBackend));
1873
1874    props.put(PROPERTY_INCLUDE_BRANCH,
1875              Collections.<Object>unmodifiableList(includeBranches));
1876
1877    props.put(PROPERTY_EXCLUDE_BRANCH,
1878              Collections.<Object>unmodifiableList(excludeBranches));
1879
1880    props.put(PROPERTY_INCLUDE_FILTER,
1881              Collections.<Object>unmodifiableList(includeFilters));
1882
1883    props.put(PROPERTY_EXCLUDE_FILTER,
1884              Collections.<Object>unmodifiableList(excludeFilters));
1885
1886    props.put(PROPERTY_INCLUDE_ATTRIBUTE,
1887              Collections.<Object>unmodifiableList(includeAttributes));
1888
1889    props.put(PROPERTY_EXCLUDE_ATTRIBUTE,
1890              Collections.<Object>unmodifiableList(excludeAttributes));
1891
1892    props.put(PROPERTY_IS_COMPRESSED,
1893              Collections.<Object>singletonList(isCompressed));
1894
1895    props.put(PROPERTY_IS_ENCRYPTED,
1896              Collections.<Object>singletonList(isEncrypted));
1897
1898    if (encryptionPassphraseFile == null)
1899    {
1900      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, Collections.emptyList());
1901    }
1902    else
1903    {
1904      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1905         Collections.<Object>singletonList(encryptionPassphraseFile));
1906    }
1907
1908    props.put(PROPERTY_SKIP_SCHEMA_VALIDATION,
1909              Collections.<Object>singletonList(skipSchemaValidation));
1910
1911    props.put(PROPERTY_STRIP_TRAILING_SPACES,
1912              Collections.<Object>singletonList(stripTrailingSpaces));
1913
1914    props.putAll(super.getTaskPropertyValues());
1915    return Collections.unmodifiableMap(props);
1916  }
1917}