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