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