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.io.Serializable; 026import java.text.ParseException; 027import java.util.ArrayList; 028import java.util.Arrays; 029import java.util.Collections; 030import java.util.Date; 031import java.util.Iterator; 032import java.util.LinkedHashMap; 033import java.util.List; 034import java.util.Map; 035import java.util.UUID; 036 037import com.unboundid.ldap.sdk.Attribute; 038import com.unboundid.ldap.sdk.Entry; 039import com.unboundid.util.NotExtensible; 040import com.unboundid.util.ThreadSafety; 041import com.unboundid.util.ThreadSafetyLevel; 042 043import static com.unboundid.ldap.sdk.unboundidds.tasks.TaskMessages.*; 044import static com.unboundid.util.Debug.*; 045import static com.unboundid.util.StaticUtils.*; 046import static com.unboundid.util.Validator.*; 047 048 049 050/** 051 * This class defines a data structure for holding information about scheduled 052 * tasks as used by the Ping Identity, UnboundID, or Alcatel-Lucent 8661 053 * Directory Server. Subclasses be used to provide additional functionality 054 * when dealing with certain types of tasks. 055 * <BR> 056 * <BLOCKQUOTE> 057 * <B>NOTE:</B> This class, and other classes within the 058 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 059 * supported for use against Ping Identity, UnboundID, and Alcatel-Lucent 8661 060 * server products. These classes provide support for proprietary 061 * functionality or for external specifications that are not considered stable 062 * or mature enough to be guaranteed to work in an interoperable way with 063 * other types of LDAP servers. 064 * </BLOCKQUOTE> 065 * <BR> 066 * All types of tasks can include the following information: 067 * <UL> 068 * <LI>Task ID -- Uniquely identifies the task in the server. It may be 069 * omitted when scheduling a new task in order to have a task ID generated 070 * for the task.</LI> 071 * <LI>Task Class Name -- The fully-qualified name of the {@code Task} 072 * subclass that provides the logic for the task. This does not need to 073 * be provided when creating a new task from one of the task-specific 074 * subclasses.</LI> 075 * <LI>Task State -- The current state of the task. See the {@link TaskState} 076 * enum for information about the possible states that a task may 077 * have.</LI> 078 * <LI>Scheduled Start Time -- The earliest time that the task should be 079 * eligible to start. It may be omitted when scheduling a new task in 080 * order to use the current time.</LI> 081 * <LI>Actual Start Time -- The time that server started processing the 082 * task.</LI> 083 * <LI>Actual Start Time -- The time that server completed processing for the 084 * task.</LI> 085 * <LI>Dependency IDs -- A list of task IDs for tasks that must complete 086 * before this task may be considered eligible to start.</LI> 087 * <LI>Failed Dependency Action -- Specifies how the server should treat this 088 * task if any of the tasks on which it depends failed. See the 089 * {@link FailedDependencyAction} enum for the failed dependency action 090 * values that may be used.</LI> 091 * <LI>Notify on Completion -- A list of e-mail addresses for users that 092 * should be notified when the task completes, regardless of whether it 093 * was successful.</LI> 094 * <LI>Notify On Error -- A list of e-mail addresses for users that should be 095 * notified if the task fails.</LI> 096 * <LI>Log Messages -- A list of the messages logged by the task while it was 097 * running.</LI> 098 * </UL> 099 * Each of these elements can be retrieving using specific methods within this 100 * class (e.g., the {@link Task#getTaskID} method can be used to retrieve the 101 * task ID), but task properties (including those specific to the particular 102 * type to task) may also be accessed using a generic API. For example, the 103 * {@link Task#getTaskPropertyValues} method retrieves a map that correlates the 104 * {@link TaskProperty} objects for the task with the values that have been set 105 * for those properties. See the documentation for the {@link TaskManager} 106 * class for an example that demonstrates accessing task information using the 107 * generic API. 108 * <BR><BR> 109 * Also note that it is possible to create new tasks using information obtained 110 * from the generic API, but that is done on a per-class basis. For example, in 111 * order to create a new {@link BackupTask} instance using the generic API, you 112 * would use the {@link BackupTask#BackupTask(Map)} constructor, in which the 113 * provided map contains a mapping between the properties and their values for 114 * that task. The {@link Task#getTaskSpecificProperties} method may be used to 115 * retrieve a list of the task-specific properties that may be provided when 116 * scheduling a task, and the {@link Task#getCommonTaskProperties} method may be 117 * used to retrieve a list of properties that can be provided when scheduling 118 * any type of task. 119 */ 120@NotExtensible() 121@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 122public class Task 123 implements Serializable 124{ 125 /** 126 * The name of the attribute used to hold the actual start time for scheduled 127 * tasks. 128 */ 129 static final String ATTR_ACTUAL_START_TIME = "ds-task-actual-start-time"; 130 131 132 133 /** 134 * The name of the attribute used to hold the completion time for scheduled 135 * tasks. 136 */ 137 static final String ATTR_COMPLETION_TIME = "ds-task-completion-time"; 138 139 140 141 /** 142 * The name of the attribute used to hold the task IDs for tasks on which a 143 * scheduled task is dependent. 144 */ 145 static final String ATTR_DEPENDENCY_ID = "ds-task-dependency-id"; 146 147 148 149 /** 150 * The name of the attribute used to indicate what action to take if one of 151 * the dependencies for a task failed to complete successfully. 152 */ 153 static final String ATTR_FAILED_DEPENDENCY_ACTION = 154 "ds-task-failed-dependency-action"; 155 156 157 158 /** 159 * The name of the attribute used to hold the log messages for scheduled 160 * tasks. 161 */ 162 static final String ATTR_LOG_MESSAGE = "ds-task-log-message"; 163 164 165 166 /** 167 * The name of the attribute used to hold the e-mail addresses of the users 168 * that should be notified whenever a scheduled task completes, regardless of 169 * success or failure. 170 */ 171 static final String ATTR_NOTIFY_ON_COMPLETION = 172 "ds-task-notify-on-completion"; 173 174 175 176 /** 177 * The name of the attribute used to hold the e-mail addresses of the users 178 * that should be notified if a scheduled task fails to complete successfully. 179 */ 180 static final String ATTR_NOTIFY_ON_ERROR = "ds-task-notify-on-error"; 181 182 183 184 /** 185 * The name of the attribute used to hold the scheduled start time for 186 * scheduled tasks. 187 */ 188 static final String ATTR_SCHEDULED_START_TIME = 189 "ds-task-scheduled-start-time"; 190 191 192 193 /** 194 * The name of the attribute used to hold the name of the class that provides 195 * the logic for scheduled tasks. 196 */ 197 static final String ATTR_TASK_CLASS = "ds-task-class-name"; 198 199 200 201 /** 202 * The name of the attribute used to hold the task ID for scheduled tasks. 203 */ 204 static final String ATTR_TASK_ID = "ds-task-id"; 205 206 207 208 /** 209 * The name of the attribute used to hold the current state for scheduled 210 * tasks. 211 */ 212 static final String ATTR_TASK_STATE = "ds-task-state"; 213 214 215 216 /** 217 * The name of the base object class for scheduled tasks. 218 */ 219 static final String OC_TASK = "ds-task"; 220 221 222 223 /** 224 * The DN of the entry below which scheduled tasks reside. 225 */ 226 static final String SCHEDULED_TASKS_BASE_DN = 227 "cn=Scheduled Tasks,cn=tasks"; 228 229 230 231 /** 232 * The task property that will be used for the task ID. 233 */ 234 static final TaskProperty PROPERTY_TASK_ID = 235 new TaskProperty(ATTR_TASK_ID, INFO_DISPLAY_NAME_TASK_ID.get(), 236 INFO_DESCRIPTION_TASK_ID.get(), String.class, false, 237 false, true); 238 239 240 241 /** 242 * The task property that will be used for the scheduled start time. 243 */ 244 static final TaskProperty PROPERTY_SCHEDULED_START_TIME = 245 new TaskProperty(ATTR_SCHEDULED_START_TIME, 246 INFO_DISPLAY_NAME_SCHEDULED_START_TIME.get(), 247 INFO_DESCRIPTION_SCHEDULED_START_TIME.get(), Date.class, 248 false, false, true); 249 250 251 252 /** 253 * The task property that will be used for the set of dependency IDs. 254 */ 255 static final TaskProperty PROPERTY_DEPENDENCY_ID = 256 new TaskProperty(ATTR_DEPENDENCY_ID, 257 INFO_DISPLAY_NAME_DEPENDENCY_ID.get(), 258 INFO_DESCRIPTION_DEPENDENCY_ID.get(), String.class, 259 false, true, true); 260 261 262 263 /** 264 * The task property that will be used for the failed dependency action. 265 */ 266 static final TaskProperty PROPERTY_FAILED_DEPENDENCY_ACTION = 267 new TaskProperty(ATTR_FAILED_DEPENDENCY_ACTION, 268 INFO_DISPLAY_NAME_FAILED_DEPENDENCY_ACTION.get(), 269 INFO_DESCRIPTION_FAILED_DEPENDENCY_ACTION.get(), 270 String.class, false, false, true, 271 new String[] 272 { 273 FailedDependencyAction.CANCEL.getName(), 274 FailedDependencyAction.DISABLE.getName(), 275 FailedDependencyAction.PROCESS.getName() 276 }); 277 278 279 280 /** 281 * The task property that will be used for the notify on completion addresses. 282 */ 283 static final TaskProperty PROPERTY_NOTIFY_ON_COMPLETION = 284 new TaskProperty(ATTR_NOTIFY_ON_COMPLETION, 285 INFO_DISPLAY_NAME_NOTIFY_ON_COMPLETION.get(), 286 INFO_DESCRIPTION_NOTIFY_ON_COMPLETION.get(), 287 String.class, false, true, true); 288 289 290 291 /** 292 * The task property that will be used for the notify on error addresses. 293 */ 294 static final TaskProperty PROPERTY_NOTIFY_ON_ERROR = 295 new TaskProperty(ATTR_NOTIFY_ON_ERROR, 296 INFO_DISPLAY_NAME_NOTIFY_ON_ERROR.get(), 297 INFO_DESCRIPTION_NOTIFY_ON_ERROR.get(), 298 String.class, false, true, true); 299 300 301 302 /** 303 * The serial version UID for this serializable class. 304 */ 305 private static final long serialVersionUID = -3521189553470479032L; 306 307 308 309 // The time that this task actually started. 310 private final Date actualStartTime; 311 312 // The time that this task completed. 313 private final Date completionTime; 314 315 // The time that this task was scheduled to start. 316 private final Date scheduledStartTime; 317 318 // The entry from which this task was decoded. 319 private final Entry taskEntry; 320 321 // The failed dependency action for this task. 322 private final FailedDependencyAction failedDependencyAction; 323 324 // The set of task IDs of the tasks on which this task is dependent. 325 private final List<String> dependencyIDs; 326 327 // The set of log messages for this task. 328 private final List<String> logMessages; 329 330 // The set of e-mail addresses of users that should be notified when the task 331 // processing is complete. 332 private final List<String> notifyOnCompletion; 333 334 // The set of e-mail addresses of users that should be notified if task 335 // processing completes with an error. 336 private final List<String> notifyOnError; 337 338 // The fully-qualified name of the task class. 339 private final String taskClassName; 340 341 // The DN of the entry for this task. 342 private final String taskEntryDN; 343 344 // The task ID for this task. 345 private final String taskID; 346 347 // The current state for this task. 348 private final TaskState taskState; 349 350 351 352 /** 353 * Creates a new uninitialized task instance which should only be used for 354 * obtaining general information about this task, including the task name, 355 * description, and supported properties. Attempts to use a task created with 356 * this constructor for any other reason will likely fail. 357 */ 358 protected Task() 359 { 360 actualStartTime = null; 361 completionTime = null; 362 scheduledStartTime = null; 363 taskEntry = null; 364 failedDependencyAction = null; 365 dependencyIDs = null; 366 logMessages = null; 367 notifyOnCompletion = null; 368 notifyOnError = null; 369 taskClassName = null; 370 taskEntryDN = null; 371 taskID = null; 372 taskState = null; 373 } 374 375 376 377 /** 378 * Creates a new unscheduled task with the specified task ID and class name. 379 * 380 * @param taskID The task ID to use for this task. If it is 381 * {@code null} then a UUID will be generated for use 382 * as the task ID. 383 * @param taskClassName The fully-qualified name of the Java class that 384 * provides the logic for the task. It must not be 385 * {@code null}. 386 */ 387 public Task(final String taskID, final String taskClassName) 388 { 389 this(taskID, taskClassName, null, null, null, null, null); 390 } 391 392 393 394 /** 395 * Creates a new unscheduled task with the provided information. 396 * 397 * @param taskID The task ID to use for this task. 398 * @param taskClassName The fully-qualified name of the Java class 399 * that provides the logic for the task. It 400 * must not be {@code null}. 401 * @param scheduledStartTime The time that this task should start 402 * running. 403 * @param dependencyIDs The list of task IDs that will be required 404 * to complete before this task will be 405 * eligible to start. 406 * @param failedDependencyAction Indicates what action should be taken if 407 * any of the dependencies for this task do 408 * not complete successfully. 409 * @param notifyOnCompletion The list of e-mail addresses of individuals 410 * that should be notified when this task 411 * completes. 412 * @param notifyOnError The list of e-mail addresses of individuals 413 * that should be notified if this task does 414 * not complete successfully. 415 */ 416 public Task(final String taskID, final String taskClassName, 417 final Date scheduledStartTime, final List<String> dependencyIDs, 418 final FailedDependencyAction failedDependencyAction, 419 final List<String> notifyOnCompletion, 420 final List<String> notifyOnError) 421 { 422 ensureNotNull(taskClassName); 423 424 this.taskClassName = taskClassName; 425 this.scheduledStartTime = scheduledStartTime; 426 this.failedDependencyAction = failedDependencyAction; 427 428 if (taskID == null) 429 { 430 this.taskID = UUID.randomUUID().toString(); 431 } 432 else 433 { 434 this.taskID = taskID; 435 } 436 437 if (dependencyIDs == null) 438 { 439 this.dependencyIDs = Collections.emptyList(); 440 } 441 else 442 { 443 this.dependencyIDs = Collections.unmodifiableList(dependencyIDs); 444 } 445 446 if (notifyOnCompletion == null) 447 { 448 this.notifyOnCompletion = Collections.emptyList(); 449 } 450 else 451 { 452 this.notifyOnCompletion = 453 Collections.unmodifiableList(notifyOnCompletion); 454 } 455 456 if (notifyOnError == null) 457 { 458 this.notifyOnError = Collections.emptyList(); 459 } 460 else 461 { 462 this.notifyOnError = Collections.unmodifiableList(notifyOnError); 463 } 464 465 taskEntry = null; 466 taskEntryDN = ATTR_TASK_ID + '=' + this.taskID + ',' + 467 SCHEDULED_TASKS_BASE_DN; 468 actualStartTime = null; 469 completionTime = null; 470 logMessages = Collections.emptyList(); 471 taskState = TaskState.UNSCHEDULED; 472 } 473 474 475 476 /** 477 * Creates a new task from the provided entry. 478 * 479 * @param entry The entry to use to create this task. 480 * 481 * @throws TaskException If the provided entry cannot be parsed as a 482 * scheduled task. 483 */ 484 public Task(final Entry entry) 485 throws TaskException 486 { 487 taskEntry = entry; 488 taskEntryDN = entry.getDN(); 489 490 // Ensure that the task entry has the appropriate object class for a 491 // scheduled task. 492 if (! entry.hasObjectClass(OC_TASK)) 493 { 494 throw new TaskException(ERR_TASK_MISSING_OC.get(taskEntryDN)); 495 } 496 497 498 // Get the task ID. It must be present. 499 taskID = entry.getAttributeValue(ATTR_TASK_ID); 500 if (taskID == null) 501 { 502 throw new TaskException(ERR_TASK_NO_ID.get(taskEntryDN)); 503 } 504 505 506 // Get the task class name. It must be present. 507 taskClassName = entry.getAttributeValue(ATTR_TASK_CLASS); 508 if (taskClassName == null) 509 { 510 throw new TaskException(ERR_TASK_NO_CLASS.get(taskEntryDN)); 511 } 512 513 514 // Get the task state. If it is not present, then assume "unscheduled". 515 final String stateStr = entry.getAttributeValue(ATTR_TASK_STATE); 516 if (stateStr == null) 517 { 518 taskState = TaskState.UNSCHEDULED; 519 } 520 else 521 { 522 taskState = TaskState.forName(stateStr); 523 if (taskState == null) 524 { 525 throw new TaskException(ERR_TASK_INVALID_STATE.get(taskEntryDN, 526 stateStr)); 527 } 528 } 529 530 531 // Get the scheduled start time. It may be absent. 532 String timestamp = entry.getAttributeValue(ATTR_SCHEDULED_START_TIME); 533 if (timestamp == null) 534 { 535 scheduledStartTime = null; 536 } 537 else 538 { 539 try 540 { 541 scheduledStartTime = decodeGeneralizedTime(timestamp); 542 } 543 catch (final ParseException pe) 544 { 545 debugException(pe); 546 throw new TaskException(ERR_TASK_CANNOT_PARSE_SCHEDULED_START_TIME.get( 547 taskEntryDN, timestamp, pe.getMessage()), 548 pe); 549 } 550 } 551 552 553 // Get the actual start time. It may be absent. 554 timestamp = entry.getAttributeValue(ATTR_ACTUAL_START_TIME); 555 if (timestamp == null) 556 { 557 actualStartTime = null; 558 } 559 else 560 { 561 try 562 { 563 actualStartTime = decodeGeneralizedTime(timestamp); 564 } 565 catch (final ParseException pe) 566 { 567 debugException(pe); 568 throw new TaskException(ERR_TASK_CANNOT_PARSE_ACTUAL_START_TIME.get( 569 taskEntryDN, timestamp, pe.getMessage()), 570 pe); 571 } 572 } 573 574 575 // Get the completion start time. It may be absent. 576 timestamp = entry.getAttributeValue(ATTR_COMPLETION_TIME); 577 if (timestamp == null) 578 { 579 completionTime = null; 580 } 581 else 582 { 583 try 584 { 585 completionTime = decodeGeneralizedTime(timestamp); 586 } 587 catch (final ParseException pe) 588 { 589 debugException(pe); 590 throw new TaskException(ERR_TASK_CANNOT_PARSE_COMPLETION_TIME.get( 591 taskEntryDN, timestamp, pe.getMessage()), 592 pe); 593 } 594 } 595 596 597 // Get the failed dependency action for this task. It may be absent. 598 final String name = entry.getAttributeValue(ATTR_FAILED_DEPENDENCY_ACTION); 599 if (name == null) 600 { 601 failedDependencyAction = null; 602 } 603 else 604 { 605 failedDependencyAction = FailedDependencyAction.forName(name); 606 } 607 608 609 // Get the dependent task IDs for this task. It may be absent. 610 dependencyIDs = parseStringList(entry, ATTR_DEPENDENCY_ID); 611 612 613 // Get the log messages for this task. It may be absent. 614 logMessages = parseStringList(entry, ATTR_LOG_MESSAGE); 615 616 617 // Get the notify on completion addresses for this task. It may be absent. 618 notifyOnCompletion = parseStringList(entry, ATTR_NOTIFY_ON_COMPLETION); 619 620 621 // Get the notify on error addresses for this task. It may be absent. 622 notifyOnError = parseStringList(entry, ATTR_NOTIFY_ON_ERROR); 623 } 624 625 626 627 /** 628 * Creates a new task from the provided set of task properties. 629 * 630 * @param taskClassName The fully-qualified name of the Java class that 631 * provides the logic for the task. It must not be 632 * {@code null}. 633 * @param properties The set of task properties and their corresponding 634 * values to use for the task. It must not be 635 * {@code null}. 636 * 637 * @throws TaskException If the provided set of properties cannot be used to 638 * create a valid scheduled task. 639 */ 640 public Task(final String taskClassName, 641 final Map<TaskProperty,List<Object>> properties) 642 throws TaskException 643 { 644 ensureNotNull(taskClassName, properties); 645 646 this.taskClassName = taskClassName; 647 648 String idStr = UUID.randomUUID().toString(); 649 Date sst = null; 650 String[] depIDs = NO_STRINGS; 651 FailedDependencyAction fda = FailedDependencyAction.CANCEL; 652 String[] noc = NO_STRINGS; 653 String[] noe = NO_STRINGS; 654 655 for (final Map.Entry<TaskProperty,List<Object>> entry : 656 properties.entrySet()) 657 { 658 final TaskProperty p = entry.getKey(); 659 final String attrName = p.getAttributeName(); 660 final List<Object> values = entry.getValue(); 661 662 if (attrName.equalsIgnoreCase(ATTR_TASK_ID)) 663 { 664 idStr = parseString(p, values, idStr); 665 } 666 else if (attrName.equalsIgnoreCase(ATTR_SCHEDULED_START_TIME)) 667 { 668 sst = parseDate(p, values, sst); 669 } 670 else if (attrName.equalsIgnoreCase(ATTR_DEPENDENCY_ID)) 671 { 672 depIDs = parseStrings(p, values, depIDs); 673 } 674 else if (attrName.equalsIgnoreCase(ATTR_FAILED_DEPENDENCY_ACTION)) 675 { 676 fda = FailedDependencyAction.forName( 677 parseString(p, values, fda.getName())); 678 } 679 else if (attrName.equalsIgnoreCase(ATTR_NOTIFY_ON_COMPLETION)) 680 { 681 noc = parseStrings(p, values, noc); 682 } 683 else if (attrName.equalsIgnoreCase(ATTR_NOTIFY_ON_ERROR)) 684 { 685 noe = parseStrings(p, values, noe); 686 } 687 } 688 689 taskID = idStr; 690 scheduledStartTime = sst; 691 dependencyIDs = Collections.unmodifiableList(Arrays.asList(depIDs)); 692 failedDependencyAction = fda; 693 notifyOnCompletion = Collections.unmodifiableList(Arrays.asList(noc)); 694 notifyOnError = Collections.unmodifiableList(Arrays.asList(noe)); 695 taskEntry = null; 696 taskEntryDN = ATTR_TASK_ID + '=' + taskID + ',' + SCHEDULED_TASKS_BASE_DN; 697 actualStartTime = null; 698 completionTime = null; 699 logMessages = Collections.emptyList(); 700 taskState = TaskState.UNSCHEDULED; 701 } 702 703 704 705 /** 706 * Retrieves a list containing instances of the available task types. The 707 * provided task instances will may only be used for obtaining general 708 * information about the task (e.g., name, description, and supported 709 * properties). 710 * 711 * @return A list containing instances of the available task types. 712 */ 713 public static List<Task> getAvailableTaskTypes() 714 { 715 final List<Task> taskList = Arrays.asList( 716 new AddSchemaFileTask(), 717 new AlertTask(), 718 new AuditDataSecurityTask(), 719 new BackupTask(), 720 new DisconnectClientTask(), 721 new DumpDBDetailsTask(), 722 new EnterLockdownModeTask(), 723 new ExportTask(), 724 new GroovyScriptedTask(), 725 new ImportTask(), 726 new LeaveLockdownModeTask(), 727 new RebuildTask(), 728 new ReEncodeEntriesTask(), 729 new RefreshEncryptionSettingsTask(), 730 new ReloadGlobalIndexTask(), 731 new ReloadHTTPConnectionHandlerCertificatesTask(), 732 new RestoreTask(), 733 new RotateLogTask(), 734 new SearchTask(), 735 new ShutdownTask(), 736 new SynchronizeEncryptionSettingsTask(), 737 new ThirdPartyTask()); 738 739 return Collections.unmodifiableList(taskList); 740 } 741 742 743 744 /** 745 * Retrieves a human-readable name for this task. 746 * 747 * @return A human-readable name for this task. 748 */ 749 public String getTaskName() 750 { 751 return INFO_TASK_NAME_GENERIC.get(); 752 } 753 754 755 756 /** 757 * Retrieves a human-readable description for this task. 758 * 759 * @return A human-readable description for this task. 760 */ 761 public String getTaskDescription() 762 { 763 return INFO_TASK_DESCRIPTION_GENERIC.get(); 764 } 765 766 767 768 /** 769 * Retrieves the entry from which this task was decoded, if available. Note 770 * that although the entry is not immutable, changes made to it will not be 771 * reflected in this task. 772 * 773 * @return The entry from which this task was decoded, or {@code null} if 774 * this task was not created from an existing entry. 775 */ 776 protected final Entry getTaskEntry() 777 { 778 return taskEntry; 779 } 780 781 782 783 /** 784 * Retrieves the DN of the entry in which this scheduled task is defined. 785 * 786 * @return The DN of the entry in which this scheduled task is defined. 787 */ 788 public final String getTaskEntryDN() 789 { 790 return taskEntryDN; 791 } 792 793 794 795 /** 796 * Retrieves the task ID for this task. 797 * 798 * @return The task ID for this task. 799 */ 800 public final String getTaskID() 801 { 802 return taskID; 803 } 804 805 806 807 /** 808 * Retrieves the fully-qualified name of the Java class that provides the 809 * logic for this class. 810 * 811 * @return The fully-qualified name of the Java class that provides the logic 812 * for this task. 813 */ 814 public final String getTaskClassName() 815 { 816 return taskClassName; 817 } 818 819 820 821 /** 822 * Retrieves the current state for this task. 823 * 824 * @return The current state for this task. 825 */ 826 public final TaskState getState() 827 { 828 return taskState; 829 } 830 831 832 833 /** 834 * Indicates whether this task is currently pending execution. 835 * 836 * @return {@code true} if this task is currently pending execution, or 837 * {@code false} if not. 838 */ 839 public final boolean isPending() 840 { 841 return taskState.isPending(); 842 } 843 844 845 846 /** 847 * Indicates whether this task is currently running. 848 * 849 * @return {@code true} if this task is currently running, or {@code false} 850 * if not. 851 */ 852 public final boolean isRunning() 853 { 854 return taskState.isRunning(); 855 } 856 857 858 859 /** 860 * Indicates whether this task has completed execution. 861 * 862 * @return {@code true} if this task has completed execution, or 863 * {@code false} if not. 864 */ 865 public final boolean isCompleted() 866 { 867 return taskState.isCompleted(); 868 } 869 870 871 872 /** 873 * Retrieves the time that this task is/was scheduled to start running. 874 * 875 * @return The time that this task is/was scheduled to start running, or 876 * {@code null} if that is not available and therefore the task 877 * should start running as soon as all dependencies have been met. 878 */ 879 public final Date getScheduledStartTime() 880 { 881 return scheduledStartTime; 882 } 883 884 885 886 /** 887 * Retrieves the time that this task actually started running. 888 * 889 * @return The time that this task actually started running, or {@code null} 890 * if that is not available (e.g., because the task has not yet 891 * started). 892 */ 893 public final Date getActualStartTime() 894 { 895 return actualStartTime; 896 } 897 898 899 900 /** 901 * Retrieves the time that this task completed. 902 * 903 * @return The time that this task completed, or {@code null} if it has not 904 * yet completed. 905 */ 906 public final Date getCompletionTime() 907 { 908 return completionTime; 909 } 910 911 912 913 /** 914 * Retrieves a list of the task IDs for tasks that must complete before this 915 * task will be eligible to start. 916 * 917 * @return A list of the task IDs for tasks that must complete before this 918 * task will be eligible to start, or an empty list if this task does 919 * not have any dependencies. 920 */ 921 public final List<String> getDependencyIDs() 922 { 923 return dependencyIDs; 924 } 925 926 927 928 /** 929 * Retrieves the failed dependency action for this task, which indicates the 930 * behavior that it should exhibit if any of its dependencies encounter a 931 * failure. 932 * 933 * @return The failed dependency action for this task, or {@code null} if it 934 * is not available. 935 */ 936 public final FailedDependencyAction getFailedDependencyAction() 937 { 938 return failedDependencyAction; 939 } 940 941 942 943 /** 944 * Retrieves the log messages for this task. Note that if the task has 945 * generated a very large number of log messages, then only a portion of the 946 * most recent messages may be available. 947 * 948 * @return The log messages for this task, or an empty list if this task does 949 * not have any log messages. 950 */ 951 public final List<String> getLogMessages() 952 { 953 return logMessages; 954 } 955 956 957 958 /** 959 * Retrieves a list of the e-mail addresses of the individuals that should be 960 * notified whenever this task completes processing, regardless of whether it 961 * was successful. 962 * 963 * @return A list of the e-mail addresses of the individuals that should be 964 * notified whenever this task completes processing, or an empty list 965 * if there are none. 966 */ 967 public final List<String> getNotifyOnCompletionAddresses() 968 { 969 return notifyOnCompletion; 970 } 971 972 973 974 /** 975 * Retrieves a list of the e-mail addresses of the individuals that should be 976 * notified if this task stops processing prematurely due to an error or 977 * other external action (e.g., server shutdown or administrative cancel). 978 * 979 * @return A list of the e-mail addresses of the individuals that should be 980 * notified if this task stops processing prematurely, or an empty 981 * list if there are none. 982 */ 983 public final List<String> getNotifyOnErrorAddresses() 984 { 985 return notifyOnError; 986 } 987 988 989 990 /** 991 * Creates an entry that may be added to the Directory Server to create a new 992 * instance of this task. 993 * 994 * @return An entry that may be added to the Directory Server to create a new 995 * instance of this task. 996 */ 997 public final Entry createTaskEntry() 998 { 999 final ArrayList<Attribute> attributes = new ArrayList<Attribute>(); 1000 1001 final ArrayList<String> ocValues = new ArrayList<String>(5); 1002 ocValues.add("top"); 1003 ocValues.add(OC_TASK); 1004 ocValues.addAll(getAdditionalObjectClasses()); 1005 attributes.add(new Attribute("objectClass", ocValues)); 1006 1007 attributes.add(new Attribute(ATTR_TASK_ID, taskID)); 1008 1009 attributes.add(new Attribute(ATTR_TASK_CLASS, taskClassName)); 1010 1011 if (scheduledStartTime != null) 1012 { 1013 attributes.add(new Attribute(ATTR_SCHEDULED_START_TIME, 1014 encodeGeneralizedTime(scheduledStartTime))); 1015 } 1016 1017 if (! dependencyIDs.isEmpty()) 1018 { 1019 attributes.add(new Attribute(ATTR_DEPENDENCY_ID, dependencyIDs)); 1020 } 1021 1022 if (failedDependencyAction != null) 1023 { 1024 attributes.add(new Attribute(ATTR_FAILED_DEPENDENCY_ACTION, 1025 failedDependencyAction.getName())); 1026 } 1027 1028 if (! notifyOnCompletion.isEmpty()) 1029 { 1030 attributes.add(new Attribute(ATTR_NOTIFY_ON_COMPLETION, 1031 notifyOnCompletion)); 1032 } 1033 1034 if (! notifyOnError.isEmpty()) 1035 { 1036 attributes.add(new Attribute(ATTR_NOTIFY_ON_ERROR, notifyOnError)); 1037 } 1038 1039 attributes.addAll(getAdditionalAttributes()); 1040 1041 return new Entry(taskEntryDN, attributes); 1042 } 1043 1044 1045 1046 /** 1047 * Parses the value of the specified attribute as a {@code boolean} value, or 1048 * throws an exception if the value cannot be decoded as a boolean. 1049 * 1050 * @param taskEntry The entry containing the attribute to be parsed. 1051 * @param attributeName The name of the attribute from which the value was 1052 * taken. 1053 * @param defaultValue The default value to use if the provided value 1054 * string is {@code null}. 1055 * 1056 * @return {@code true} if the value string represents a boolean value of 1057 * {@code true}, {@code false} if the value string represents a 1058 * boolean value of {@code false}, or the default value if the value 1059 * string is {@code null}. 1060 * 1061 * @throws TaskException If the provided value string cannot be parsed as a 1062 * {@code boolean} value. 1063 */ 1064 protected static boolean parseBooleanValue(final Entry taskEntry, 1065 final String attributeName, 1066 final boolean defaultValue) 1067 throws TaskException 1068 { 1069 final String valueString = taskEntry.getAttributeValue(attributeName); 1070 if (valueString == null) 1071 { 1072 return defaultValue; 1073 } 1074 else if (valueString.equalsIgnoreCase("true")) 1075 { 1076 return true; 1077 } 1078 else if (valueString.equalsIgnoreCase("false")) 1079 { 1080 return false; 1081 } 1082 else 1083 { 1084 throw new TaskException(ERR_TASK_CANNOT_PARSE_BOOLEAN.get( 1085 taskEntry.getDN(), valueString, 1086 attributeName)); 1087 } 1088 } 1089 1090 1091 1092 /** 1093 * Parses the values of the specified attribute as a list of strings. 1094 * 1095 * @param taskEntry The entry containing the attribute to be parsed. 1096 * @param attributeName The name of the attribute from which the value was 1097 * taken. 1098 * 1099 * @return A list of strings containing the values of the specified 1100 * attribute, or an empty list if the specified attribute does not 1101 * exist in the target entry. The returned list will be 1102 * unmodifiable. 1103 */ 1104 protected static List<String> parseStringList(final Entry taskEntry, 1105 final String attributeName) 1106 { 1107 final String[] valueStrings = taskEntry.getAttributeValues(attributeName); 1108 if (valueStrings == null) 1109 { 1110 return Collections.emptyList(); 1111 } 1112 else 1113 { 1114 return Collections.unmodifiableList(Arrays.asList(valueStrings)); 1115 } 1116 } 1117 1118 1119 1120 /** 1121 * Parses the provided set of values for the associated task property as a 1122 * {@code Boolean}. 1123 * 1124 * @param p The task property with which the values are 1125 * associated. 1126 * @param values The provided values for the task property. 1127 * @param defaultValue The default value to use if the provided object array 1128 * is empty. 1129 * 1130 * @return The parsed {@code Boolean} value. 1131 * 1132 * @throws TaskException If there is a problem with the provided values. 1133 */ 1134 protected static Boolean parseBoolean(final TaskProperty p, 1135 final List<Object> values, 1136 final Boolean defaultValue) 1137 throws TaskException 1138 { 1139 // Check to see if any values were provided. If not, then it may or may not 1140 // be a problem. 1141 if (values.isEmpty()) 1142 { 1143 if (p.isRequired()) 1144 { 1145 throw new TaskException(ERR_TASK_REQUIRED_PROPERTY_WITHOUT_VALUES.get( 1146 p.getDisplayName())); 1147 } 1148 else 1149 { 1150 return defaultValue; 1151 } 1152 } 1153 1154 // If there were multiple values, then that's always an error. 1155 if (values.size() > 1) 1156 { 1157 throw new TaskException(ERR_TASK_PROPERTY_NOT_MULTIVALUED.get( 1158 p.getDisplayName())); 1159 } 1160 1161 // Make sure that the value can be interpreted as a Boolean. 1162 final Boolean booleanValue; 1163 final Object o = values.get(0); 1164 if (o instanceof Boolean) 1165 { 1166 booleanValue = (Boolean) o; 1167 } 1168 else if (o instanceof String) 1169 { 1170 final String valueStr = (String) o; 1171 if (valueStr.equalsIgnoreCase("true")) 1172 { 1173 booleanValue = Boolean.TRUE; 1174 } 1175 else if (valueStr.equalsIgnoreCase("false")) 1176 { 1177 booleanValue = Boolean.FALSE; 1178 } 1179 else 1180 { 1181 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_BOOLEAN.get( 1182 p.getDisplayName())); 1183 } 1184 } 1185 else 1186 { 1187 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_BOOLEAN.get( 1188 p.getDisplayName())); 1189 } 1190 1191 return booleanValue; 1192 } 1193 1194 1195 1196 /** 1197 * Parses the provided set of values for the associated task property as a 1198 * {@code Date}. 1199 * 1200 * @param p The task property with which the values are 1201 * associated. 1202 * @param values The provided values for the task property. 1203 * @param defaultValue The default value to use if the provided object array 1204 * is empty. 1205 * 1206 * @return The parsed {@code Date} value. 1207 * 1208 * @throws TaskException If there is a problem with the provided values. 1209 */ 1210 protected static Date parseDate(final TaskProperty p, 1211 final List<Object> values, 1212 final Date defaultValue) 1213 throws TaskException 1214 { 1215 // Check to see if any values were provided. If not, then it may or may not 1216 // be a problem. 1217 if (values.isEmpty()) 1218 { 1219 if (p.isRequired()) 1220 { 1221 throw new TaskException(ERR_TASK_REQUIRED_PROPERTY_WITHOUT_VALUES.get( 1222 p.getDisplayName())); 1223 } 1224 else 1225 { 1226 return defaultValue; 1227 } 1228 } 1229 1230 // If there were multiple values, then that's always an error. 1231 if (values.size() > 1) 1232 { 1233 throw new TaskException(ERR_TASK_PROPERTY_NOT_MULTIVALUED.get( 1234 p.getDisplayName())); 1235 } 1236 1237 // Make sure that the value can be interpreted as a Date. 1238 final Date dateValue; 1239 final Object o = values.get(0); 1240 if (o instanceof Date) 1241 { 1242 dateValue = (Date) o; 1243 } 1244 else if (o instanceof String) 1245 { 1246 try 1247 { 1248 dateValue = decodeGeneralizedTime((String) o); 1249 } 1250 catch (final ParseException pe) 1251 { 1252 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_DATE.get( 1253 p.getDisplayName()), pe); 1254 } 1255 } 1256 else 1257 { 1258 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_DATE.get( 1259 p.getDisplayName())); 1260 } 1261 1262 // If the task property has a set of allowed values, then make sure that the 1263 // provided value is acceptable. 1264 final Object[] allowedValues = p.getAllowedValues(); 1265 if (allowedValues != null) 1266 { 1267 boolean found = false; 1268 for (final Object allowedValue : allowedValues) 1269 { 1270 if (dateValue.equals(allowedValue)) 1271 { 1272 found = true; 1273 break; 1274 } 1275 } 1276 1277 if (! found) 1278 { 1279 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_ALLOWED.get( 1280 p.getDisplayName(), dateValue.toString())); 1281 } 1282 } 1283 1284 return dateValue; 1285 } 1286 1287 1288 1289 /** 1290 * Parses the provided set of values for the associated task property as a 1291 * {@code Long}. 1292 * 1293 * @param p The task property with which the values are 1294 * associated. 1295 * @param values The provided values for the task property. 1296 * @param defaultValue The default value to use if the provided object array 1297 * is empty. 1298 * 1299 * @return The parsed {@code Long} value. 1300 * 1301 * @throws TaskException If there is a problem with the provided values. 1302 */ 1303 protected static Long parseLong(final TaskProperty p, 1304 final List<Object> values, 1305 final Long defaultValue) 1306 throws TaskException 1307 { 1308 // Check to see if any values were provided. If not, then it may or may not 1309 // be a problem. 1310 if (values.isEmpty()) 1311 { 1312 if (p.isRequired()) 1313 { 1314 throw new TaskException(ERR_TASK_REQUIRED_PROPERTY_WITHOUT_VALUES.get( 1315 p.getDisplayName())); 1316 } 1317 else 1318 { 1319 return defaultValue; 1320 } 1321 } 1322 1323 // If there were multiple values, then that's always an error. 1324 if (values.size() > 1) 1325 { 1326 throw new TaskException(ERR_TASK_PROPERTY_NOT_MULTIVALUED.get( 1327 p.getDisplayName())); 1328 } 1329 1330 // Make sure that the value can be interpreted as a Long. 1331 final Long longValue; 1332 final Object o = values.get(0); 1333 if (o instanceof Long) 1334 { 1335 longValue = (Long) o; 1336 } 1337 else if (o instanceof Number) 1338 { 1339 longValue = ((Number) o).longValue(); 1340 } 1341 else if (o instanceof String) 1342 { 1343 try 1344 { 1345 longValue = Long.parseLong((String) o); 1346 } 1347 catch (final Exception e) 1348 { 1349 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_LONG.get( 1350 p.getDisplayName()), e); 1351 } 1352 } 1353 else 1354 { 1355 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_LONG.get( 1356 p.getDisplayName())); 1357 } 1358 1359 // If the task property has a set of allowed values, then make sure that the 1360 // provided value is acceptable. 1361 final Object[] allowedValues = p.getAllowedValues(); 1362 if (allowedValues != null) 1363 { 1364 boolean found = false; 1365 for (final Object allowedValue : allowedValues) 1366 { 1367 if (longValue.equals(allowedValue)) 1368 { 1369 found = true; 1370 break; 1371 } 1372 } 1373 1374 if (! found) 1375 { 1376 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_ALLOWED.get( 1377 p.getDisplayName(), longValue.toString())); 1378 } 1379 } 1380 1381 return longValue; 1382 } 1383 1384 1385 1386 /** 1387 * Parses the provided set of values for the associated task property as a 1388 * {@code String}. 1389 * 1390 * @param p The task property with which the values are 1391 * associated. 1392 * @param values The provided values for the task property. 1393 * @param defaultValue The default value to use if the provided object array 1394 * is empty. 1395 * 1396 * @return The parsed {@code String} value. 1397 * 1398 * @throws TaskException If there is a problem with the provided values. 1399 */ 1400 protected static String parseString(final TaskProperty p, 1401 final List<Object> values, 1402 final String defaultValue) 1403 throws TaskException 1404 { 1405 // Check to see if any values were provided. If not, then it may or may not 1406 // be a problem. 1407 if (values.isEmpty()) 1408 { 1409 if (p.isRequired()) 1410 { 1411 throw new TaskException(ERR_TASK_REQUIRED_PROPERTY_WITHOUT_VALUES.get( 1412 p.getDisplayName())); 1413 } 1414 else 1415 { 1416 return defaultValue; 1417 } 1418 } 1419 1420 // If there were multiple values, then that's always an error. 1421 if (values.size() > 1) 1422 { 1423 throw new TaskException(ERR_TASK_PROPERTY_NOT_MULTIVALUED.get( 1424 p.getDisplayName())); 1425 } 1426 1427 // Make sure that the value is a String. 1428 final String valueStr; 1429 final Object o = values.get(0); 1430 if (o instanceof String) 1431 { 1432 valueStr = (String) o; 1433 } 1434 else if (values.get(0) instanceof CharSequence) 1435 { 1436 valueStr = o.toString(); 1437 } 1438 else 1439 { 1440 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_STRING.get( 1441 p.getDisplayName())); 1442 } 1443 1444 // If the task property has a set of allowed values, then make sure that the 1445 // provided value is acceptable. 1446 final Object[] allowedValues = p.getAllowedValues(); 1447 if (allowedValues != null) 1448 { 1449 boolean found = false; 1450 for (final Object allowedValue : allowedValues) 1451 { 1452 final String s = (String) allowedValue; 1453 if (valueStr.equalsIgnoreCase(s)) 1454 { 1455 found = true; 1456 break; 1457 } 1458 } 1459 1460 if (! found) 1461 { 1462 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_ALLOWED.get( 1463 p.getDisplayName(), valueStr)); 1464 } 1465 } 1466 1467 return valueStr; 1468 } 1469 1470 1471 1472 /** 1473 * Parses the provided set of values for the associated task property as a 1474 * {@code String} array. 1475 * 1476 * @param p The task property with which the values are 1477 * associated. 1478 * @param values The provided values for the task property. 1479 * @param defaultValues The set of default values to use if the provided 1480 * object array is empty. 1481 * 1482 * @return The parsed {@code String} values. 1483 * 1484 * @throws TaskException If there is a problem with the provided values. 1485 */ 1486 protected static String[] parseStrings(final TaskProperty p, 1487 final List<Object> values, 1488 final String[] defaultValues) 1489 throws TaskException 1490 { 1491 // Check to see if any values were provided. If not, then it may or may not 1492 // be a problem. 1493 if (values.isEmpty()) 1494 { 1495 if (p.isRequired()) 1496 { 1497 throw new TaskException(ERR_TASK_REQUIRED_PROPERTY_WITHOUT_VALUES.get( 1498 p.getDisplayName())); 1499 } 1500 else 1501 { 1502 return defaultValues; 1503 } 1504 } 1505 1506 1507 // Iterate through each of the values and perform appropriate validation for 1508 // them. 1509 final String[] stringValues = new String[values.size()]; 1510 for (int i=0; i < values.size(); i++) 1511 { 1512 final Object o = values.get(i); 1513 1514 // Make sure that the value is a String. 1515 final String valueStr; 1516 if (o instanceof String) 1517 { 1518 valueStr = (String) o; 1519 } 1520 else if (o instanceof CharSequence) 1521 { 1522 valueStr = o.toString(); 1523 } 1524 else 1525 { 1526 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_STRING.get( 1527 p.getDisplayName())); 1528 } 1529 1530 // If the task property has a set of allowed values, then make sure that 1531 // the provided value is acceptable. 1532 final Object[] allowedValues = p.getAllowedValues(); 1533 if (allowedValues != null) 1534 { 1535 boolean found = false; 1536 for (final Object allowedValue : allowedValues) 1537 { 1538 final String s = (String) allowedValue; 1539 if (valueStr.equalsIgnoreCase(s)) 1540 { 1541 found = true; 1542 break; 1543 } 1544 } 1545 1546 if (! found) 1547 { 1548 throw new TaskException(ERR_TASK_PROPERTY_VALUE_NOT_ALLOWED.get( 1549 p.getDisplayName(), valueStr)); 1550 } 1551 } 1552 1553 stringValues[i] = valueStr; 1554 } 1555 1556 return stringValues; 1557 } 1558 1559 1560 1561 /** 1562 * Retrieves a list of the additional object classes (other than the base 1563 * "top" and "ds-task" classes) that should be included when creating new task 1564 * entries of this type. 1565 * 1566 * @return A list of the additional object classes that should be included in 1567 * new task entries of this type, or an empty list if there do not 1568 * need to be any additional classes. 1569 */ 1570 protected List<String> getAdditionalObjectClasses() 1571 { 1572 return Collections.emptyList(); 1573 } 1574 1575 1576 1577 /** 1578 * Retrieves a list of the additional attributes (other than attributes common 1579 * to all task types) that should be included when creating new task entries 1580 * of this type. 1581 * 1582 * @return A list of the additional attributes that should be included in new 1583 * task entries of this type, or an empty list if there do not need 1584 * to be any additional attributes. 1585 */ 1586 protected List<Attribute> getAdditionalAttributes() 1587 { 1588 return Collections.emptyList(); 1589 } 1590 1591 1592 1593 /** 1594 * Decodes the provided entry as a scheduled task. An attempt will be made to 1595 * decode the entry as an appropriate subclass if possible, but it will fall 1596 * back to a generic task if it is not possible to decode as a more specific 1597 * task type. 1598 * 1599 * @param entry The entry to be decoded. 1600 * 1601 * @return The decoded task. 1602 * 1603 * @throws TaskException If the provided entry cannot be parsed as a 1604 * scheduled task. 1605 */ 1606 public static Task decodeTask(final Entry entry) 1607 throws TaskException 1608 { 1609 final String taskClass = entry.getAttributeValue(ATTR_TASK_CLASS); 1610 if (taskClass == null) 1611 { 1612 throw new TaskException(ERR_TASK_NO_CLASS.get(entry.getDN())); 1613 } 1614 1615 try 1616 { 1617 if (taskClass.equals(AddSchemaFileTask.ADD_SCHEMA_FILE_TASK_CLASS)) 1618 { 1619 return new AddSchemaFileTask(entry); 1620 } 1621 else if (taskClass.equals(AlertTask.ALERT_TASK_CLASS)) 1622 { 1623 return new AlertTask(entry); 1624 } 1625 else if (taskClass.equals(AuditDataSecurityTask. 1626 AUDIT_DATA_SECURITY_TASK_CLASS)) 1627 { 1628 return new AuditDataSecurityTask(entry); 1629 } 1630 else if (taskClass.equals(BackupTask.BACKUP_TASK_CLASS)) 1631 { 1632 return new BackupTask(entry); 1633 } 1634 else if (taskClass.equals( 1635 DisconnectClientTask.DISCONNECT_CLIENT_TASK_CLASS)) 1636 { 1637 return new DisconnectClientTask(entry); 1638 } 1639 else if (taskClass.equals(DumpDBDetailsTask.DUMP_DB_DETAILS_TASK_CLASS)) 1640 { 1641 return new DumpDBDetailsTask(entry); 1642 } 1643 else if (taskClass.equals( 1644 EnterLockdownModeTask.ENTER_LOCKDOWN_MODE_TASK_CLASS)) 1645 { 1646 return new EnterLockdownModeTask(entry); 1647 } 1648 else if (taskClass.equals(ExportTask.EXPORT_TASK_CLASS)) 1649 { 1650 return new ExportTask(entry); 1651 } 1652 else if (taskClass.equals(GroovyScriptedTask.GROOVY_SCRIPTED_TASK_CLASS)) 1653 { 1654 return new GroovyScriptedTask(entry); 1655 } 1656 else if (taskClass.equals(ImportTask.IMPORT_TASK_CLASS)) 1657 { 1658 return new ImportTask(entry); 1659 } 1660 else if (taskClass.equals( 1661 LeaveLockdownModeTask.LEAVE_LOCKDOWN_MODE_TASK_CLASS)) 1662 { 1663 return new LeaveLockdownModeTask(entry); 1664 } 1665 else if (taskClass.equals(RebuildTask.REBUILD_TASK_CLASS)) 1666 { 1667 return new RebuildTask(entry); 1668 } 1669 else if (taskClass.equals( 1670 ReEncodeEntriesTask.RE_ENCODE_ENTRIES_TASK_CLASS)) 1671 { 1672 return new ReEncodeEntriesTask(entry); 1673 } 1674 else if (taskClass.equals(RefreshEncryptionSettingsTask. 1675 REFRESH_ENCRYPTION_SETTINGS_TASK_CLASS)) 1676 { 1677 return new RefreshEncryptionSettingsTask(entry); 1678 } 1679 else if (taskClass.equals( 1680 ReloadGlobalIndexTask.RELOAD_GLOBAL_INDEX_TASK_CLASS)) 1681 { 1682 return new ReloadGlobalIndexTask(entry); 1683 } 1684 else if (taskClass.equals( 1685 ReloadHTTPConnectionHandlerCertificatesTask. 1686 RELOAD_HTTP_CONNECTION_HANDLER_CERTIFICATES_TASK_CLASS)) 1687 { 1688 return new ReloadHTTPConnectionHandlerCertificatesTask(entry); 1689 } 1690 else if (taskClass.equals(RestoreTask.RESTORE_TASK_CLASS)) 1691 { 1692 return new RestoreTask(entry); 1693 } 1694 else if (taskClass.equals(RotateLogTask.ROTATE_LOG_TASK_CLASS)) 1695 { 1696 return new RotateLogTask(entry); 1697 } 1698 else if (taskClass.equals(SearchTask.SEARCH_TASK_CLASS)) 1699 { 1700 return new SearchTask(entry); 1701 } 1702 else if (taskClass.equals(ShutdownTask.SHUTDOWN_TASK_CLASS)) 1703 { 1704 return new ShutdownTask(entry); 1705 } 1706 else if (taskClass.equals(SynchronizeEncryptionSettingsTask. 1707 SYNCHRONIZE_ENCRYPTION_SETTINGS_TASK_CLASS)) 1708 { 1709 return new SynchronizeEncryptionSettingsTask(entry); 1710 } 1711 else if (taskClass.equals(ThirdPartyTask.THIRD_PARTY_TASK_CLASS)) 1712 { 1713 return new ThirdPartyTask(entry); 1714 } 1715 } 1716 catch (final TaskException te) 1717 { 1718 debugException(te); 1719 } 1720 1721 return new Task(entry); 1722 } 1723 1724 1725 1726 /** 1727 * Retrieves a list of task properties that may be provided when scheduling 1728 * any type of task. This includes: 1729 * <UL> 1730 * <LI>The task ID</LI> 1731 * <LI>The scheduled start time</LI> 1732 * <LI>The task IDs of any tasks on which this task is dependent</LI> 1733 * <LI>The action to take for this task if any of its dependencies fail</LI> 1734 * <LI>The addresses of users to notify when this task completes</LI> 1735 * <LI>The addresses of users to notify if this task fails</LI> 1736 * </UL> 1737 * 1738 * @return A list of task properties that may be provided when scheduling any 1739 * type of task. 1740 */ 1741 public static List<TaskProperty> getCommonTaskProperties() 1742 { 1743 final List<TaskProperty> taskList = Arrays.asList( 1744 PROPERTY_TASK_ID, 1745 PROPERTY_SCHEDULED_START_TIME, 1746 PROPERTY_DEPENDENCY_ID, 1747 PROPERTY_FAILED_DEPENDENCY_ACTION, 1748 PROPERTY_NOTIFY_ON_COMPLETION, 1749 PROPERTY_NOTIFY_ON_ERROR); 1750 1751 return Collections.unmodifiableList(taskList); 1752 } 1753 1754 1755 1756 /** 1757 * Retrieves a list of task-specific properties that may be provided when 1758 * scheduling a task of this type. This method should be overridden by 1759 * subclasses in order to provide an appropriate set of properties. 1760 * 1761 * @return A list of task-specific properties that may be provided when 1762 * scheduling a task of this type. 1763 */ 1764 public List<TaskProperty> getTaskSpecificProperties() 1765 { 1766 return Collections.emptyList(); 1767 } 1768 1769 1770 1771 /** 1772 * Retrieves the values of the task properties for this task. The data type 1773 * of the values will vary based on the data type of the corresponding task 1774 * property and may be one of the following types: {@code Boolean}, 1775 * {@code Date}, {@code Long}, or {@code String}. Task properties which do 1776 * not have any values will be included in the map with an empty value list. 1777 * <BR><BR> 1778 * Note that subclasses which have additional task properties should override 1779 * this method and return a map which contains both the property values from 1780 * this class (obtained from {@code super.getTaskPropertyValues()} and the 1781 * values of their own task-specific properties. 1782 * 1783 * @return A map of the task property values for this task. 1784 */ 1785 public Map<TaskProperty,List<Object>> getTaskPropertyValues() 1786 { 1787 final LinkedHashMap<TaskProperty,List<Object>> props = 1788 new LinkedHashMap<TaskProperty,List<Object>>(); 1789 1790 props.put(PROPERTY_TASK_ID, 1791 Collections.<Object>unmodifiableList(Arrays.asList(taskID))); 1792 1793 if (scheduledStartTime == null) 1794 { 1795 props.put(PROPERTY_SCHEDULED_START_TIME, Collections.emptyList()); 1796 } 1797 else 1798 { 1799 props.put(PROPERTY_SCHEDULED_START_TIME, 1800 Collections.<Object>unmodifiableList(Arrays.asList( 1801 scheduledStartTime))); 1802 } 1803 1804 props.put(PROPERTY_DEPENDENCY_ID, 1805 Collections.<Object>unmodifiableList(dependencyIDs)); 1806 1807 if (failedDependencyAction == null) 1808 { 1809 props.put(PROPERTY_FAILED_DEPENDENCY_ACTION, Collections.emptyList()); 1810 } 1811 else 1812 { 1813 props.put(PROPERTY_FAILED_DEPENDENCY_ACTION, 1814 Collections.<Object>unmodifiableList(Arrays.asList( 1815 failedDependencyAction.getName()))); 1816 } 1817 1818 props.put(PROPERTY_NOTIFY_ON_COMPLETION, 1819 Collections.<Object>unmodifiableList(notifyOnCompletion)); 1820 1821 props.put(PROPERTY_NOTIFY_ON_ERROR, 1822 Collections.<Object>unmodifiableList(notifyOnError)); 1823 1824 return Collections.unmodifiableMap(props); 1825 } 1826 1827 1828 1829 /** 1830 * Retrieves a string representation of this task. 1831 * 1832 * @return A string representation of this task. 1833 */ 1834 @Override() 1835 public final String toString() 1836 { 1837 final StringBuilder buffer = new StringBuilder(); 1838 toString(buffer); 1839 return buffer.toString(); 1840 } 1841 1842 1843 1844 /** 1845 * Appends a string representation of this task to the provided buffer. 1846 * 1847 * @param buffer The buffer to which the string representation should be 1848 * provided. 1849 */ 1850 public final void toString(final StringBuilder buffer) 1851 { 1852 buffer.append("Task(name='"); 1853 buffer.append(getTaskName()); 1854 buffer.append("', className='"); 1855 buffer.append(taskClassName); 1856 buffer.append(", properties={"); 1857 1858 boolean added = false; 1859 for (final Map.Entry<TaskProperty,List<Object>> e : 1860 getTaskPropertyValues().entrySet()) 1861 { 1862 if (added) 1863 { 1864 buffer.append(", "); 1865 } 1866 else 1867 { 1868 added = true; 1869 } 1870 1871 buffer.append(e.getKey().getAttributeName()); 1872 buffer.append("={"); 1873 1874 final Iterator<Object> iterator = e.getValue().iterator(); 1875 while (iterator.hasNext()) 1876 { 1877 buffer.append('\''); 1878 buffer.append(String.valueOf(iterator.next())); 1879 buffer.append('\''); 1880 1881 if (iterator.hasNext()) 1882 { 1883 buffer.append(','); 1884 } 1885 } 1886 1887 buffer.append('}'); 1888 } 1889 1890 buffer.append("})"); 1891 } 1892}