1 package org.apache.turbine.services.schedule;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.text.ParseException;
23 import java.util.ArrayList;
24 import java.util.List;
25 import java.util.Set;
26
27 import org.apache.fulcrum.quartz.QuartzScheduler;
28 import org.apache.logging.log4j.LogManager;
29 import org.apache.logging.log4j.Logger;
30 import org.apache.turbine.services.InitializationException;
31 import org.apache.turbine.services.TurbineBaseService;
32 import org.apache.turbine.services.TurbineServices;
33 import org.apache.turbine.util.TurbineException;
34 import org.quartz.CronScheduleBuilder;
35 import org.quartz.JobBuilder;
36 import org.quartz.JobDetail;
37 import org.quartz.JobKey;
38 import org.quartz.Scheduler;
39 import org.quartz.SchedulerException;
40 import org.quartz.Trigger;
41 import org.quartz.TriggerBuilder;
42 import org.quartz.impl.matchers.GroupMatcher;
43
44
45
46
47
48
49 public class QuartzSchedulerService
50 extends TurbineBaseService
51 implements ScheduleService
52 {
53
54 protected static final Logger log = LogManager.getLogger(ScheduleService.LOGGER_NAME);
55
56
57 protected boolean enabled = false;
58
59
60 private Scheduler scheduler;
61
62
63
64
65
66
67
68 @Override
69 public void init()
70 throws InitializationException
71 {
72 setEnabled(getConfiguration().getBoolean("enabled", true));
73 QuartzScheduler qs = (QuartzScheduler) TurbineServices.getInstance()
74 .getService(QuartzScheduler.class.getName());
75 this.scheduler = qs.getScheduler();
76
77 restart();
78 setInit(true);
79 }
80
81
82
83
84
85
86 @Override
87 public void shutdown()
88 {
89 try
90 {
91 this.scheduler.shutdown();
92 }
93 catch (SchedulerException e)
94 {
95 log.error("Could not shut down the scheduler service", e);
96 }
97 }
98
99
100
101
102 @Override
103 public JobEntry newJob(int sec, int min, int hour, int wd, int day_mo, String task) throws TurbineException
104 {
105 try
106 {
107 JobDetail jd = JobBuilder.newJob(JobEntryQuartz.class)
108 .withIdentity(task, JobEntryQuartz.DEFAULT_JOB_GROUP_NAME)
109 .build();
110
111 CronScheduleBuilder csb = createCronExpression(sec, min, hour, wd, day_mo);
112
113 Trigger t = TriggerBuilder.newTrigger()
114 .withIdentity(task, JobEntryQuartz.DEFAULT_JOB_GROUP_NAME)
115 .withSchedule(csb)
116 .forJob(jd)
117 .build();
118
119 JobEntryQuartz jeq = new JobEntryQuartz(t, jd);
120
121 return jeq;
122 }
123 catch (ParseException e)
124 {
125 throw new TurbineException("Could not create scheduled job " + task, e);
126 }
127 }
128
129
130
131
132
133
134
135
136
137
138
139
140 private CronScheduleBuilder createCronExpression(int sec, int min, int hour, int wd, int day_mo) throws ParseException
141 {
142 StringBuilder sb = new StringBuilder();
143 sb.append(sec == -1 ? "*" : String.valueOf(sec)).append(' ');
144 sb.append(min == -1 ? "*" : String.valueOf(min)).append(' ');
145 sb.append(hour == -1 ? "*" : String.valueOf(hour)).append(' ');
146 if (day_mo == -1)
147 {
148 sb.append(wd == -1 ? "*" : "?").append(' ');
149 }
150 else
151 {
152 sb.append(day_mo).append(' ');
153 }
154 sb.append("* ");
155 if (day_mo == -1)
156 {
157 sb.append(wd == -1 ? "?" : String.valueOf(wd));
158 }
159 else
160 {
161 sb.append("*");
162 }
163
164 return CronScheduleBuilder.cronSchedule(sb.toString());
165 }
166
167
168
169
170
171
172
173
174 @Override
175 public JobEntry getJob(int oid)
176 throws TurbineException
177 {
178 for (JobEntry je : listJobs())
179 {
180 if (je.getJobId() == oid)
181 {
182 return je;
183 }
184 }
185
186 throw new TurbineException("Could not retrieve scheduled job with id " + oid);
187 }
188
189
190
191
192
193
194
195 @Override
196 public void addJob(JobEntry je)
197 throws TurbineException
198 {
199 try
200 {
201
202 JobEntryQuartz jq = downCast(je);
203 this.scheduler.scheduleJob(jq.getJobDetail(), jq.getJobTrigger());
204 }
205 catch (SchedulerException e)
206 {
207 throw new TurbineException("Problem adding Scheduled Job: " + je.getTask(), e);
208 }
209 }
210
211
212
213
214
215
216
217 @Override
218 public void removeJob(JobEntry je)
219 throws TurbineException
220 {
221 try
222 {
223 JobEntryQuartz jq = downCast(je);
224 this.scheduler.deleteJob(jq.getJobTrigger().getJobKey());
225
226 }
227 catch (SchedulerException e)
228 {
229 throw new TurbineException("Problem removing Scheduled Job: " + je.getTask(), e);
230 }
231 }
232
233
234
235
236
237
238
239 @Override
240 public void updateJob(JobEntry je)
241 throws TurbineException
242 {
243 try
244 {
245
246 JobEntryQuartz jq = downCast(je);
247 this.scheduler.rescheduleJob(jq.getJobTrigger().getKey(), jq.getJobTrigger());
248 }
249 catch (SchedulerException e)
250 {
251 throw new TurbineException("Problem updating Scheduled Job: " + je.getTask(), e);
252 }
253 }
254
255
256
257
258
259
260 @Override
261 public List<? extends JobEntry> listJobs()
262 {
263 List<JobEntryQuartz> jobs = new ArrayList<>();
264
265 try
266 {
267 GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(JobEntryQuartz.DEFAULT_JOB_GROUP_NAME);
268 Set<JobKey> jobKeys = scheduler.getJobKeys(groupMatcher);
269 for (JobKey jk : jobKeys)
270 {
271 List<? extends Trigger> triggers = this.scheduler.getTriggersOfJob(jk);
272
273 if (triggers == null || triggers.isEmpty())
274 {
275 continue;
276 }
277 JobDetail jd = this.scheduler.getJobDetail(jk);
278 JobEntryQuartz job = new JobEntryQuartz(triggers.get(0), jd);
279 job.setJobId(jk.hashCode());
280 jobs.add(job);
281 }
282 }
283 catch (SchedulerException e)
284 {
285 log.error("Problem listing Scheduled Jobs", e);
286 }
287
288 return jobs;
289 }
290
291
292
293
294
295
296
297
298 protected void setEnabled(boolean enabled)
299 {
300 this.enabled = enabled;
301 }
302
303
304
305
306
307
308 @Override
309 public boolean isEnabled()
310 {
311 return enabled;
312 }
313
314
315
316
317 @Override
318 public synchronized void startScheduler()
319 {
320 setEnabled(true);
321 restart();
322 }
323
324
325
326
327 @Override
328 public synchronized void stopScheduler()
329 {
330 log.info("Stopping job scheduler");
331 try
332 {
333 this.scheduler.standby();
334 enabled = false;
335 }
336 catch (SchedulerException e)
337 {
338 log.error("Could not stop scheduler", e);
339 }
340 }
341
342
343
344
345
346
347
348 public synchronized void restart()
349 {
350 if (enabled)
351 {
352 log.info("Starting job scheduler");
353 try
354 {
355 if (!this.scheduler.isStarted())
356 {
357 this.scheduler.start();
358 }
359 else
360 {
361 notify();
362 }
363 }
364 catch (SchedulerException e)
365 {
366 log.error("Could not start scheduler", e);
367 }
368 }
369 }
370
371
372
373
374
375
376
377 private JobEntryQuartz downCast(JobEntry je) throws TurbineException
378 {
379 if (je instanceof JobEntryQuartz)
380 {
381 return (JobEntryQuartz)je;
382 }
383 else
384 {
385 throw new TurbineException("Invalid job type for this scheduler " + je.getClass());
386 }
387 }
388
389
390
391
392
393
394 public Scheduler getScheduler()
395 {
396 return scheduler;
397 }
398
399
400
401
402
403
404
405
406
407
408
409 public JobEntryQuartz buildJobEntry(Trigger trigger, JobDetail jd) {
410 JobEntryQuartz job = new JobEntryQuartz(trigger, jd);
411 return job;
412 }
413 }
414