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