001package com.identityworksllc.iiq.common.task; 002 003import sailpoint.api.SailPointContext; 004import sailpoint.api.TaskManager; 005import sailpoint.object.*; 006import sailpoint.task.AbstractTaskExecutor; 007import sailpoint.task.TaskMonitor; 008import sailpoint.tools.GeneralException; 009import sailpoint.tools.Message; 010 011import java.util.HashMap; 012import java.util.Map; 013import java.util.concurrent.atomic.AtomicBoolean; 014 015/** 016 * A task executor that will invoke a Rule that returns a boolean indicating that 017 * another task should be run. This can be used to skip an expensive task, or a task 018 * likely to cause problems, such as during externally defined maintenance windows, 019 * final exam periods, or other critical times. 020 * 021 * BETA! 022 */ 023public class ConditionalTask extends AbstractTaskExecutor { 024 private TaskManager taskManager; 025 private final AtomicBoolean terminated; 026 027 /** 028 * Constructs a new conditional task 029 */ 030 public ConditionalTask() { 031 this.terminated = new AtomicBoolean(); 032 } 033 034 @Override 035 public void execute(SailPointContext context, TaskSchedule taskSchedule, TaskResult taskResult, Attributes<String, Object> attributes) throws Exception { 036 TaskMonitor monitor = new TaskMonitor(context, taskResult); 037 super.setMonitor(monitor); 038 039 this.taskManager = new TaskManager(context); 040 041 boolean wait = attributes.getBoolean("awaitCompletion", false); 042 043 String ruleName = attributes.getString("conditionalRuleName"); 044 Rule conditionalRule = context.getObject(Rule.class, ruleName); 045 if (conditionalRule == null) { 046 throw new GeneralException("Unable to find conditional rule: " + ruleName); 047 } 048 049 String taskName = attributes.getString("taskName"); 050 TaskDefinition taskDef = context.getObject(TaskDefinition.class, taskName); 051 if (taskDef == null) { 052 throw new GeneralException("Unable to find child task: " + taskName); 053 } 054 055 Map<String, Object> inputs = new HashMap<>(); 056 057 Object ruleOutput = context.runRule(conditionalRule, inputs); 058 if (ruleOutput instanceof Boolean) { 059 boolean shouldRun = (Boolean) ruleOutput; 060 if (shouldRun) { 061 if (wait) { 062 TaskResult result = taskManager.runSync(taskDef, new HashMap<>()); 063 064 TaskResult parent = monitor.lockMasterResult(); 065 try { 066 parent.assimilateResult(result); 067 } finally { 068 monitor.commitMasterResult(); 069 } 070 } else { 071 TaskSchedule schedule = taskManager.run(taskDef, new HashMap<>()); 072 if (schedule != null) { 073 TaskResult parent = monitor.lockMasterResult(); 074 try { 075 parent.addMessage(Message.info("Started task " + schedule.getName())); 076 } finally { 077 monitor.commitMasterResult(); 078 } 079 } 080 } 081 } else { 082 TaskResult parent = monitor.lockMasterResult(); 083 try { 084 parent.addMessage(Message.info("Conditional rule returned false, indicating that task " + taskDef.getName() + " should be skipped")); 085 } finally { 086 monitor.commitMasterResult(); 087 } 088 } 089 } else { 090 throw new GeneralException("Illegal output of conditional rule: " + ruleOutput); 091 } 092 } 093 094 /** 095 * Terminates the task 096 * @return True, indicating that we have reacted to the termination 097 */ 098 @Override 099 public boolean terminate() { 100 this.terminated.set(true); 101 if (this.taskManager != null) { 102 this.taskManager.terminate(); 103 } 104 return true; 105 } 106}