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.Debug.*;
042    import static com.unboundid.util.Validator.*;
043    
044    
045    
046    /**
047     * <BLOCKQUOTE>
048     *   <B>NOTE:</B>  This class is part of the Commercial Edition of the UnboundID
049     *   LDAP SDK for Java.  It is not available for use in applications that
050     *   include only the Standard Edition of the LDAP SDK, and is not supported for
051     *   use in conjunction with non-UnboundID products.
052     * </BLOCKQUOTE>
053     * This class defines a Directory Server task that can be used to export the
054     * contents of a backend to LDIF.  The properties that are available for use
055     * with this type of task include:
056     * <UL>
057     *   <LI>The backend ID for the backend from which the data is to be exported.
058     *       It must be provided when scheduling a task of this type.</LI>
059     *   <LI>The path (on the server system) and name of the LDIF file to be
060     *       written.  It must be provided when scheduling a task of this type.</LI>
061     *   <LI>A flag that indicates whether to append to any existing file or to
062     *       overwrite it.</LI>
063     *   <LI>An optional list of base DNs for branches that should be included in
064     *       the export.</LI>
065     *   <LI>An optional list of base DNs for branches that should be excluded from
066     *       the export.</LI>
067     *   <LI>An optional list of filters that may be used to determine whether an
068     *       entry should be included in the export.</LI>
069     *   <LI>An optional list of filters that may be used to determine whether an
070     *       entry should be excluded from the export.</LI>
071     *   <LI>An optional list of attributes that should be included in entries that
072     *       are exported.</LI>
073     *   <LI>An optional list of attributes that should be excluded form entries
074     *       that are exported.</LI>
075     *   <LI>An integer value that specifies the column at which long lines should
076     *       be wrapped.  A value less than or equal to zero indicates that no
077     *       wrapping should be performed.</LI>
078     *   <LI>A flag that indicates whether to compress the LDIF data as it is
079     *       written.</LI>
080     *   <LI>A flag that indicates whether to encrypt the LDIF data as it is
081     *       written.</LI>
082     *   <LI>A flag that indicates whether to generate a signature for the LDIF data
083     *       as it is written.</LI>
084     * </UL>
085     */
086    @NotMutable()
087    @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
088    public final class ExportTask
089           extends Task
090    {
091      /**
092       * The fully-qualified name of the Java class that is used for the export
093       * task.
094       */
095      static final String EXPORT_TASK_CLASS =
096           "com.unboundid.directory.server.tasks.ExportTask";
097    
098    
099    
100      /**
101       * The name of the attribute used to indicate whether to append to an existing
102       * file.
103       */
104      private static final String ATTR_APPEND_TO_LDIF =
105           "ds-task-export-append-to-ldif";
106    
107    
108    
109      /**
110       * The name of the attribute used to specify the backend ID of the backend to
111       * export.
112       */
113      private static final String ATTR_BACKEND_ID = "ds-task-export-backend-id";
114    
115    
116    
117      /**
118       * The name of the attribute used to indicate whether the exported LDIF should
119       * be compressed as it is written.
120       */
121      private static final String ATTR_COMPRESS = "ds-task-export-compress-ldif";
122    
123    
124    
125      /**
126       * The name of the attribute used to indicate whether the exported LDIF should
127       * be encrypted as it is written.
128       */
129      private static final String ATTR_ENCRYPT = "ds-task-export-encrypt-ldif";
130    
131    
132    
133      /**
134       * The name of the attribute used to specify the attributes to exclude from
135       * the export.
136       */
137      private static final String ATTR_EXCLUDE_ATTRIBUTE =
138           "ds-task-export-exclude-attribute";
139    
140    
141    
142      /**
143       * The name of the attribute used to specify the base DNs to exclude from the
144       * export.
145       */
146      private static final String ATTR_EXCLUDE_BRANCH =
147           "ds-task-export-exclude-branch";
148    
149    
150    
151      /**
152       * The name of the attribute used to specify the filters to use to identify
153       * entries to exclude from the export.
154       */
155      private static final String ATTR_EXCLUDE_FILTER =
156           "ds-task-export-exclude-filter";
157    
158    
159    
160      /**
161       * The name of the attribute used to specify the attributes to include in the
162       * export.
163       */
164      private static final String ATTR_INCLUDE_ATTRIBUTE =
165           "ds-task-export-include-attribute";
166    
167    
168    
169      /**
170       * The name of the attribute used to specify the base DNs to include in the
171       * export.
172       */
173      private static final String ATTR_INCLUDE_BRANCH =
174           "ds-task-export-include-branch";
175    
176    
177    
178      /**
179       * The name of the attribute used to specify the filters to use to identify
180       * entries to include in the export.
181       */
182      private static final String ATTR_INCLUDE_FILTER =
183           "ds-task-export-include-filter";
184    
185    
186    
187      /**
188       * The name of the attribute used to specify the path to the LDIF file to be
189       * written.
190       */
191      private static final String ATTR_LDIF_FILE = "ds-task-export-ldif-file";
192    
193    
194    
195      /**
196       * The name of the attribute used to indicate whether the exported LDIF should
197       * include a signed hash of the contents.
198       */
199      private static final String ATTR_SIGN = "ds-task-export-sign-hash";
200    
201    
202    
203      /**
204       * The name of the attribute used to specify the column at which to wrap long
205       * lines in the export.
206       */
207      private static final String ATTR_WRAP_COLUMN = "ds-task-export-wrap-column";
208    
209    
210    
211      /**
212       * The name of the object class used in export task entries.
213       */
214      private static final String OC_EXPORT_TASK = "ds-task-export";
215    
216    
217    
218      /**
219       * The task property for the backend ID.
220       */
221      private static final TaskProperty PROPERTY_BACKEND_ID =
222           new TaskProperty(ATTR_BACKEND_ID, INFO_DISPLAY_NAME_BACKEND_ID.get(),
223                            INFO_DESCRIPTION_BACKEND_ID_EXPORT.get(), String.class,
224                            true, false, false);
225    
226    
227    
228      /**
229       * The task property for the LDIF file.
230       */
231      private static final TaskProperty PROPERTY_LDIF_FILE =
232           new TaskProperty(ATTR_LDIF_FILE, INFO_DISPLAY_NAME_LDIF_FILE.get(),
233                            INFO_DESCRIPTION_LDIF_FILE_EXPORT.get(), String.class,
234                            true, false, false);
235    
236    
237    
238      /**
239       * The task property for the append to LDIF flag.
240       */
241      private static final TaskProperty PROPERTY_APPEND_TO_LDIF =
242           new TaskProperty(ATTR_APPEND_TO_LDIF,
243                            INFO_DISPLAY_NAME_APPEND_TO_LDIF.get(),
244                            INFO_DESCRIPTION_APPEND_TO_LDIF.get(), Boolean.class,
245                            false, false, true);
246    
247    
248    
249      /**
250       * The task property for the include branches.
251       */
252      private static final TaskProperty PROPERTY_INCLUDE_BRANCH =
253           new TaskProperty(ATTR_INCLUDE_BRANCH,
254                            INFO_DISPLAY_NAME_INCLUDE_BRANCH.get(),
255                            INFO_DESCRIPTION_INCLUDE_BRANCH_EXPORT.get(),
256                            String.class, false, true, true);
257    
258    
259    
260      /**
261       * The task property for the exclude branches.
262       */
263      private static final TaskProperty PROPERTY_EXCLUDE_BRANCH =
264           new TaskProperty(ATTR_EXCLUDE_BRANCH,
265                            INFO_DISPLAY_NAME_EXCLUDE_BRANCH.get(),
266                            INFO_DESCRIPTION_EXCLUDE_BRANCH_EXPORT.get(),
267                            String.class, false, true, true);
268    
269    
270    
271      /**
272       * The task property for the include filters.
273       */
274      private static final TaskProperty PROPERTY_INCLUDE_FILTER =
275           new TaskProperty(ATTR_INCLUDE_FILTER,
276                            INFO_DISPLAY_NAME_INCLUDE_FILTER.get(),
277                            INFO_DESCRIPTION_INCLUDE_FILTER_EXPORT.get(),
278                            String.class, false, true, true);
279    
280    
281    
282      /**
283       * The task property for the exclude filters.
284       */
285      private static final TaskProperty PROPERTY_EXCLUDE_FILTER =
286           new TaskProperty(ATTR_EXCLUDE_FILTER,
287                            INFO_DISPLAY_NAME_EXCLUDE_FILTER.get(),
288                            INFO_DESCRIPTION_EXCLUDE_FILTER_EXPORT.get(),
289                            String.class, false, true, true);
290    
291    
292    
293      /**
294       * The task property for the include attributes.
295       */
296      private static final TaskProperty PROPERTY_INCLUDE_ATTRIBUTE =
297           new TaskProperty(ATTR_INCLUDE_ATTRIBUTE,
298                            INFO_DISPLAY_NAME_INCLUDE_ATTRIBUTE.get(),
299                            INFO_DESCRIPTION_INCLUDE_ATTRIBUTE_EXPORT.get(),
300                            String.class, false, true, true);
301    
302    
303    
304      /**
305       * The task property for the exclude attributes.
306       */
307      private static final TaskProperty PROPERTY_EXCLUDE_ATTRIBUTE =
308           new TaskProperty(ATTR_EXCLUDE_ATTRIBUTE,
309                            INFO_DISPLAY_NAME_EXCLUDE_ATTRIBUTE.get(),
310                            INFO_DESCRIPTION_EXCLUDE_ATTRIBUTE_EXPORT.get(),
311                            String.class, false, true, true);
312    
313    
314    
315      /**
316       * The task property for the wrap column.
317       */
318      private static final TaskProperty PROPERTY_WRAP_COLUMN =
319           new TaskProperty(ATTR_WRAP_COLUMN, INFO_DISPLAY_NAME_WRAP_COLUMN.get(),
320                            INFO_DESCRIPTION_WRAP_COLUMN.get(), Long.class, false,
321                            false, true);
322    
323    
324    
325      /**
326       * The task property for the compress flag.
327       */
328      private static final TaskProperty PROPERTY_COMPRESS =
329           new TaskProperty(ATTR_COMPRESS, INFO_DISPLAY_NAME_COMPRESS.get(),
330                            INFO_DESCRIPTION_COMPRESS_EXPORT.get(), Boolean.class,
331                            false, false, false);
332    
333    
334    
335      /**
336       * The task property for the encrypt flag.
337       */
338      private static final TaskProperty PROPERTY_ENCRYPT =
339           new TaskProperty(ATTR_ENCRYPT, INFO_DISPLAY_NAME_ENCRYPT.get(),
340                            INFO_DESCRIPTION_ENCRYPT_EXPORT.get(), Boolean.class,
341                            false, false, false);
342    
343    
344    
345      /**
346       * The task property for the sign flag.
347       */
348      private static final TaskProperty PROPERTY_SIGN =
349           new TaskProperty(ATTR_SIGN, INFO_DISPLAY_NAME_SIGN.get(),
350                            INFO_DESCRIPTION_SIGN_EXPORT.get(), Boolean.class,
351                            false, false, false);
352    
353    
354    
355      /**
356       * The serial version UID for this serializable class.
357       */
358      private static final long serialVersionUID = 5489855404880345160L;
359    
360    
361    
362      // Indicates whether to append the data to an existing file.
363      private final boolean appendToLDIF;
364    
365      // Indicates whether to compress the data.
366      private final boolean compress;
367    
368      // Indicates whether to encrypt the data.
369      private final boolean encrypt;
370    
371      // Indicates whether to sign the data.
372      private final boolean sign;
373    
374      // The column at which to wrap long lines.
375      private final int wrapColumn;
376    
377      // The set of attributes to exclude from the export.
378      private final List<String> excludeAttributes;
379    
380      // The set of base DNs to exclude from the export.
381      private final List<String> excludeBranches;
382    
383      // The set of filters to use to identify entries to exclude.
384      private final List<String> excludeFilters;
385    
386      // The set of attributes to include in the export.
387      private final List<String> includeAttributes;
388    
389      // The set of base DNs to include in the export.
390      private final List<String> includeBranches;
391    
392      // The set of filters to use to identify entries to include.
393      private final List<String> includeFilters;
394    
395      // The backend ID of the backend to export.
396      private final String backendID;
397    
398      // The path to the LDIF file to generate.
399      private final String ldifFile;
400    
401    
402    
403      /**
404       * Creates a new uninitialized export task instance which should only be used
405       * for obtaining general information about this task, including the task name,
406       * description, and supported properties.  Attempts to use a task created with
407       * this constructor for any other reason will likely fail.
408       */
409      public ExportTask()
410      {
411        appendToLDIF      = false;
412        compress          = false;
413        encrypt           = false;
414        sign              = false;
415        wrapColumn        = -1;
416        excludeAttributes = null;
417        excludeBranches   = null;
418        excludeFilters    = null;
419        includeAttributes = null;
420        includeBranches   = null;
421        includeFilters    = null;
422        backendID         = null;
423        ldifFile          = null;
424      }
425    
426    
427    
428    
429      /**
430       * Creates a new export task with the provided information.
431       *
432       * @param  taskID     The task ID to use for this task.  If it is {@code null}
433       *                    then a UUID will be generated for use as the task ID.
434       * @param  backendID  The backend ID of the backend containing the data to
435       *                    export.  It must not be {@code null}.
436       * @param  ldifFile   The path to the LDIF file to create.  It may be an
437       *                    absolute path or a path relative to the server install
438       *                    root.  It must not be {@code null}.
439       */
440      public ExportTask(final String taskID, final String backendID,
441                        final String ldifFile)
442      {
443        this(taskID, backendID, ldifFile, false, null, null, null, null, null, null,
444             -1, false, false, false, null, null, null, null, null);
445      }
446    
447    
448    
449      /**
450       * Creates a new export task with the provided information.
451       *
452       * @param  taskID                  The task ID to use for this task.  If it is
453       *                                 {@code null} then a UUID will be generated
454       *                                 for use as the task ID.
455       * @param  backendID               The backend ID of the backend to be
456       *                                 exported.  It must not be {@code null}.
457       * @param  ldifFile                The path to the LDIF file to be written.
458       *                                 It may be an absolute path or one that is
459       *                                 relative to the server root.  It must not
460       *                                 be {@code null}.
461       * @param  appendToLDIF            Indicates whether to an append to any
462       *                                 existing file rather than overwriting it.
463       * @param  includeBranches         The set of base DNs of entries to include
464       *                                 in the export.  It may be {@code null} or
465       *                                 empty if no entries should be excluded
466       *                                 based on their location.
467       * @param  excludeBranches         The set of base DNs of entries to exclude
468       *                                 from the export.  It may be {@code null} or
469       *                                 empty if no entries should be excluded
470       *                                 based on their location.
471       * @param  includeFilters          The set of filters to use to match entries
472       *                                 that should be included in the export.  It
473       *                                 may be {@code null} or empty if no entries
474       *                                 should be excluded based on their content.
475       * @param  excludeFilters          The set of filters to use to match entries
476       *                                 that should be excluded from the export.
477       *                                 It may be {@code null} or empty if no
478       *                                 entries should be excluded based on their
479       *                                 content.
480       * @param  includeAttributes       The set of attributes that should be
481       *                                 included in exported entries.  It may be
482       *                                 {@code null} or empty if all attributes
483       *                                 should be included.
484       * @param  excludeAttributes       The set of attributes that should be
485       *                                 excluded from exported entries.  It may be
486       *                                 {@code null} or empty if no attributes
487       *                                 should be excluded.
488       * @param  wrapColumn              The column at which long lines should be
489       *                                 wrapped.  It may be less than or equal to
490       *                                 zero to indicate that long lines should not
491       *                                 be wrapped.
492       * @param  compress                Indicates whether the LDIF data should be
493       *                                 compressed as it is written.
494       * @param  encrypt                 Indicates whether the LDIF data should be
495       *                                 encrypted as it is written.
496       * @param  sign                    Indicates whether to include a signed hash
497       *                                 of the content in the exported data.
498       * @param  scheduledStartTime      The time that this task should start
499       *                                 running.
500       * @param  dependencyIDs           The list of task IDs that will be required
501       *                                 to complete before this task will be
502       *                                 eligible to start.
503       * @param  failedDependencyAction  Indicates what action should be taken if
504       *                                 any of the dependencies for this task do
505       *                                 not complete successfully.
506       * @param  notifyOnCompletion      The list of e-mail addresses of individuals
507       *                                 that should be notified when this task
508       *                                 completes.
509       * @param  notifyOnError           The list of e-mail addresses of individuals
510       *                                 that should be notified if this task does
511       *                                 not complete successfully.
512       */
513      public ExportTask(final String taskID, final String backendID,
514                        final String ldifFile, final boolean appendToLDIF,
515                        final List<String> includeBranches,
516                        final List<String> excludeBranches,
517                        final List<String> includeFilters,
518                        final List<String> excludeFilters,
519                        final List<String> includeAttributes,
520                        final List<String> excludeAttributes, final int wrapColumn,
521                        final boolean compress, final boolean encrypt,
522                        final boolean sign, final Date scheduledStartTime,
523                        final List<String> dependencyIDs,
524                        final FailedDependencyAction failedDependencyAction,
525                        final List<String> notifyOnCompletion,
526                        final List<String> notifyOnError)
527      {
528        super(taskID, EXPORT_TASK_CLASS, scheduledStartTime,
529              dependencyIDs, failedDependencyAction, notifyOnCompletion,
530              notifyOnError);
531    
532        ensureNotNull(backendID, ldifFile);
533    
534        this.backendID    = backendID;
535        this.ldifFile     = ldifFile;
536        this.appendToLDIF = appendToLDIF;
537        this.wrapColumn   = wrapColumn;
538        this.compress     = compress;
539        this.encrypt      = encrypt;
540        this.sign         = sign;
541    
542        if (includeBranches == null)
543        {
544          this.includeBranches = Collections.emptyList();
545        }
546        else
547        {
548          this.includeBranches = Collections.unmodifiableList(includeBranches);
549        }
550    
551        if (excludeBranches == null)
552        {
553          this.excludeBranches = Collections.emptyList();
554        }
555        else
556        {
557          this.excludeBranches = Collections.unmodifiableList(excludeBranches);
558        }
559    
560        if (includeFilters == null)
561        {
562          this.includeFilters = Collections.emptyList();
563        }
564        else
565        {
566          this.includeFilters = Collections.unmodifiableList(includeFilters);
567        }
568    
569        if (excludeFilters == null)
570        {
571          this.excludeFilters = Collections.emptyList();
572        }
573        else
574        {
575          this.excludeFilters = Collections.unmodifiableList(excludeFilters);
576        }
577    
578        if (includeAttributes == null)
579        {
580          this.includeAttributes = Collections.emptyList();
581        }
582        else
583        {
584          this.includeAttributes = Collections.unmodifiableList(includeAttributes);
585        }
586    
587        if (excludeAttributes == null)
588        {
589          this.excludeAttributes = Collections.emptyList();
590        }
591        else
592        {
593          this.excludeAttributes = Collections.unmodifiableList(excludeAttributes);
594        }
595      }
596    
597    
598    
599      /**
600       * Creates a new export task from the provided entry.
601       *
602       * @param  entry  The entry to use to create this export task.
603       *
604       * @throws  TaskException  If the provided entry cannot be parsed as an export
605       *                         task entry.
606       */
607      public ExportTask(final Entry entry)
608             throws TaskException
609      {
610        super(entry);
611    
612    
613        // Get the backend ID.  It must be present.
614        backendID = entry.getAttributeValue(ATTR_BACKEND_ID);
615        if (backendID == null)
616        {
617          throw new TaskException(ERR_EXPORT_TASK_NO_BACKEND_ID.get(
618                                       getTaskEntryDN()));
619        }
620    
621    
622        // Get the LDIF file path.  It must be present.
623        ldifFile = entry.getAttributeValue(ATTR_LDIF_FILE);
624        if (ldifFile == null)
625        {
626          throw new TaskException(ERR_EXPORT_TASK_NO_LDIF_FILE.get(
627                                       getTaskEntryDN()));
628        }
629    
630    
631        // Get the appendLDIF flag.  It may be absent.
632        appendToLDIF = parseBooleanValue(entry, ATTR_APPEND_TO_LDIF, false);
633    
634    
635        // Get the list of include branches.  It may be absent.
636        includeBranches = parseStringList(entry, ATTR_INCLUDE_BRANCH);
637    
638    
639        // Get the list of exclude branches.  It may be absent.
640        excludeBranches = parseStringList(entry, ATTR_EXCLUDE_BRANCH);
641    
642    
643        // Get the list of include filters.  It may be absent.
644        includeFilters = parseStringList(entry, ATTR_INCLUDE_FILTER);
645    
646    
647        // Get the list of exclude filters.  It may be absent.
648        excludeFilters = parseStringList(entry, ATTR_EXCLUDE_FILTER);
649    
650    
651        // Get the list of include attributes.  It may be absent.
652        includeAttributes = parseStringList(entry, ATTR_INCLUDE_ATTRIBUTE);
653    
654    
655        // Get the list of exclude attributes.  It may be absent.
656        excludeAttributes = parseStringList(entry, ATTR_EXCLUDE_ATTRIBUTE);
657    
658    
659        // Get the wrap column.  It may be absent.
660        final String wrapStr = entry.getAttributeValue(ATTR_WRAP_COLUMN);
661        if (wrapStr == null)
662        {
663          wrapColumn = -1;
664        }
665        else
666        {
667          try
668          {
669            wrapColumn = Integer.parseInt(wrapStr);
670          }
671          catch (Exception e)
672          {
673            debugException(e);
674            throw new TaskException(ERR_EXPORT_TASK_CANNOT_PARSE_WRAP_COLUMN.get(
675                                         getTaskEntryDN(), wrapStr), e);
676          }
677        }
678    
679    
680        // Get the compress flag.  It may be absent.
681        compress = parseBooleanValue(entry, ATTR_COMPRESS, false);
682    
683    
684        // Get the encrypt flag.  It may be absent.
685        encrypt = parseBooleanValue(entry, ATTR_ENCRYPT, false);
686    
687    
688        // Get the sign flag.  It may be absent.
689        sign = parseBooleanValue(entry, ATTR_SIGN, false);
690      }
691    
692    
693    
694      /**
695       * Creates a new export task from the provided set of task properties.
696       *
697       * @param  properties  The set of task properties and their corresponding
698       *                     values to use for the task.  It must not be
699       *                     {@code null}.
700       *
701       * @throws  TaskException  If the provided set of properties cannot be used to
702       *                         create a valid export task.
703       */
704      public ExportTask(final Map<TaskProperty,List<Object>> properties)
705             throws TaskException
706      {
707        super(EXPORT_TASK_CLASS, properties);
708    
709        boolean  a  = false;
710        boolean  c  = false;
711        boolean  e  = false;
712        boolean  s  = false;
713        long     w  = 0;
714        String   b  = null;
715        String   l  = null;
716        String[] eA = StaticUtils.NO_STRINGS;
717        String[] eB = StaticUtils.NO_STRINGS;
718        String[] eF = StaticUtils.NO_STRINGS;
719        String[] iA = StaticUtils.NO_STRINGS;
720        String[] iB = StaticUtils.NO_STRINGS;
721        String[] iF = StaticUtils.NO_STRINGS;
722    
723        for (final Map.Entry<TaskProperty,List<Object>> entry :
724             properties.entrySet())
725        {
726          final TaskProperty p = entry.getKey();
727          final String attrName = p.getAttributeName();
728          final List<Object> values = entry.getValue();
729    
730          if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID))
731          {
732            b = parseString(p, values, b);
733          }
734          else if (attrName.equalsIgnoreCase(ATTR_LDIF_FILE))
735          {
736            l = parseString(p, values, l);
737          }
738          else if (attrName.equalsIgnoreCase(ATTR_APPEND_TO_LDIF))
739          {
740            a = parseBoolean(p, values, a);
741          }
742          else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_BRANCH))
743          {
744            iB = parseStrings(p, values, iB);
745          }
746          else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_BRANCH))
747          {
748            eB = parseStrings(p, values, eB);
749          }
750          else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_FILTER))
751          {
752            iF = parseStrings(p, values, iF);
753          }
754          else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_FILTER))
755          {
756            eF = parseStrings(p, values, eF);
757          }
758          else if (attrName.equalsIgnoreCase(ATTR_INCLUDE_ATTRIBUTE))
759          {
760            iA = parseStrings(p, values, iA);
761          }
762          else if (attrName.equalsIgnoreCase(ATTR_EXCLUDE_ATTRIBUTE))
763          {
764            eA = parseStrings(p, values, eA);
765          }
766          else if (attrName.equalsIgnoreCase(ATTR_WRAP_COLUMN))
767          {
768            w = parseLong(p, values, w);
769          }
770          else if (attrName.equalsIgnoreCase(ATTR_COMPRESS))
771          {
772            c = parseBoolean(p, values, c);
773          }
774          else if (attrName.equalsIgnoreCase(ATTR_ENCRYPT))
775          {
776            e = parseBoolean(p, values, e);
777          }
778          else if (attrName.equalsIgnoreCase(ATTR_SIGN))
779          {
780            s = parseBoolean(p, values, s);
781          }
782        }
783    
784        if (b == null)
785        {
786          throw new TaskException(ERR_EXPORT_TASK_NO_BACKEND_ID.get(
787                                       getTaskEntryDN()));
788        }
789    
790        if (l == null)
791        {
792          throw new TaskException(ERR_EXPORT_TASK_NO_LDIF_FILE.get(
793                                       getTaskEntryDN()));
794        }
795    
796        backendID         = b;
797        ldifFile          = l;
798        appendToLDIF      = a;
799        includeAttributes = Collections.unmodifiableList(Arrays.asList(iA));
800        excludeAttributes = Collections.unmodifiableList(Arrays.asList(eA));
801        includeBranches   = Collections.unmodifiableList(Arrays.asList(iB));
802        excludeBranches   = Collections.unmodifiableList(Arrays.asList(eB));
803        includeFilters    = Collections.unmodifiableList(Arrays.asList(iF));
804        excludeFilters    = Collections.unmodifiableList(Arrays.asList(eF));
805        wrapColumn        = (int) w;
806        compress          = c;
807        encrypt           = e;
808        sign              = s;
809      }
810    
811    
812    
813      /**
814       * {@inheritDoc}
815       */
816      @Override()
817      public String getTaskName()
818      {
819        return INFO_TASK_NAME_EXPORT.get();
820      }
821    
822    
823    
824      /**
825       * {@inheritDoc}
826       */
827      @Override()
828      public String getTaskDescription()
829      {
830        return INFO_TASK_DESCRIPTION_EXPORT.get();
831      }
832    
833    
834    
835      /**
836       * Retrieves the backend ID of the backend from which the data is to be
837       * exported.
838       *
839       * @return  The backend ID of the backend from which the data is to be
840       *          exported.
841       */
842      public String getBackendID()
843      {
844        return backendID;
845      }
846    
847    
848    
849      /**
850       * Retrieves the path to the LDIF file to which the exported data should be
851       * written.  It may be either an absolute path or one that is relative to the
852       * server root.
853       *
854       * @return  The path to the LDIF file to which the exported data should be
855       *          written.
856       */
857      public String getLDIFFile()
858      {
859        return ldifFile;
860      }
861    
862    
863    
864      /**
865       * Indicates whether to append to the LDIF file rather than overwriting it if
866       * it already exists.
867       *
868       * @return  {@code true} if the server should append to an existing LDIF file,
869       *          or {@code false} if the server should overwrite it.
870       */
871      public boolean appendToLDIF()
872      {
873        return appendToLDIF;
874      }
875    
876    
877    
878      /**
879       * Retrieves a list of base DNs of branches that should be included in the
880       * export.
881       *
882       * @return  A list of base DNs of branches that should be included in the
883       *          export, or an empty list if no entries should be excluded based on
884       *          their location.
885       */
886      public List<String> getIncludeBranches()
887      {
888        return includeBranches;
889      }
890    
891    
892    
893      /**
894       * Retrieves a list of base DNs of branches that should be excluded from the
895       * export.
896       *
897       * @return  A list of base DNs of branches that should be excluded from the
898       *          export, or an empty list if no entries should be excluded based on
899       *          their location.
900       */
901      public List<String> getExcludeBranches()
902      {
903        return excludeBranches;
904      }
905    
906    
907    
908      /**
909       * Retrieves a list of search filters that should be used to determine which
910       * entries should be included in the export.
911       *
912       * @return  A list of search filters that should be used to determine which
913       *          entries should be included in the export, or an empty list if no
914       *          entries should be excluded based on their content.
915       */
916      public List<String> getIncludeFilters()
917      {
918        return includeFilters;
919      }
920    
921    
922    
923      /**
924       * Retrieves a list of search filters that should be used to determine which
925       * entries should be excluded from the export.
926       *
927       * @return  A list of search filters that should be used to determine which
928       *          entries should be excluded from the export, or an empty list if no
929       *          entries should be excluded based on their content.
930       */
931      public List<String> getExcludeFilters()
932      {
933        return excludeFilters;
934      }
935    
936    
937    
938      /**
939       * Retrieves a list of the attributes that should be included in exported
940       * entries.
941       *
942       * @return  A list of the attributes that should be included in exported
943       *          entries, or an empty list if no attributes should be excluded.
944       */
945      public List<String> getIncludeAttributes()
946      {
947        return includeAttributes;
948      }
949    
950    
951    
952      /**
953       * Retrieves a list of the attributes that should be excluded from exported
954       * entries.
955       *
956       * @return  A list of the attributes that should be excluded from exported
957       *          entries, or an empty list if no attributes should be excluded.
958       */
959      public List<String> getExcludeAttributes()
960      {
961        return excludeAttributes;
962      }
963    
964    
965    
966      /**
967       * Retrieves the column number at which long lines should be wrapped.
968       *
969       * @return  The column number at which long lines should be wrapped, or a
970       *          value less than or equal to zero to indicate that no wrapping
971       *          should be performed.
972       */
973      public int getWrapColumn()
974      {
975        return wrapColumn;
976      }
977    
978    
979    
980      /**
981       * Indicates whether the LDIF data should be compressed as it is exported.
982       *
983       * @return  {@code true} if the LDIF data should be compressed as it is
984       *          exported, or {@code false} if not.
985       */
986      public boolean compress()
987      {
988        return compress;
989      }
990    
991    
992    
993      /**
994       * Indicates whether the LDIF data should be encrypted as it is exported.
995       *
996       * @return  {@code true} if the LDIF data should be encrypted as it is
997       *          exported, or {@code false} if not.
998       */
999      public boolean encrypt()
1000      {
1001        return encrypt;
1002      }
1003    
1004    
1005    
1006      /**
1007       * Indicates whether the exported LDIF data should include a signed hash.
1008       *
1009       * @return  {@code true} if the exported LDIF data should include a signed
1010       *          hash, or {@code false} if not.
1011       */
1012      public boolean sign()
1013      {
1014        return sign;
1015      }
1016    
1017    
1018    
1019      /**
1020       * {@inheritDoc}
1021       */
1022      @Override()
1023      protected List<String> getAdditionalObjectClasses()
1024      {
1025        return Arrays.asList(OC_EXPORT_TASK);
1026      }
1027    
1028    
1029    
1030      /**
1031       * {@inheritDoc}
1032       */
1033      @Override()
1034      protected List<Attribute> getAdditionalAttributes()
1035      {
1036        final ArrayList<Attribute> attrs = new ArrayList<Attribute>(13);
1037    
1038        attrs.add(new Attribute(ATTR_BACKEND_ID, backendID));
1039        attrs.add(new Attribute(ATTR_LDIF_FILE, ldifFile));
1040        attrs.add(new Attribute(ATTR_APPEND_TO_LDIF, String.valueOf(appendToLDIF)));
1041        attrs.add(new Attribute(ATTR_COMPRESS, String.valueOf(compress)));
1042        attrs.add(new Attribute(ATTR_ENCRYPT, String.valueOf(encrypt)));
1043        attrs.add(new Attribute(ATTR_SIGN, String.valueOf(sign)));
1044    
1045        if (! includeBranches.isEmpty())
1046        {
1047          attrs.add(new Attribute(ATTR_INCLUDE_BRANCH, includeBranches));
1048        }
1049    
1050        if (! excludeBranches.isEmpty())
1051        {
1052          attrs.add(new Attribute(ATTR_EXCLUDE_BRANCH, excludeBranches));
1053        }
1054    
1055        if (! includeAttributes.isEmpty())
1056        {
1057          attrs.add(new Attribute(ATTR_INCLUDE_ATTRIBUTE, includeAttributes));
1058        }
1059    
1060        if (! excludeAttributes.isEmpty())
1061        {
1062          attrs.add(new Attribute(ATTR_EXCLUDE_ATTRIBUTE, excludeAttributes));
1063        }
1064    
1065        if (! includeFilters.isEmpty())
1066        {
1067          attrs.add(new Attribute(ATTR_INCLUDE_FILTER, includeFilters));
1068        }
1069    
1070        if (! excludeFilters.isEmpty())
1071        {
1072          attrs.add(new Attribute(ATTR_EXCLUDE_FILTER, excludeFilters));
1073        }
1074    
1075        if (wrapColumn > 0)
1076        {
1077          attrs.add(new Attribute(ATTR_WRAP_COLUMN, String.valueOf(wrapColumn)));
1078        }
1079    
1080        return attrs;
1081      }
1082    
1083    
1084    
1085      /**
1086       * {@inheritDoc}
1087       */
1088      @Override()
1089      public List<TaskProperty> getTaskSpecificProperties()
1090      {
1091        final List<TaskProperty> propList = Arrays.asList(
1092             PROPERTY_BACKEND_ID,
1093             PROPERTY_LDIF_FILE,
1094             PROPERTY_APPEND_TO_LDIF,
1095             PROPERTY_INCLUDE_BRANCH,
1096             PROPERTY_EXCLUDE_BRANCH,
1097             PROPERTY_INCLUDE_FILTER,
1098             PROPERTY_EXCLUDE_FILTER,
1099             PROPERTY_INCLUDE_ATTRIBUTE,
1100             PROPERTY_EXCLUDE_ATTRIBUTE,
1101             PROPERTY_WRAP_COLUMN,
1102             PROPERTY_COMPRESS,
1103             PROPERTY_ENCRYPT,
1104             PROPERTY_SIGN);
1105    
1106        return Collections.unmodifiableList(propList);
1107      }
1108    
1109    
1110    
1111      /**
1112       * {@inheritDoc}
1113       */
1114      @Override()
1115      public Map<TaskProperty,List<Object>> getTaskPropertyValues()
1116      {
1117        final LinkedHashMap<TaskProperty,List<Object>> props =
1118             new LinkedHashMap<TaskProperty,List<Object>>();
1119    
1120        props.put(PROPERTY_BACKEND_ID,
1121                  Collections.<Object>unmodifiableList(Arrays.asList(backendID)));
1122    
1123        props.put(PROPERTY_LDIF_FILE,
1124                  Collections.<Object>unmodifiableList(Arrays.asList(ldifFile)));
1125    
1126        props.put(PROPERTY_APPEND_TO_LDIF,
1127                  Collections.<Object>unmodifiableList(Arrays.asList(
1128                       appendToLDIF)));
1129    
1130        props.put(PROPERTY_INCLUDE_BRANCH,
1131                  Collections.<Object>unmodifiableList(includeBranches));
1132    
1133        props.put(PROPERTY_EXCLUDE_BRANCH,
1134                  Collections.<Object>unmodifiableList(excludeBranches));
1135    
1136        props.put(PROPERTY_INCLUDE_FILTER,
1137                  Collections.<Object>unmodifiableList(includeFilters));
1138    
1139        props.put(PROPERTY_EXCLUDE_FILTER,
1140                  Collections.<Object>unmodifiableList(excludeFilters));
1141    
1142        props.put(PROPERTY_INCLUDE_ATTRIBUTE,
1143                  Collections.<Object>unmodifiableList(includeAttributes));
1144    
1145        props.put(PROPERTY_EXCLUDE_ATTRIBUTE,
1146                  Collections.<Object>unmodifiableList(excludeAttributes));
1147    
1148        props.put(PROPERTY_WRAP_COLUMN,
1149                  Collections.<Object>unmodifiableList(Arrays.asList(
1150                       Long.valueOf(wrapColumn))));
1151    
1152        props.put(PROPERTY_COMPRESS,
1153                  Collections.<Object>unmodifiableList(Arrays.asList(compress)));
1154    
1155        props.put(PROPERTY_ENCRYPT,
1156                  Collections.<Object>unmodifiableList(Arrays.asList(encrypt)));
1157    
1158        props.put(PROPERTY_SIGN,
1159                  Collections.<Object>unmodifiableList(Arrays.asList(sign)));
1160    
1161        props.putAll(super.getTaskPropertyValues());
1162        return Collections.unmodifiableMap(props);
1163      }
1164    }