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