001/*
002 * Copyright 2008-2022 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2008-2022 Ping Identity Corporation
007 *
008 * Licensed under the Apache License, Version 2.0 (the "License");
009 * you may not use this file except in compliance with the License.
010 * You may obtain a copy of the License at
011 *
012 *    http://www.apache.org/licenses/LICENSE-2.0
013 *
014 * Unless required by applicable law or agreed to in writing, software
015 * distributed under the License is distributed on an "AS IS" BASIS,
016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017 * See the License for the specific language governing permissions and
018 * limitations under the License.
019 */
020/*
021 * Copyright (C) 2008-2022 Ping Identity Corporation
022 *
023 * This program is free software; you can redistribute it and/or modify
024 * it under the terms of the GNU General Public License (GPLv2 only)
025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
026 * as published by the Free Software Foundation.
027 *
028 * This program is distributed in the hope that it will be useful,
029 * but WITHOUT ANY WARRANTY; without even the implied warranty of
030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
031 * GNU General Public License for more details.
032 *
033 * You should have received a copy of the GNU General Public License
034 * along with this program; if not, see <http://www.gnu.org/licenses>.
035 */
036package com.unboundid.ldap.sdk.unboundidds.tasks;
037
038
039
040import java.util.ArrayList;
041import java.util.Arrays;
042import java.util.Collections;
043import java.util.Date;
044import java.util.LinkedHashMap;
045import java.util.List;
046import java.util.Map;
047
048import com.unboundid.ldap.sdk.Attribute;
049import com.unboundid.ldap.sdk.Entry;
050import com.unboundid.util.NotMutable;
051import com.unboundid.util.NotNull;
052import com.unboundid.util.Nullable;
053import com.unboundid.util.StaticUtils;
054import com.unboundid.util.ThreadSafety;
055import com.unboundid.util.ThreadSafetyLevel;
056import com.unboundid.util.Validator;
057import com.unboundid.util.args.DurationArgument;
058
059import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*;
060
061
062
063/**
064 * This class defines a Directory Server task that can be used to back up one or
065 * more Directory Server backends.
066 * <BR>
067 * <BLOCKQUOTE>
068 *   <B>NOTE:</B>  This class, and other classes within the
069 *   {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only
070 *   supported for use against Ping Identity, UnboundID, and
071 *   Nokia/Alcatel-Lucent 8661 server products.  These classes provide support
072 *   for proprietary functionality or for external specifications that are not
073 *   considered stable or mature enough to be guaranteed to work in an
074 *   interoperable way with other types of LDAP servers.
075 * </BLOCKQUOTE>
076 * <BR>
077 * The properties that are available for use with this type of task include:
078 * <UL>
079 *   <LI>The path to the directory in which the backup should be placed.  If
080 *       multiple backends are to be backed up at once, then this should be the
081 *       parent of the backup directories for each backend.  This must be
082 *       provided when scheduling this task.</LI>
083 *   <LI>The backend IDs of the backends to archive.  If this is not provided,
084 *       then the server will attempt to back up all supported backends.</LI>
085 *   <LI>The backup ID to use for the backup.  If this is not provided, then the
086 *       server will generate a backup ID.</LI>
087 *   <LI>A flag that indicates whether the backup should be an incremental
088 *       backup (if the backend supports that capability) or a full backup.</LI>
089 *   <LI>The backup ID of the existing backup on which the incremental backup
090 *       should be based.  If this is not provided and an incremental backup
091 *       is to be performed, then it will be based on the most recent backup in
092 *       the backup directory.</LI>
093 *   <LI>A flag that indicates whether to compress the contents of the
094 *       backup.</LI>
095 *   <LI>A flag that indicates whether to encrypt the contents of the
096 *       backup.</LI>
097 *   <LI>A flag that indicates whether to hash the contents of the backup to use
098 *       as a checksum for verifying the integrity of the backup.</LI>
099 *   <LI>A flag that indicates whether to sign the backup hash in order to
100 *       prevent anyone from tampering with it.</LI>
101 *   <LI>The path to a file containing a passphrase to use to generate the
102 *       encryption key.</LI>
103 *   <LI>The ID of the encryption settings definition to use to generate the
104 *       encryption key.</LI>
105 *   <LI>The maximum rate in megabytes per second at which the backup should be
106 *       written.</LI>
107 *   <LI>The minimum number of previous full backups to retain.</LI>
108 *   <LI>The minimum age of previous full backups to retain.</LI>
109 * </UL>
110
111 */
112@NotMutable()
113@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
114public final class BackupTask
115       extends Task
116{
117  /**
118   * The fully-qualified name of the Java class that is used for the backup
119   * task.
120   */
121  @NotNull static final String BACKUP_TASK_CLASS =
122       "com.unboundid.directory.server.tasks.BackupTask";
123
124
125
126  /**
127   * The name of the attribute used to specify backend IDs of the backends to
128   * archive.
129   */
130  @NotNull private static final String ATTR_BACKEND_ID =
131       "ds-task-backup-backend-id";
132
133
134
135  /**
136   * The name of the attribute used to indicate whether to back up the contents
137   * of all supported backends.
138   */
139  @NotNull private static final String ATTR_BACKUP_ALL = "ds-task-backup-all";
140
141
142
143  /**
144   * The name of the attribute used to specify the path to the directory in
145   * which the backup is to be written.
146   */
147  @NotNull private static final String ATTR_BACKUP_DIRECTORY =
148       "ds-backup-directory-path";
149
150
151
152  /**
153   * The name of the attribute used to specify the backup ID for the backup.
154   */
155  @NotNull private static final String ATTR_BACKUP_ID = "ds-backup-id";
156
157
158
159  /**
160   * The name of the attribute used to indicate whether to compress the backup.
161   */
162  @NotNull private static final String ATTR_COMPRESS =
163       "ds-task-backup-compress";
164
165
166
167  /**
168   * The name of the attribute used to indicate whether to encrypt the backup.
169   */
170  @NotNull private static final String ATTR_ENCRYPT = "ds-task-backup-encrypt";
171
172
173
174  /**
175   * The name of the attribute used to specify the path to a file that contains
176   * the passphrase to use to generate the encryption key.
177   */
178  @NotNull private static final String ATTR_ENCRYPTION_PASSPHRASE_FILE =
179       "ds-task-backup-encryption-passphrase-file";
180
181
182
183  /**
184   * The name of the attribute used to specify the path to a file that contains
185   * the ID of the encryption settings definition to use to generate the
186   * encryption key.
187   */
188  @NotNull private static final String ATTR_ENCRYPTION_SETTINGS_DEFINITION_ID =
189       "ds-task-backup-encryption-settings-definition-id";
190
191
192
193  /**
194   * The name of the attribute used to indicate whether to create a hash of the
195   * backup.
196   */
197  @NotNull private static final String ATTR_HASH = "ds-task-backup-hash";
198
199
200
201  /**
202   * The name of the attribute used to indicate whether to perform an
203   * incremental backup rather than a full backup.
204   */
205  @NotNull private static final String ATTR_INCREMENTAL =
206       "ds-task-backup-incremental";
207
208
209
210  /**
211   * The name of the attribute used to specify the backup ID of the backup
212   * on which to base the incremental backup.
213   */
214  @NotNull private static final String ATTR_INCREMENTAL_BASE_ID =
215       "ds-task-backup-incremental-base-id";
216
217
218
219  /**
220   * The name of the attribute used to specify the maximum backup write rate in
221   * megabytes per second.
222   */
223  @NotNull private static final String ATTR_MAX_MEGABYTES_PER_SECOND =
224       "ds-task-backup-max-megabytes-per-second";
225
226
227
228  /**
229   * The name of the attribute used to specify the minimum age of previous full
230   * backups to retain.
231   */
232  @NotNull private static final String ATTR_RETAIN_PREVIOUS_FULL_BACKUP_AGE =
233       "ds-task-backup-retain-previous-full-backup-age";
234
235
236
237  /**
238   * The name of the attribute used to specify the number of previous full
239   * backups to retain.
240   */
241  @NotNull private static final String ATTR_RETAIN_PREVIOUS_FULL_BACKUP_COUNT =
242       "ds-task-backup-retain-previous-full-backup-count";
243
244
245
246  /**
247   * The name of the attribute used to indicate whether to sign the hash of the
248   * backup.
249   */
250  @NotNull private static final String ATTR_SIGN_HASH =
251       "ds-task-backup-sign-hash";
252
253
254
255  /**
256   * The name of the object class used in backup task entries.
257   */
258  @NotNull private static final String OC_BACKUP_TASK = "ds-task-backup";
259
260
261
262  /**
263   * The task property that will be used for the backup directory.
264   */
265  @NotNull private static final TaskProperty PROPERTY_BACKUP_DIRECTORY =
266       new TaskProperty(ATTR_BACKUP_DIRECTORY,
267            INFO_DISPLAY_NAME_BACKUP_DIRECTORY.get(),
268            INFO_DESCRIPTION_BACKUP_DIRECTORY_BACKUP.get(),
269            String.class, true, false, false);
270
271
272
273  /**
274   * The task property that will be used for the backend ID.
275   */
276  @NotNull private static final TaskProperty PROPERTY_BACKEND_ID =
277       new TaskProperty(ATTR_BACKEND_ID, INFO_DISPLAY_NAME_BACKEND_ID.get(),
278            INFO_DESCRIPTION_BACKEND_ID_BACKUP.get(), String.class, false, true,
279            false);
280
281
282
283  /**
284   * The task property that will be used for the backup ID.
285   */
286  @NotNull private static final TaskProperty PROPERTY_BACKUP_ID =
287       new TaskProperty(ATTR_BACKUP_ID, INFO_DISPLAY_NAME_BACKUP_ID.get(),
288            INFO_DESCRIPTION_BACKUP_ID_BACKUP.get(), String.class, false, false,
289            true);
290
291
292
293  /**
294   * The task property that will be used for the incremental flag.
295   */
296  @NotNull private static final TaskProperty PROPERTY_INCREMENTAL =
297       new TaskProperty(ATTR_INCREMENTAL, INFO_DISPLAY_NAME_INCREMENTAL.get(),
298            INFO_DESCRIPTION_INCREMENTAL.get(), Boolean.class, false, false,
299            false);
300
301
302
303  /**
304   * The task property that will be used for the incremental base ID.
305   */
306  @NotNull private static final TaskProperty PROPERTY_INCREMENTAL_BASE_ID =
307       new TaskProperty(ATTR_INCREMENTAL_BASE_ID,
308            INFO_DISPLAY_NAME_INCREMENTAL_BASE_ID.get(),
309            INFO_DESCRIPTION_INCREMENTAL_BASE_ID.get(), String.class, false,
310            false, true);
311
312
313
314  /**
315   * The task property that will be used for the compress flag.
316   */
317  @NotNull private static final TaskProperty PROPERTY_COMPRESS =
318       new TaskProperty(ATTR_COMPRESS, INFO_DISPLAY_NAME_COMPRESS.get(),
319            INFO_DESCRIPTION_COMPRESS_BACKUP.get(), Boolean.class, false, false,
320            false);
321
322
323
324  /**
325   * The task property that will be used for the encrypt flag.
326   */
327  @NotNull private static final TaskProperty PROPERTY_ENCRYPT =
328       new TaskProperty(ATTR_ENCRYPT, INFO_DISPLAY_NAME_ENCRYPT.get(),
329            INFO_DESCRIPTION_ENCRYPT_BACKUP.get(), Boolean.class, false, false,
330            false);
331
332
333
334  /**
335   * The task property that will be used for the encryption passphrase file.
336   */
337  @NotNull private static final TaskProperty
338       PROPERTY_ENCRYPTION_PASSPHRASE_FILE = new TaskProperty(
339            ATTR_ENCRYPTION_PASSPHRASE_FILE,
340            INFO_DISPLAY_NAME_ENCRYPTION_PASSPHRASE_FILE.get(),
341            INFO_DESCRIPTION_ENCRYPTION_PASSPHRASE_FILE.get(),
342            String.class, false, false, true);
343
344
345
346  /**
347   * The task property that will be used for the encryption settings definition
348   * ID.
349   */
350  @NotNull private static final TaskProperty
351       PROPERTY_ENCRYPTION_SETTINGS_DEFINITION_ID = new TaskProperty(
352            ATTR_ENCRYPTION_SETTINGS_DEFINITION_ID,
353            INFO_DISPLAY_NAME_ENCRYPTION_SETTINGS_DEFINITION_ID.get(),
354            INFO_DESCRIPTION_ENCRYPTION_SETTINGS_DEFINITION_ID.get(),
355            String.class, false, false, true);
356
357
358
359  /**
360   * The task property that will be used for the hash flag.
361   */
362  @NotNull private static final TaskProperty PROPERTY_HASH =
363       new TaskProperty(ATTR_HASH, INFO_DISPLAY_NAME_HASH.get(),
364            INFO_DESCRIPTION_HASH_BACKUP.get(), Boolean.class, false, false,
365            false);
366
367
368
369  /**
370   * The task property that will be used for the sign hash flag.
371   */
372  @NotNull private static final TaskProperty PROPERTY_SIGN_HASH =
373       new TaskProperty(ATTR_SIGN_HASH, INFO_DISPLAY_NAME_SIGN_HASH.get(),
374            INFO_DESCRIPTION_SIGN_HASH_BACKUP.get(), Boolean.class, false,
375            false, false);
376
377
378
379  /**
380   * The task property that will be used for the maximum write rate in megabytes
381   * per second.
382   */
383  @NotNull private static final TaskProperty PROPERTY_MAX_MEGABYTES_PER_SECOND =
384       new TaskProperty(ATTR_MAX_MEGABYTES_PER_SECOND,
385            INFO_DISPLAY_NAME_BACKUP_MAX_MEGABYTES_PER_SECOND.get(),
386            INFO_DESCRIPTION_BACKUP_MAX_MEGABYTES_PER_SECOND.get(),
387            Long.class, false, false, true);
388
389
390
391  /**
392   * The task property that will be used for the retain previous full backup
393   * age.
394   */
395  @NotNull private static final TaskProperty
396       PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_AGE = new TaskProperty(
397            ATTR_RETAIN_PREVIOUS_FULL_BACKUP_AGE,
398            INFO_DISPLAY_NAME_BACKUP_RETAIN_AGE.get(),
399            INFO_DESCRIPTION_BACKUP_RETAIN_AGE.get(),
400            String.class, false, false, true);
401
402
403
404  /**
405   * The task property that will be used for the retain previous full backup
406   * count.
407   */
408  @NotNull private static final TaskProperty
409       PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_COUNT = new TaskProperty(
410            ATTR_RETAIN_PREVIOUS_FULL_BACKUP_COUNT,
411            INFO_DISPLAY_NAME_BACKUP_RETAIN_COUNT.get(),
412            INFO_DESCRIPTION_BACKUP_RETAIN_COUNT.get(),
413            Long.class, false, false, true);
414
415
416
417  /**
418   * The serial version UID for this serializable class.
419   */
420  private static final long serialVersionUID = 2637190942057174423L;
421
422
423
424  // Indicates whether to compress the backup.
425  private final boolean compress;
426
427  // Indicates whether to encrypt the backup.
428  private final boolean encrypt;
429
430  // Indicates whether to generate a hash of the backup.
431  private final boolean hash;
432
433  // Indicates whether to sign the backup hash.
434  private final boolean signHash;
435
436  // Indicates whether to perform an incremental backup.
437  private final boolean incremental;
438
439  // The maximum backup write rate in megabytes per second.
440  @Nullable private final Integer maxMegabytesPerSecond;
441
442  // The retain previous full backup count.
443  @Nullable private final Integer retainPreviousFullBackupCount;
444
445  // The backend IDs of the backends to back up.
446  @NotNull private final List<String> backendIDs;
447
448  // The path to the directory in which to write the backup.
449  @NotNull private final String backupDirectory;
450
451  // The backup ID to use for the backup.
452  @Nullable private final String backupID;
453
454  // The path to a file containing the passphrase to use to generate the
455  // encryption key.
456  @Nullable private final String encryptionPassphraseFile;
457
458  // The identifier for the encryption settings definition to use to generate
459  // the encryption key.
460  @Nullable private final String encryptionSettingsDefinitionID;
461
462  // The backup ID of the backup to use as the base for the incremental backup.
463  @Nullable private final String incrementalBaseID;
464
465  // The retain previous full backup age.
466  @Nullable private final String retainPreviousFullBackupAge;
467
468
469
470  /**
471   * Creates a new uninitialized backup task instance which should only be
472   * used for obtaining general information about this task, including the task
473   * name, description, and supported properties.  Attempts to use a task
474   * created with this constructor for any other reason will likely fail.
475   */
476  public BackupTask()
477  {
478    compress = false;
479    encrypt = false;
480    hash = false;
481    signHash = false;
482    incremental = false;
483    maxMegabytesPerSecond = null;
484    retainPreviousFullBackupCount = null;
485    backendIDs = null;
486    backupDirectory = null;
487    backupID = null;
488    encryptionPassphraseFile = null;
489    encryptionSettingsDefinitionID = null;
490    incrementalBaseID = null;
491    retainPreviousFullBackupAge = null;
492  }
493
494
495
496  /**
497   * Creates a new backup task with the provided information.
498   *
499   * @param  taskID           The task ID to use for this task.  If it is
500   *                          {@code null} then a UUID will be generated for use
501   *                          as the task ID.
502   * @param  backupDirectory  The path to the directory on the server into which
503   *                          the backup should be written.  If a single backend
504   *                          is to be archived, then this should be the path to
505   *                          the specific backup directory for that backend.
506   *                          If multiple backends are to be archived, then this
507   *                          should be the parent of the directories for each
508   *                          of the backends.  It must not be {@code null}.
509   * @param  backendID        The backend ID of the backend to back up.  It may
510   *                          be {@code null} if all supported backends should
511   *                          be backed up.
512   */
513  public BackupTask(@Nullable final String taskID,
514                    @NotNull final String backupDirectory,
515                    @Nullable final String backendID)
516  {
517    this(taskID, backupDirectory,
518         ((backendID == null) ? null : Collections.singletonList(backendID)),
519         null, false, null, false, false, false, false, null, null, null, null,
520         null);
521  }
522
523
524
525  /**
526   * Creates a new restore task with the provided information.
527   *
528   * @param  taskID                  The task ID to use for this task.  If it is
529   *                                 {@code null} then a UUID will be generated
530   *                                 for use as the task ID.
531   * @param  backupDirectory         The path to the directory on the server
532   *                                 into which the backup should be written.
533   *                                 If a single backend is to be archived, then
534   *                                 this should be the path to the specific
535   *                                 backup directory for that backend.  If
536   *                                 multiple backends are to be archived, then
537   *                                 this should be the parent of the
538   *                                 directories for each of the backends.  It
539   *                                 must not be {@code null}.
540   * @param  backendIDs              A list of the backend IDs of the backends
541   *                                 to archive.  It may be {@code null} or
542   *                                 empty if all supported backends should be
543   *                                 archived.
544   * @param  backupID                The backup ID to use for this backup.  It
545   *                                 may be {@code null} to indicate that the
546   *                                 server should generate the backup ID.
547   * @param  incremental             Indicates whether to perform an incremental
548   *                                 backup rather than a full backup.
549   * @param  incrementalBaseID       The backup ID of the existing backup on
550   *                                 which to base the incremental backup.  It
551   *                                 may be {@code null} if this is not an
552   *                                 incremental backup or if it should be based
553   *                                 on the most recent backup.
554   * @param  compress                Indicates whether the backup should be
555   *                                 compressed.
556   * @param  encrypt                 Indicates whether the backup should be
557   *                                 encrypted.
558   * @param  hash                    Indicates whether to generate a hash of the
559   *                                 backup contents.
560   * @param  signHash                Indicates whether to sign the hash of the
561   *                                 backup contents.
562   * @param  scheduledStartTime      The time that this task should start
563   *                                 running.
564   * @param  dependencyIDs           The list of task IDs that will be required
565   *                                 to complete before this task will be
566   *                                 eligible to start.
567   * @param  failedDependencyAction  Indicates what action should be taken if
568   *                                 any of the dependencies for this task do
569   *                                 not complete successfully.
570   * @param  notifyOnCompletion      The list of e-mail addresses of individuals
571   *                                 that should be notified when this task
572   *                                 completes.
573   * @param  notifyOnError           The list of e-mail addresses of individuals
574   *                                 that should be notified if this task does
575   *                                 not complete successfully.
576   */
577  public BackupTask(@Nullable final String taskID,
578              @NotNull final String backupDirectory,
579              @Nullable final List<String> backendIDs,
580              @Nullable final String backupID,
581              final boolean incremental,
582              @Nullable final String incrementalBaseID,
583              final boolean compress, final boolean encrypt,
584              final boolean hash, final boolean signHash,
585              @Nullable final Date scheduledStartTime,
586              @Nullable final List<String> dependencyIDs,
587              @Nullable final FailedDependencyAction failedDependencyAction,
588              @Nullable final List<String> notifyOnCompletion,
589              @Nullable final List<String> notifyOnError)
590  {
591    this(taskID, backupDirectory, backendIDs, backupID, incremental,
592         incrementalBaseID, compress, encrypt, null, null, hash, signHash,
593         null, null, null, scheduledStartTime, dependencyIDs,
594         failedDependencyAction, notifyOnCompletion, notifyOnError);
595  }
596
597
598
599  /**
600   * Creates a new restore task with the provided information.
601   *
602   * @param  taskID                          The task ID to use for this task.
603   *                                         If it is {@code null} then a UUID
604   *                                         will be generated for use as the
605   *                                         task ID.
606   * @param  backupDirectory                 The path to the directory on the
607   *                                         server into which the backup should
608   *                                         be written.  If a single backend is
609   *                                         to be archived, then this should be
610   *                                         the path to the specific backup
611   *                                         directory for that backend.  If
612   *                                         multiple backends are to be
613   *                                         archived, then this should be the
614   *                                         parent of the directories for each
615   *                                         of the backends.  It must not be
616   *                                         {@code null}.
617   * @param  backendIDs                      A list of the backend IDs of the
618   *                                         backends to archive.  It may be
619   *                                         {@code null} or empty if all
620   *                                         supported backends should be
621   *                                         archived.
622   * @param  backupID                        The backup ID to use for this
623   *                                         backup.  It may be {@code null} to
624   *                                         indicate that the server should
625   *                                         generate the backup ID.
626   * @param  incremental                     Indicates whether to perform an
627   *                                         incremental backup rather than a
628   *                                         full backup.
629   * @param  incrementalBaseID               The backup ID of the existing
630   *                                         backup on which to base the
631   *                                         incremental backup.  It may be
632   *                                         {@code null} if this is not an
633   *                                         incremental backup or if it should
634   *                                         be based on the most recent backup.
635   * @param  compress                        Indicates whether the backup should
636   *                                         be compressed.
637   * @param  encrypt                         Indicates whether the backup should
638   *                                         be encrypted.
639   * @param  encryptionPassphraseFile        The path to a file containing the
640   *                                         passphrase to use to generate the
641   *                                         encryption key.  It amy be
642   *                                         {@code null} if the backup is not
643   *                                         to be encrypted, or if the key
644   *                                         should be obtained in some other
645   *                                         way.
646   * @param  encryptionSettingsDefinitionID  The ID of the encryption settings
647   *                                         definition use to generate the
648   *                                         encryption key.  It may be
649   *                                         {@code null} if the backup is not
650   *                                         to be encrypted, or if the key
651   *                                         should be obtained in some other
652   *                                         way.
653   * @param  hash                            Indicates whether to generate a
654   *                                         hash of the backup contents.
655   * @param  signHash                        Indicates whether to sign the hash
656   *                                         of the backup contents.
657   * @param  maxMegabytesPerSecond           The maximum rate in megabytes per
658   *                                         second at which the backup should
659   *                                         be written.
660   * @param  retainPreviousFullBackupCount   The minimum number of previous
661   *                                         backups to retain.
662   * @param  retainPreviousFullBackupAge     A string representation of the
663   *                                         minimum age of previous backups to
664   *                                         retain.  The age should be
665   *                                         formatted in the same way as values
666   *                                         for the {@link DurationArgument}
667   *                                         class.
668   * @param  scheduledStartTime              The time that this task should
669   *                                         start running.
670   * @param  dependencyIDs                   The list of task IDs that will be
671   *                                         required to complete before this
672   *                                         task will be eligible to start.
673   * @param  failedDependencyAction          Indicates what action should be
674   *                                         taken if any of the dependencies
675   *                                         for this task do not complete
676   *                                         successfully.
677   * @param  notifyOnCompletion              The list of e-mail addresses of
678   *                                         individuals that should be notified
679   *                                         when this task completes.
680   * @param  notifyOnError                   The list of e-mail addresses of
681   *                                         individuals that should be notified
682   *                                         if this task does not complete
683   *                                         successfully.
684   */
685  public BackupTask(@Nullable final String taskID,
686              @NotNull final String backupDirectory,
687              @Nullable final List<String> backendIDs,
688              @Nullable final String backupID,
689              final boolean incremental,
690              @Nullable final String incrementalBaseID,
691              final boolean compress, final boolean encrypt,
692              @Nullable final String encryptionPassphraseFile,
693              @Nullable final String encryptionSettingsDefinitionID,
694              final boolean hash, final boolean signHash,
695              @Nullable final Integer maxMegabytesPerSecond,
696              @Nullable final Integer retainPreviousFullBackupCount,
697              @Nullable final String retainPreviousFullBackupAge,
698              @Nullable final Date scheduledStartTime,
699              @Nullable final List<String> dependencyIDs,
700              @Nullable final FailedDependencyAction failedDependencyAction,
701              @Nullable final List<String> notifyOnCompletion,
702              @Nullable final List<String> notifyOnError)
703  {
704    this(taskID, backupDirectory, backendIDs, backupID, incremental,
705         incrementalBaseID, compress, encrypt, encryptionPassphraseFile,
706         encryptionSettingsDefinitionID, hash, signHash, maxMegabytesPerSecond,
707         retainPreviousFullBackupCount, retainPreviousFullBackupAge,
708         scheduledStartTime, dependencyIDs, failedDependencyAction, null,
709         notifyOnCompletion, null, notifyOnError, null, null, null);
710  }
711
712
713
714  /**
715   * Creates a new restore task with the provided information.
716   *
717   * @param  taskID                          The task ID to use for this task.
718   *                                         If it is {@code null} then a UUID
719   *                                         will be generated for use as the
720   *                                         task ID.
721   * @param  backupDirectory                 The path to the directory on the
722   *                                         server into which the backup should
723   *                                         be written.  If a single backend is
724   *                                         to be archived, then this should be
725   *                                         the path to the specific backup
726   *                                         directory for that backend.  If
727   *                                         multiple backends are to be
728   *                                         archived, then this should be the
729   *                                         parent of the directories for each
730   *                                         of the backends.  It must not be
731   *                                         {@code null}.
732   * @param  backendIDs                      A list of the backend IDs of the
733   *                                         backends to archive.  It may be
734   *                                         {@code null} or empty if all
735   *                                         supported backends should be
736   *                                         archived.
737   * @param  backupID                        The backup ID to use for this
738   *                                         backup.  It may be {@code null} to
739   *                                         indicate that the server should
740   *                                         generate the backup ID.
741   * @param  incremental                     Indicates whether to perform an
742   *                                         incremental backup rather than a
743   *                                         full backup.
744   * @param  incrementalBaseID               The backup ID of the existing
745   *                                         backup on which to base the
746   *                                         incremental backup.  It may be
747   *                                         {@code null} if this is not an
748   *                                         incremental backup or if it should
749   *                                         be based on the most recent backup.
750   * @param  compress                        Indicates whether the backup should
751   *                                         be compressed.
752   * @param  encrypt                         Indicates whether the backup should
753   *                                         be encrypted.
754   * @param  encryptionPassphraseFile        The path to a file containing the
755   *                                         passphrase to use to generate the
756   *                                         encryption key.  It amy be
757   *                                         {@code null} if the backup is not
758   *                                         to be encrypted, or if the key
759   *                                         should be obtained in some other
760   *                                         way.
761   * @param  encryptionSettingsDefinitionID  The ID of the encryption settings
762   *                                         definition use to generate the
763   *                                         encryption key.  It may be
764   *                                         {@code null} if the backup is not
765   *                                         to be encrypted, or if the key
766   *                                         should be obtained in some other
767   *                                         way.
768   * @param  hash                            Indicates whether to generate a
769   *                                         hash of the backup contents.
770   * @param  signHash                        Indicates whether to sign the hash
771   *                                         of the backup contents.
772   * @param  maxMegabytesPerSecond           The maximum rate in megabytes per
773   *                                         second at which the backup should
774   *                                         be written.
775   * @param  retainPreviousFullBackupCount   The minimum number of previous
776   *                                         backups to retain.
777   * @param  retainPreviousFullBackupAge     A string representation of the
778   *                                         minimum age of previous backups to
779   *                                         retain.  The age should be
780   *                                         formatted in the same way as values
781   *                                         for the {@link DurationArgument}
782   *                                         class.
783   * @param  scheduledStartTime              The time that this task should
784   *                                         start running.
785   * @param  dependencyIDs                   The list of task IDs that will be
786   *                                         required to complete before this
787   *                                         task will be eligible to start.
788   * @param  failedDependencyAction          Indicates what action should be
789   *                                         taken if any of the dependencies
790   *                                         for this task do not complete
791   *                                         successfully.
792   * @param  notifyOnStart                   The list of e-mail addresses of
793   *                                         individuals that should be notified
794   *                                         when this task starts running.
795   * @param  notifyOnCompletion              The list of e-mail addresses of
796   *                                         individuals that should be notified
797   *                                         when this task completes.
798   * @param  notifyOnSuccess                 The list of e-mail addresses of
799   *                                         individuals that should be notified
800   *                                         if this task completes
801   *                                         successfully.
802   * @param  notifyOnError                   The list of e-mail addresses of
803   *                                         individuals that should be notified
804   *                                         if this task does not complete
805   *                                         successfully.
806   * @param  alertOnStart                    Indicates whether the server should
807   *                                         send an alert notification when
808   *                                         this task starts.
809   * @param  alertOnSuccess                  Indicates whether the server should
810   *                                         send an alert notification if this
811   *                                         task completes successfully.
812   * @param  alertOnError                    Indicates whether the server should
813   *                                         send an alert notification if this
814   *                                         task fails to complete
815   *                                         successfully.
816   */
817  public BackupTask(@Nullable final String taskID,
818              @NotNull final String backupDirectory,
819              @Nullable final List<String> backendIDs,
820              @Nullable final String backupID,
821              final boolean incremental,
822              @Nullable final String incrementalBaseID,
823              final boolean compress, final boolean encrypt,
824              @Nullable final String encryptionPassphraseFile,
825              @Nullable final String encryptionSettingsDefinitionID,
826              final boolean hash, final boolean signHash,
827              @Nullable final Integer maxMegabytesPerSecond,
828              @Nullable final Integer retainPreviousFullBackupCount,
829              @Nullable final String retainPreviousFullBackupAge,
830              @Nullable final Date scheduledStartTime,
831              @Nullable final List<String> dependencyIDs,
832              @Nullable final FailedDependencyAction failedDependencyAction,
833              @Nullable final List<String> notifyOnStart,
834              @Nullable final List<String> notifyOnCompletion,
835              @Nullable final List<String> notifyOnSuccess,
836              @Nullable final List<String> notifyOnError,
837              @Nullable final Boolean alertOnStart,
838              @Nullable final Boolean alertOnSuccess,
839              @Nullable final Boolean alertOnError)
840  {
841    super(taskID, BACKUP_TASK_CLASS, scheduledStartTime,
842         dependencyIDs, failedDependencyAction, notifyOnStart,
843         notifyOnCompletion, notifyOnSuccess,  notifyOnError, alertOnStart,
844         alertOnSuccess, alertOnError);
845
846    Validator.ensureNotNull(backupDirectory);
847
848    this.backupDirectory = backupDirectory;
849    this.backupID = backupID;
850    this.incremental = incremental;
851    this.incrementalBaseID = incrementalBaseID;
852    this.compress = compress;
853    this.encrypt = encrypt;
854    this.encryptionPassphraseFile = encryptionPassphraseFile;
855    this.encryptionSettingsDefinitionID = encryptionSettingsDefinitionID;
856    this.hash = hash;
857    this.signHash = signHash;
858    this.maxMegabytesPerSecond = maxMegabytesPerSecond;
859    this.retainPreviousFullBackupCount = retainPreviousFullBackupCount;
860    this.retainPreviousFullBackupAge = retainPreviousFullBackupAge;
861
862    if (backendIDs == null)
863    {
864      this.backendIDs = Collections.emptyList();
865    }
866    else
867    {
868      this.backendIDs = Collections.unmodifiableList(backendIDs);
869    }
870  }
871
872
873
874  /**
875   * Creates a new backup task from the provided entry.
876   *
877   * @param  entry  The entry to use to create this backup task.
878   *
879   * @throws  TaskException  If the provided entry cannot be parsed as a backup
880   *                         task entry.
881   */
882  public BackupTask(@NotNull final Entry entry)
883         throws TaskException
884  {
885    super(entry);
886
887
888    // Get the backup directory.  It must be present.
889    backupDirectory = entry.getAttributeValue(ATTR_BACKUP_DIRECTORY);
890    if (backupDirectory == null)
891    {
892      throw new TaskException(ERR_BACKUP_NO_BACKUP_DIRECTORY.get(
893                                   getTaskEntryDN()));
894    }
895
896
897    // Get the set of backend IDs.  It may be absent.
898    backendIDs = parseStringList(entry, ATTR_BACKEND_ID);
899
900
901    // Get the backup ID.  It may be absent.
902    backupID = entry.getAttributeValue(ATTR_BACKUP_ID);
903
904
905    // Get the incremental flag.  It may be absent.
906    incremental = parseBooleanValue(entry, ATTR_INCREMENTAL, false);
907
908
909    // Get the incremental base ID.  It may be absent.
910    incrementalBaseID = entry.getAttributeValue(ATTR_INCREMENTAL_BASE_ID);
911
912
913    // Determine whether to compress the backup.  It may be absent.
914    compress = parseBooleanValue(entry, ATTR_COMPRESS, false);
915
916
917    // Determine whether to encrypt the backup.  It may be absent.
918    encrypt = parseBooleanValue(entry, ATTR_ENCRYPT, false);
919
920
921    // Get the path to the encryption passphrase file.  It may be absent.
922    encryptionPassphraseFile =
923         entry.getAttributeValue(ATTR_ENCRYPTION_PASSPHRASE_FILE);
924
925
926    // Get the encryption settings definition ID.  It may be absent.
927    encryptionSettingsDefinitionID =
928         entry.getAttributeValue(ATTR_ENCRYPTION_SETTINGS_DEFINITION_ID);
929
930
931    // Determine whether to hash the backup.  It may be absent.
932    hash = parseBooleanValue(entry, ATTR_HASH, false);
933
934
935    // Determine whether to sign the hash.  It may be absent.
936    signHash = parseBooleanValue(entry, ATTR_SIGN_HASH, false);
937
938
939    // Get the maximum write rate in megabytes per second.  It may be absent.
940    maxMegabytesPerSecond =
941         entry.getAttributeValueAsInteger(ATTR_MAX_MEGABYTES_PER_SECOND);
942
943
944    // Get the retain previous full backup count.  It may be absent.
945    retainPreviousFullBackupCount = entry.getAttributeValueAsInteger(
946         ATTR_RETAIN_PREVIOUS_FULL_BACKUP_COUNT);
947
948
949    // Get the retain previous full backup age.  It may be absent.
950    retainPreviousFullBackupAge = entry.getAttributeValue(
951         ATTR_RETAIN_PREVIOUS_FULL_BACKUP_AGE);
952  }
953
954
955
956  /**
957   * Creates a new backup task from the provided set of task properties.
958   *
959   * @param  properties  The set of task properties and their corresponding
960   *                     values to use for the task.  It must not be
961   *                     {@code null}.
962   *
963   * @throws  TaskException  If the provided set of properties cannot be used to
964   *                         create a valid backup task.
965   */
966  public BackupTask(@NotNull final Map<TaskProperty,List<Object>> properties)
967         throws TaskException
968  {
969    super(BACKUP_TASK_CLASS, properties);
970
971    boolean  c           = false;
972    boolean  e           = false;
973    boolean  h           = false;
974    boolean  i           = false;
975    boolean  s           = false;
976    Integer  maxMB       = null;
977    Integer  retainCount = null;
978    String   bDir        = null;
979    String   bkID        = null;
980    String   incID       = null;
981    String   encID       = null;
982    String   encPWFile   = null;
983    String   retainAge   = null;
984    String[] beIDs       = StaticUtils.NO_STRINGS;
985
986    for (final Map.Entry<TaskProperty,List<Object>> entry :
987         properties.entrySet())
988    {
989      final TaskProperty p = entry.getKey();
990      final String attrName = p.getAttributeName();
991      final List<Object> values = entry.getValue();
992
993      if (attrName.equalsIgnoreCase(ATTR_BACKUP_DIRECTORY))
994      {
995        bDir = parseString(p, values, bDir);
996      }
997      else if (attrName.equalsIgnoreCase(ATTR_BACKEND_ID))
998      {
999        beIDs = parseStrings(p, values, beIDs);
1000      }
1001      else if (attrName.equalsIgnoreCase(ATTR_BACKUP_ID))
1002      {
1003        bkID = parseString(p, values, bkID);
1004      }
1005      else if (attrName.equalsIgnoreCase(ATTR_INCREMENTAL))
1006      {
1007        i = parseBoolean(p, values, i);
1008      }
1009      else if (attrName.equalsIgnoreCase(ATTR_INCREMENTAL_BASE_ID))
1010      {
1011        incID = parseString(p, values, incID);
1012      }
1013      else if (attrName.equalsIgnoreCase(ATTR_COMPRESS))
1014      {
1015        c = parseBoolean(p, values, c);
1016      }
1017      else if (attrName.equalsIgnoreCase(ATTR_ENCRYPT))
1018      {
1019        e = parseBoolean(p, values, e);
1020      }
1021      else if (attrName.equalsIgnoreCase(ATTR_ENCRYPTION_PASSPHRASE_FILE))
1022      {
1023        encPWFile = parseString(p, values, encPWFile);
1024      }
1025      else if (attrName.equalsIgnoreCase(
1026           ATTR_ENCRYPTION_SETTINGS_DEFINITION_ID))
1027      {
1028        encID = parseString(p, values, encID);
1029      }
1030      else if (attrName.equalsIgnoreCase(ATTR_HASH))
1031      {
1032        h = parseBoolean(p, values, h);
1033      }
1034      else if (attrName.equalsIgnoreCase(ATTR_SIGN_HASH))
1035      {
1036        s = parseBoolean(p, values, s);
1037      }
1038      else if (attrName.equalsIgnoreCase(ATTR_MAX_MEGABYTES_PER_SECOND))
1039      {
1040        final Long maxMBLong = parseLong(p, values, null);
1041        if (maxMBLong == null)
1042        {
1043          maxMB = null;
1044        }
1045        else
1046        {
1047          maxMB = maxMBLong.intValue();
1048        }
1049      }
1050      else if (attrName.equalsIgnoreCase(
1051           ATTR_RETAIN_PREVIOUS_FULL_BACKUP_COUNT))
1052      {
1053        final Long retainCountLong = parseLong(p, values, null);
1054        if (retainCountLong == null)
1055        {
1056          retainCount = null;
1057        }
1058        else
1059        {
1060          retainCount = retainCountLong.intValue();
1061        }
1062      }
1063      else if (attrName.equalsIgnoreCase(ATTR_RETAIN_PREVIOUS_FULL_BACKUP_AGE))
1064      {
1065        retainAge = parseString(p, values, retainAge);
1066      }
1067    }
1068
1069    if (bDir == null)
1070    {
1071      throw new TaskException(ERR_BACKUP_NO_BACKUP_DIRECTORY.get(
1072                                   getTaskEntryDN()));
1073    }
1074
1075    backupDirectory = bDir;
1076    backendIDs = Arrays.asList(beIDs);
1077    backupID = bkID;
1078    incremental = i;
1079    incrementalBaseID = incID;
1080    compress = c;
1081    encrypt = e;
1082    encryptionPassphraseFile = encPWFile;
1083    encryptionSettingsDefinitionID = encID;
1084    hash = h;
1085    signHash = s;
1086    maxMegabytesPerSecond = maxMB;
1087    retainPreviousFullBackupCount = retainCount;
1088    retainPreviousFullBackupAge = retainAge;
1089  }
1090
1091
1092
1093  /**
1094   * {@inheritDoc}
1095   */
1096  @Override()
1097  @NotNull()
1098  public String getTaskName()
1099  {
1100    return INFO_TASK_NAME_BACKUP.get();
1101  }
1102
1103
1104
1105  /**
1106   * {@inheritDoc}
1107   */
1108  @Override()
1109  @NotNull()
1110  public String getTaskDescription()
1111  {
1112    return INFO_TASK_DESCRIPTION_BACKUP.get();
1113  }
1114
1115
1116
1117  /**
1118   * Retrieves the path to the backup directory in which the backup files should
1119   * be written.  If a single backend is to be archived, then this will be the
1120   * directory in which the backup files are written.  If multiple backends are
1121   * to be archived, then this will be the parent of the directories containing
1122   * the backups for each backend.
1123   *
1124   * @return  The path to the backup directory in which the backup files should
1125   *          be written.
1126   */
1127  @NotNull()
1128  public String getBackupDirectory()
1129  {
1130    return backupDirectory;
1131  }
1132
1133
1134
1135  /**
1136   * Indicates whether the server should back up all supported backends.
1137   *
1138   * @return  {@code true} if the server should back up all supported backends,
1139   *          or {@code false} if it should back up a specified backend or set
1140   *          of backends.
1141   */
1142  public boolean backupAll()
1143  {
1144    return backendIDs.isEmpty();
1145  }
1146
1147
1148
1149  /**
1150   * Retrieves the set of backend IDs for the backends that should be archived.
1151   *
1152   * @return  The set of backend IDs for the backends that should be archived,
1153   *          or an empty list if the server should back up all supported
1154   *          backends.
1155   */
1156  @NotNull()
1157  public List<String> getBackendIDs()
1158  {
1159    return backendIDs;
1160  }
1161
1162
1163
1164  /**
1165   * Retrieves the backup ID for the backup to generate.
1166   *
1167   * @return  The backup ID for the backup to generate, or {@code null} if the
1168   *          server should generate a backup ID.
1169   */
1170  @Nullable()
1171  public String getBackupID()
1172  {
1173    return backupID;
1174  }
1175
1176
1177
1178  /**
1179   * Indicates whether the server should attempt to perform an incremental
1180   * backup rather than a full backup.
1181   *
1182   * @return  {@code true} if the server should attempt to perform an
1183   *          incremental backup, or {@code false} for a full backup.
1184   */
1185  public boolean incremental()
1186  {
1187    return incremental;
1188  }
1189
1190
1191
1192  /**
1193   * Retrieves the backup ID of the existing backup on which the incremental
1194   * backup should be based.
1195   *
1196   * @return  The backup ID of the existing backup on which the incremental
1197   *          backup should be based, or {@code null} if it is not an
1198   *          incremental backup or the server should use the most recent
1199   *          backup available as the base for the new incremental backup.
1200   */
1201  @Nullable()
1202  public String getIncrementalBaseID()
1203  {
1204    return incrementalBaseID;
1205  }
1206
1207
1208
1209  /**
1210   * Indicates whether the backup should be compressed.
1211   *
1212   * @return  {@code true} if the backup should be compressed, or {@code false}
1213   *          if not.
1214   */
1215  public boolean compress()
1216  {
1217    return compress;
1218  }
1219
1220
1221
1222  /**
1223   * Indicates whether the backup should be encrypted.
1224   *
1225   * @return  {@code true} if the backup should be encrypted, or {@code false}
1226   *          if not.
1227   */
1228  public boolean encrypt()
1229  {
1230    return encrypt;
1231  }
1232
1233
1234
1235  /**
1236   * Retrieves the path to a file that contains the passphrase to use to
1237   * generate the encryption key.
1238   *
1239   * @return  The path to a file that contains the passphrase to use to
1240   *          generate the encryption key, or {@code null} if the backup should
1241   *          not be encrypted or if the encryption key should be obtained
1242   *          through some other means.
1243   */
1244  @Nullable()
1245  public String getEncryptionPassphraseFile()
1246  {
1247    return encryptionPassphraseFile;
1248  }
1249
1250
1251
1252  /**
1253   * Retrieves the identifier of the encryption settings definition to use to
1254   * generate the encryption key.
1255   *
1256   * @return  The identifier of the encryption settings definition to use to
1257   *          generate the encryption key, or {@code null} if the backup should
1258   *          not be encrypted or if the encryption key should be obtained
1259   *          through some other means.
1260   */
1261  @Nullable()
1262  public String getEncryptionSettingsDefinitionID()
1263  {
1264    return encryptionSettingsDefinitionID;
1265  }
1266
1267
1268
1269  /**
1270   * Indicates whether the server should generate a hash of the backup.
1271   *
1272   * @return  {@code true} if the server should generate a hash of the backup,
1273   *          or {@code false} if not.
1274   */
1275  public boolean hash()
1276  {
1277    return hash;
1278  }
1279
1280
1281
1282  /**
1283   * Indicates whether the server should sign the backup hash.
1284   *
1285   * @return  {@code true} if the server should sign the backup hash, or
1286   *          {@code false} if not.
1287   */
1288  public boolean signHash()
1289  {
1290    return signHash;
1291  }
1292
1293
1294
1295  /**
1296   * Retrieves the maximum rate, in megabytes per second, at which the backup
1297   * should be written.
1298   *
1299   * @return  The maximum rate, in megabytes per second, at which the backup
1300   *          should be written, or {@code null} if the writing should not be
1301   *          rate limited.
1302   */
1303  @Nullable()
1304  public Integer getMaxMegabytesPerSecond()
1305  {
1306    return maxMegabytesPerSecond;
1307  }
1308
1309
1310
1311  /**
1312   * Retrieves the minimum number of previous full backups that should be
1313   * retained if the new backup is created successfully.
1314   *
1315   * @return  The minimum number of previous full backups that should be
1316   *          retained if the new backup is created successfully, or
1317   *          {@code null} if no backups should be removed or if the backup age
1318   *          should be the only retention criteria.
1319   */
1320  @Nullable()
1321  public Integer getRetainPreviousFullBackupCount()
1322  {
1323    return retainPreviousFullBackupCount;
1324  }
1325
1326
1327
1328  /**
1329   * Retrieves a string representation of the minimum age of previous full
1330   * backups that should be retained if the new backup is created successfully.
1331   *
1332   * @return  A string representation fo the minimum age of previous full
1333   *          backups that should be retained if the new backup is created
1334   *          successfully, or {@code null} if no backups should be removed or
1335   *          if the backup count should be the only retention criteria.
1336   */
1337  @Nullable()
1338  public String getRetainPreviousFullBackupAge()
1339  {
1340    return retainPreviousFullBackupAge;
1341  }
1342
1343
1344
1345  /**
1346   * {@inheritDoc}
1347   */
1348  @Override()
1349  @NotNull()
1350  protected List<String> getAdditionalObjectClasses()
1351  {
1352    return Collections.singletonList(OC_BACKUP_TASK);
1353  }
1354
1355
1356
1357  /**
1358   * {@inheritDoc}
1359   */
1360  @Override()
1361  @NotNull()
1362  protected List<Attribute> getAdditionalAttributes()
1363  {
1364    final ArrayList<Attribute> attrs = new ArrayList<>(20);
1365
1366    attrs.add(new Attribute(ATTR_BACKUP_DIRECTORY, backupDirectory));
1367    attrs.add(new Attribute(ATTR_INCREMENTAL,  String.valueOf(incremental)));
1368    attrs.add(new Attribute(ATTR_COMPRESS, String.valueOf(compress)));
1369    attrs.add(new Attribute(ATTR_ENCRYPT, String.valueOf(encrypt)));
1370    attrs.add(new Attribute(ATTR_HASH, String.valueOf(hash)));
1371    attrs.add(new Attribute(ATTR_SIGN_HASH, String.valueOf(signHash)));
1372
1373    if (backendIDs.isEmpty())
1374    {
1375      attrs.add(new Attribute(ATTR_BACKUP_ALL, "true"));
1376    }
1377    else
1378    {
1379      attrs.add(new Attribute(ATTR_BACKEND_ID, backendIDs));
1380    }
1381
1382    if (backupID != null)
1383    {
1384      attrs.add(new Attribute(ATTR_BACKUP_ID, backupID));
1385    }
1386
1387    if (incrementalBaseID != null)
1388    {
1389      attrs.add(new Attribute(ATTR_INCREMENTAL_BASE_ID, incrementalBaseID));
1390    }
1391
1392    if (encryptionPassphraseFile != null)
1393    {
1394      attrs.add(new Attribute(ATTR_ENCRYPTION_PASSPHRASE_FILE,
1395           encryptionPassphraseFile));
1396    }
1397
1398    if (encryptionSettingsDefinitionID != null)
1399    {
1400      attrs.add(new Attribute(ATTR_ENCRYPTION_SETTINGS_DEFINITION_ID,
1401           encryptionSettingsDefinitionID));
1402    }
1403
1404    if (maxMegabytesPerSecond != null)
1405    {
1406      attrs.add(new Attribute(ATTR_MAX_MEGABYTES_PER_SECOND,
1407           String.valueOf(maxMegabytesPerSecond)));
1408    }
1409
1410    if (retainPreviousFullBackupCount != null)
1411    {
1412      attrs.add(new Attribute(ATTR_RETAIN_PREVIOUS_FULL_BACKUP_COUNT,
1413           String.valueOf(retainPreviousFullBackupCount)));
1414    }
1415
1416    if (retainPreviousFullBackupAge != null)
1417    {
1418      attrs.add(new Attribute(ATTR_RETAIN_PREVIOUS_FULL_BACKUP_AGE,
1419           retainPreviousFullBackupAge));
1420    }
1421
1422    return attrs;
1423  }
1424
1425
1426
1427  /**
1428   * {@inheritDoc}
1429   */
1430  @Override()
1431  @NotNull()
1432  public List<TaskProperty> getTaskSpecificProperties()
1433  {
1434    final List<TaskProperty> propList = Arrays.asList(
1435         PROPERTY_BACKUP_DIRECTORY,
1436         PROPERTY_BACKEND_ID,
1437         PROPERTY_BACKUP_ID,
1438         PROPERTY_INCREMENTAL,
1439         PROPERTY_INCREMENTAL_BASE_ID,
1440         PROPERTY_COMPRESS,
1441         PROPERTY_ENCRYPT,
1442         PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1443         PROPERTY_ENCRYPTION_SETTINGS_DEFINITION_ID,
1444         PROPERTY_HASH,
1445         PROPERTY_SIGN_HASH,
1446         PROPERTY_MAX_MEGABYTES_PER_SECOND,
1447         PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_COUNT,
1448         PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_AGE);
1449
1450    return Collections.unmodifiableList(propList);
1451  }
1452
1453
1454
1455  /**
1456   * {@inheritDoc}
1457   */
1458  @Override()
1459  @NotNull()
1460  public Map<TaskProperty,List<Object>> getTaskPropertyValues()
1461  {
1462    final LinkedHashMap<TaskProperty,List<Object>> props =
1463         new LinkedHashMap<>(StaticUtils.computeMapCapacity(20));
1464
1465    props.put(PROPERTY_BACKUP_DIRECTORY,
1466         Collections.<Object>singletonList(backupDirectory));
1467
1468    props.put(PROPERTY_BACKEND_ID,
1469              Collections.<Object>unmodifiableList(backendIDs));
1470
1471    if (backupID == null)
1472    {
1473      props.put(PROPERTY_BACKUP_ID, Collections.emptyList());
1474    }
1475    else
1476    {
1477      props.put(PROPERTY_BACKUP_ID,
1478                Collections.<Object>singletonList(backupID));
1479    }
1480
1481    props.put(PROPERTY_INCREMENTAL,
1482              Collections.<Object>singletonList(incremental));
1483
1484    if (incrementalBaseID == null)
1485    {
1486      props.put(PROPERTY_INCREMENTAL_BASE_ID, Collections.emptyList());
1487    }
1488    else
1489    {
1490      props.put(PROPERTY_INCREMENTAL_BASE_ID,
1491                Collections.<Object>singletonList(incrementalBaseID));
1492    }
1493
1494    props.put(PROPERTY_COMPRESS,
1495              Collections.<Object>singletonList(compress));
1496
1497    props.put(PROPERTY_ENCRYPT,
1498              Collections.<Object>singletonList(encrypt));
1499
1500    if (encryptionPassphraseFile == null)
1501    {
1502      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE, Collections.emptyList());
1503    }
1504    else
1505    {
1506      props.put(PROPERTY_ENCRYPTION_PASSPHRASE_FILE,
1507         Collections.<Object>singletonList(encryptionPassphraseFile));
1508    }
1509
1510    if (encryptionSettingsDefinitionID == null)
1511    {
1512      props.put(PROPERTY_ENCRYPTION_SETTINGS_DEFINITION_ID,
1513           Collections.emptyList());
1514    }
1515    else
1516    {
1517      props.put(PROPERTY_ENCRYPTION_SETTINGS_DEFINITION_ID,
1518         Collections.<Object>singletonList(encryptionSettingsDefinitionID));
1519    }
1520
1521    props.put(PROPERTY_HASH,
1522              Collections.<Object>singletonList(hash));
1523
1524    props.put(PROPERTY_SIGN_HASH,
1525              Collections.<Object>singletonList(signHash));
1526
1527    if (maxMegabytesPerSecond == null)
1528    {
1529      props.put(PROPERTY_MAX_MEGABYTES_PER_SECOND, Collections.emptyList());
1530    }
1531    else
1532    {
1533      props.put(PROPERTY_MAX_MEGABYTES_PER_SECOND,
1534         Collections.<Object>singletonList(maxMegabytesPerSecond.longValue()));
1535    }
1536
1537    if (retainPreviousFullBackupCount == null)
1538    {
1539      props.put(PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_COUNT,
1540           Collections.emptyList());
1541    }
1542    else
1543    {
1544      props.put(PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_COUNT,
1545         Collections.<Object>singletonList(
1546              retainPreviousFullBackupCount.longValue()));
1547    }
1548
1549    if (retainPreviousFullBackupAge == null)
1550    {
1551      props.put(PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_AGE,
1552           Collections.emptyList());
1553    }
1554    else
1555    {
1556      props.put(PROPERTY_RETAIN_PREVIOUS_FULL_BACKUP_AGE,
1557         Collections.<Object>singletonList(retainPreviousFullBackupAge));
1558    }
1559
1560    props.putAll(super.getTaskPropertyValues());
1561    return Collections.unmodifiableMap(props);
1562  }
1563}