1 package com.atlassian.scheduler.quartz2;
2
3 import com.atlassian.scheduler.SchedulerServiceException;
4 import com.atlassian.scheduler.config.CronScheduleInfo;
5 import com.atlassian.scheduler.config.IntervalScheduleInfo;
6 import com.atlassian.scheduler.config.JobConfig;
7 import com.atlassian.scheduler.config.JobId;
8 import com.atlassian.scheduler.config.Schedule;
9 import com.atlassian.scheduler.core.spi.SchedulerServiceConfiguration;
10 import com.atlassian.scheduler.core.util.ParameterMapSerializer;
11 import com.atlassian.scheduler.cron.CronSyntaxException;
12 import org.quartz.CronExpression;
13 import org.quartz.CronScheduleBuilder;
14 import org.quartz.CronTrigger;
15 import org.quartz.JobDataMap;
16 import org.quartz.SimpleScheduleBuilder;
17 import org.quartz.SimpleTrigger;
18 import org.quartz.TriggerBuilder;
19
20 import javax.annotation.Nonnull;
21 import java.text.ParseException;
22 import java.util.Date;
23 import java.util.Locale;
24 import java.util.TimeZone;
25
26 import static com.atlassian.scheduler.core.util.CronExpressionQuantizer.quantizeSecondsField;
27 import static com.atlassian.scheduler.core.util.QuartzParseExceptionMapper.mapException;
28 import static com.atlassian.scheduler.core.util.TimeIntervalQuantizer.quantizeToMinutes;
29 import static com.atlassian.scheduler.quartz2.Quartz2SchedulerFacade.QUARTZ_PARAMETERS_KEY;
30 import static com.atlassian.scheduler.quartz2.Quartz2SchedulerFacade.QUARTZ_TRIGGER_GROUP;
31 import static org.quartz.CronScheduleBuilder.cronScheduleNonvalidatedExpression;
32 import static org.quartz.SimpleScheduleBuilder.simpleSchedule;
33 import static org.quartz.TriggerKey.triggerKey;
34
35
36
37
38 class Quartz2TriggerFactory {
39 private final SchedulerServiceConfiguration config;
40 private final ParameterMapSerializer parameterMapSerializer;
41
42 Quartz2TriggerFactory(SchedulerServiceConfiguration config, ParameterMapSerializer parameterMapSerializer) {
43 this.config = config;
44 this.parameterMapSerializer = parameterMapSerializer;
45 }
46
47 public TriggerBuilder<?> buildTrigger(final JobId jobId, final JobConfig jobConfig)
48 throws SchedulerServiceException {
49 final byte[] parameters = parameterMapSerializer.serializeParameters(jobConfig.getParameters());
50 final JobDataMap jobDataMap = new JobDataMap();
51 jobDataMap.put(QUARTZ_PARAMETERS_KEY, parameters);
52 return buildTrigger(jobConfig.getSchedule())
53 .withIdentity(triggerKey(jobId.toString(), QUARTZ_TRIGGER_GROUP))
54 .usingJobData(jobDataMap);
55 }
56
57 public TriggerBuilder<?> buildTrigger(Schedule schedule) throws SchedulerServiceException {
58 switch (schedule.getType()) {
59 case INTERVAL:
60 return getSimpleTrigger(schedule.getIntervalScheduleInfo());
61 case CRON_EXPRESSION:
62 return getCronTrigger(schedule.getCronScheduleInfo());
63 }
64 throw new IllegalStateException("type=" + schedule.getType());
65 }
66
67 private static TriggerBuilder<SimpleTrigger> getSimpleTrigger(IntervalScheduleInfo info) {
68 final Date startTime = (info.getFirstRunTime() != null) ? info.getFirstRunTime() : new Date();
69 return TriggerBuilder.newTrigger()
70 .withSchedule(interval(info.getIntervalInMillis()))
71 .startAt(startTime);
72 }
73
74 private static SimpleScheduleBuilder interval(final long intervalInMillis) {
75 if (intervalInMillis == 0L) {
76 return simpleSchedule().withRepeatCount(0);
77 }
78
79 return simpleSchedule()
80 .withIntervalInMilliseconds(quantizeToMinutes(intervalInMillis))
81 .repeatForever();
82 }
83
84 private TriggerBuilder<CronTrigger> getCronTrigger(CronScheduleInfo info) throws CronSyntaxException {
85 try {
86
87 final String cronExpression = new CronExpression(info.getCronExpression()).getCronExpression();
88 final CronScheduleBuilder schedule = cronScheduleNonvalidatedExpression(quantizeSecondsField(cronExpression))
89 .inTimeZone(getTimeZone(info));
90 return TriggerBuilder.newTrigger()
91 .withSchedule(schedule);
92 } catch (ParseException pe) {
93 throw mapException(info.getCronExpression().toUpperCase(Locale.US), pe);
94 }
95 }
96
97 @Nonnull
98 private TimeZone getTimeZone(CronScheduleInfo info) {
99 TimeZone timeZone = info.getTimeZone();
100 if (timeZone == null) {
101 timeZone = config.getDefaultTimeZone();
102 if (timeZone == null) {
103 timeZone = TimeZone.getDefault();
104 }
105 }
106 return timeZone;
107 }
108 }