View Javadoc

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   * @since v1.0
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              // Force validation to happen first
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 }