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.commons.logging.Log;
28 import org.apache.commons.logging.LogFactory;
29 import org.apache.fulcrum.quartz.QuartzScheduler;
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 Log log = LogFactory.getLog(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<JobEntryQuartz>();
264
265 try
266 {
267 @SuppressWarnings("unchecked")
268 GroupMatcher<JobKey> groupMatcher = GroupMatcher.groupEquals(JobEntryQuartz.DEFAULT_JOB_GROUP_NAME);
269 Set<JobKey> jobKeys = scheduler.getJobKeys(groupMatcher);
270 for (JobKey jk : jobKeys)
271 {
272 List<? extends Trigger> triggers = this.scheduler.getTriggersOfJob(jk);
273
274 if (triggers == null || triggers.isEmpty())
275 {
276 continue;
277 }
278 JobDetail jd = this.scheduler.getJobDetail(jk);
279 JobEntryQuartz job = new JobEntryQuartz(triggers.get(0), jd);
280 job.setJobId(jk.hashCode());
281 jobs.add(job);
282 }
283 }
284 catch (SchedulerException e)
285 {
286 log.error("Problem listing Scheduled Jobs", e);
287 }
288
289 return jobs;
290 }
291
292
293
294
295
296
297
298
299 protected void setEnabled(boolean enabled)
300 {
301 this.enabled = enabled;
302 }
303
304
305
306
307
308
309 @Override
310 public boolean isEnabled()
311 {
312 return enabled;
313 }
314
315
316
317
318 @Override
319 public synchronized void startScheduler()
320 {
321 setEnabled(true);
322 restart();
323 }
324
325
326
327
328 @Override
329 public synchronized void stopScheduler()
330 {
331 log.info("Stopping job scheduler");
332 try
333 {
334 this.scheduler.standby();
335 enabled = false;
336 }
337 catch (SchedulerException e)
338 {
339 log.error("Could not stop scheduler", e);
340 }
341 }
342
343
344
345
346
347
348
349 public synchronized void restart()
350 {
351 if (enabled)
352 {
353 log.info("Starting job scheduler");
354 try
355 {
356 if (!this.scheduler.isStarted())
357 {
358 this.scheduler.start();
359 }
360 else
361 {
362 notify();
363 }
364 }
365 catch (SchedulerException e)
366 {
367 log.error("Could not start scheduler", e);
368 }
369 }
370 }
371
372
373
374
375
376
377
378 private JobEntryQuartz downCast(JobEntry je) throws TurbineException
379 {
380 if (je instanceof JobEntryQuartz)
381 {
382 return (JobEntryQuartz)je;
383 }
384 else
385 {
386 throw new TurbineException("Invalid job type for this scheduler " + je.getClass());
387 }
388 }
389 }
390