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