1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.syncope.core.provisioning.java.job;
20
21 import java.time.OffsetDateTime;
22 import java.util.Objects;
23 import java.util.Optional;
24 import org.apache.syncope.common.lib.types.AuditElements;
25 import org.apache.syncope.common.lib.types.TaskType;
26 import org.apache.syncope.core.persistence.api.dao.TaskDAO;
27 import org.apache.syncope.core.persistence.api.dao.TaskExecDAO;
28 import org.apache.syncope.core.persistence.api.entity.task.SchedTask;
29 import org.apache.syncope.core.persistence.api.entity.task.TaskExec;
30 import org.apache.syncope.core.persistence.api.entity.task.TaskUtilsFactory;
31 import org.apache.syncope.core.provisioning.api.AuditManager;
32 import org.apache.syncope.core.provisioning.api.data.TaskDataBinder;
33 import org.apache.syncope.core.provisioning.api.event.JobStatusEvent;
34 import org.apache.syncope.core.provisioning.api.job.JobManager;
35 import org.apache.syncope.core.provisioning.api.job.SchedTaskJobDelegate;
36 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
37 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
38 import org.apache.syncope.core.spring.security.SecureRandomUtils;
39 import org.apache.syncope.core.spring.security.SecurityProperties;
40 import org.quartz.JobExecutionContext;
41 import org.quartz.JobExecutionException;
42 import org.slf4j.Logger;
43 import org.slf4j.LoggerFactory;
44 import org.slf4j.MDC;
45 import org.springframework.beans.factory.annotation.Autowired;
46 import org.springframework.context.ApplicationEventPublisher;
47 import org.springframework.transaction.annotation.Transactional;
48
49 public abstract class AbstractSchedTaskJobDelegate<T extends SchedTask> implements SchedTaskJobDelegate {
50
51 protected static final Logger LOG = LoggerFactory.getLogger(SchedTaskJobDelegate.class);
52
53 @Autowired
54 protected SecurityProperties securityProperties;
55
56 protected TaskType taskType;
57
58
59
60
61 protected T task;
62
63
64
65
66 @Autowired
67 protected TaskExecDAO taskExecDAO;
68
69
70
71
72 @Autowired
73 protected TaskDAO taskDAO;
74
75 @Autowired
76 protected TaskUtilsFactory taskUtilsFactory;
77
78 @Autowired
79 protected TaskDataBinder taskDataBinder;
80
81
82
83
84 @Autowired
85 protected NotificationManager notificationManager;
86
87
88
89
90 @Autowired
91 protected AuditManager auditManager;
92
93 @Autowired
94 protected ApplicationEventPublisher publisher;
95
96 protected boolean interrupt;
97
98 protected boolean interrupted;
99
100 protected void setStatus(final String status) {
101 Objects.requireNonNull(task, "Task cannot be undefined");
102 publisher.publishEvent(new JobStatusEvent(this, taskDataBinder.buildRefDesc(task), status));
103 }
104
105 @Override
106 public void interrupt() {
107 interrupt = true;
108 }
109
110 @Override
111 public boolean isInterrupted() {
112 return interrupted;
113 }
114
115 @SuppressWarnings("unchecked")
116 @Transactional
117 @Override
118 public void execute(
119 final TaskType taskType,
120 final String taskKey,
121 final boolean dryRun,
122 final JobExecutionContext context)
123 throws JobExecutionException {
124
125 this.taskType = taskType;
126 task = (T) taskDAO.find(taskType, taskKey);
127 if (task == null) {
128 throw new JobExecutionException("Task " + taskKey + " not found");
129 }
130
131 if (!task.isActive()) {
132 LOG.info("Task {} not active, aborting...", taskKey);
133 return;
134 }
135
136 boolean manageOperationId = Optional.ofNullable(MDC.get(OPERATION_ID)).
137 map(operationId -> false).
138 orElseGet(() -> {
139 MDC.put(OPERATION_ID, SecureRandomUtils.generateRandomUUID().toString());
140 return true;
141 });
142
143 String executor = Optional.ofNullable(context.getMergedJobDataMap().getString(JobManager.EXECUTOR_KEY)).
144 orElse(securityProperties.getAdminUser());
145 TaskExec<SchedTask> execution = taskUtilsFactory.getInstance(taskType).newTaskExec();
146 execution.setStart(OffsetDateTime.now());
147 execution.setTask(task);
148 execution.setExecutor(executor);
149
150 setStatus("Initialization completed");
151
152 AuditElements.Result result;
153
154 try {
155 execution.setMessage(doExecute(dryRun, executor, context));
156 execution.setStatus(TaskJob.Status.SUCCESS.name());
157
158 result = AuditElements.Result.SUCCESS;
159 } catch (JobExecutionException e) {
160 LOG.error("While executing task {}", taskKey, e);
161 result = AuditElements.Result.FAILURE;
162
163 execution.setMessage(ExceptionUtils2.getFullStackTrace(e));
164 execution.setStatus(TaskJob.Status.FAILURE.name());
165 }
166 execution.setEnd(OffsetDateTime.now());
167
168 if (hasToBeRegistered(execution)) {
169 register(execution);
170 }
171 task = (T) taskDAO.save(task);
172
173 setStatus(null);
174
175 notificationManager.createTasks(
176 executor,
177 AuditElements.EventCategoryType.TASK,
178 this.getClass().getSimpleName(),
179 null,
180 this.getClass().getSimpleName(),
181 result,
182 task,
183 execution);
184
185 auditManager.audit(
186 executor,
187 AuditElements.EventCategoryType.TASK,
188 task.getClass().getSimpleName(),
189 null,
190 null,
191 result,
192 task,
193 null);
194
195 if (manageOperationId) {
196 MDC.remove(OPERATION_ID);
197 }
198 }
199
200
201
202
203
204
205
206
207
208
209 protected abstract String doExecute(boolean dryRun, String executor, JobExecutionContext context)
210 throws JobExecutionException;
211
212
213
214
215
216
217
218 protected boolean hasToBeRegistered(final TaskExec<?> execution) {
219 return false;
220 }
221
222 protected void register(final TaskExec<?> execution) {
223 taskExecDAO.saveAndAdd(taskType, task.getKey(), execution);
224 }
225 }