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.report;
20
21 import java.io.ByteArrayOutputStream;
22 import java.io.IOException;
23 import java.io.OutputStream;
24 import java.time.OffsetDateTime;
25 import java.util.Objects;
26 import java.util.Optional;
27 import java.util.zip.Deflater;
28 import java.util.zip.ZipEntry;
29 import java.util.zip.ZipOutputStream;
30 import org.apache.syncope.common.lib.report.ReportConf;
31 import org.apache.syncope.common.lib.types.AuditElements;
32 import org.apache.syncope.core.persistence.api.dao.ReportDAO;
33 import org.apache.syncope.core.persistence.api.entity.EntityFactory;
34 import org.apache.syncope.core.persistence.api.entity.Report;
35 import org.apache.syncope.core.persistence.api.entity.ReportExec;
36 import org.apache.syncope.core.provisioning.api.AuditManager;
37 import org.apache.syncope.core.provisioning.api.data.ReportDataBinder;
38 import org.apache.syncope.core.provisioning.api.event.JobStatusEvent;
39 import org.apache.syncope.core.provisioning.api.job.JobManager;
40 import org.apache.syncope.core.provisioning.api.job.report.ReportJobDelegate;
41 import org.apache.syncope.core.provisioning.api.notification.NotificationManager;
42 import org.apache.syncope.core.provisioning.api.utils.ExceptionUtils2;
43 import org.apache.syncope.core.spring.security.SecurityProperties;
44 import org.quartz.JobExecutionContext;
45 import org.quartz.JobExecutionException;
46 import org.slf4j.Logger;
47 import org.slf4j.LoggerFactory;
48 import org.springframework.beans.factory.annotation.Autowired;
49 import org.springframework.context.ApplicationEventPublisher;
50 import org.springframework.transaction.annotation.Transactional;
51
52 public abstract class AbstractReportJobDelegate implements ReportJobDelegate {
53
54 protected static final Logger LOG = LoggerFactory.getLogger(ReportJobDelegate.class);
55
56 @Autowired
57 protected SecurityProperties securityProperties;
58
59
60
61
62 protected Report report;
63
64 protected ReportConf conf;
65
66
67
68
69 @Autowired
70 protected ReportDAO reportDAO;
71
72 @Autowired
73 protected EntityFactory entityFactory;
74
75 @Autowired
76 protected ReportDataBinder reportDataBinder;
77
78
79
80
81 @Autowired
82 protected NotificationManager notificationManager;
83
84
85
86
87 @Autowired
88 protected AuditManager auditManager;
89
90 @Autowired
91 protected ApplicationEventPublisher publisher;
92
93 protected boolean interrupt;
94
95 protected boolean interrupted;
96
97 @Override
98 public void setConf(final ReportConf conf) {
99 this.conf = conf;
100 }
101
102 protected void setStatus(final String status) {
103 Objects.requireNonNull(report, "Report cannot be undefined");
104 publisher.publishEvent(new JobStatusEvent(this, reportDataBinder.buildRefDesc(report), status));
105 }
106
107 @Override
108 public void interrupt() {
109 interrupt = true;
110 }
111
112 @Override
113 public boolean isInterrupted() {
114 return interrupted;
115 }
116
117 @Transactional
118 @Override
119 public void execute(
120 final String reportKey,
121 final boolean dryRun,
122 final JobExecutionContext context) throws JobExecutionException {
123
124 report = reportDAO.find(reportKey);
125 if (report == null) {
126 throw new JobExecutionException("Report " + reportKey + " not found");
127 }
128
129 if (!report.isActive()) {
130 LOG.info("Report {} not active, aborting...", reportKey);
131 return;
132 }
133
134 String executor = Optional.ofNullable(context.getMergedJobDataMap().getString(JobManager.EXECUTOR_KEY)).
135 orElse(securityProperties.getAdminUser());
136 ReportExec execution = entityFactory.newEntity(ReportExec.class);
137 execution.setStart(OffsetDateTime.now());
138 execution.setReport(report);
139 execution.setExecutor(executor);
140
141 setStatus("Initialization completed");
142
143 AuditElements.Result result;
144
145 ByteArrayOutputStream baos = new ByteArrayOutputStream();
146 ZipOutputStream zos = new ZipOutputStream(baos);
147 zos.setLevel(Deflater.BEST_COMPRESSION);
148 try {
149
150 zos.putNextEntry(new ZipEntry(report.getName()));
151 } catch (IOException e) {
152 throw new JobExecutionException("While configuring for output", e, true);
153 }
154
155 setStatus("Starting");
156 try {
157 execution.setMessage(doExecute(dryRun, zos, executor, context));
158 execution.setStatus(ReportJob.Status.SUCCESS.name());
159
160 result = AuditElements.Result.SUCCESS;
161 } catch (JobExecutionException e) {
162 LOG.error("While executing report {}", reportKey, e);
163 result = AuditElements.Result.FAILURE;
164
165 execution.setMessage(ExceptionUtils2.getFullStackTrace(e));
166 execution.setStatus(ReportJob.Status.FAILURE.name());
167 } finally {
168 setStatus(null);
169
170 try {
171 zos.closeEntry();
172 zos.close();
173 } catch (IOException e) {
174 LOG.error("While closing output", e);
175 }
176 }
177 if (result == AuditElements.Result.SUCCESS) {
178 execution.setExecResult(baos.toByteArray());
179 }
180 execution.setEnd(OffsetDateTime.now());
181
182 report.add(execution);
183 report = reportDAO.save(report);
184
185 setStatus(null);
186
187 notificationManager.createTasks(
188 executor,
189 AuditElements.EventCategoryType.REPORT,
190 this.getClass().getSimpleName(),
191 null,
192 this.getClass().getSimpleName(),
193 result,
194 report,
195 execution);
196
197 auditManager.audit(
198 executor,
199 AuditElements.EventCategoryType.REPORT,
200 report.getClass().getSimpleName(),
201 null,
202 null,
203 result,
204 report,
205 null);
206 }
207
208
209
210
211
212
213
214
215
216
217
218 protected abstract String doExecute(
219 boolean dryRun, OutputStream os, String executor, JobExecutionContext context)
220 throws JobExecutionException;
221 }