1 package com.atlassian.sal.core.scheduling;
2
3 import com.atlassian.sal.api.scheduling.PluginJob;
4 import com.atlassian.sal.api.scheduling.PluginScheduler;
5
6 import java.util.Date;
7 import java.util.Map;
8 import java.util.concurrent.ConcurrentHashMap;
9 import java.util.concurrent.Executors;
10 import java.util.concurrent.Future;
11 import java.util.concurrent.ScheduledExecutorService;
12 import java.util.concurrent.TimeUnit;
13
14
15
16
17 public class ExecutorPluginScheduler implements PluginScheduler
18 {
19
20 public static final int DEFAULT_POOL_SIZE = 5;
21 private final ScheduledExecutorService jobExecutor;
22 private final Map<String, Future<?>> jobs;
23
24 public ExecutorPluginScheduler()
25 {
26 this(Executors.newScheduledThreadPool(DEFAULT_POOL_SIZE));
27 }
28
29 public ExecutorPluginScheduler(ScheduledExecutorService executor)
30 {
31 this.jobExecutor = executor;
32 this.jobs = new ConcurrentHashMap<String, Future<?>>();
33 }
34
35 @Override
36 public synchronized void scheduleJob(String jobKey, Class<? extends PluginJob> jobClass, Map<String, Object> jobDataMap, Date startTime, long repeatInterval)
37 {
38 final Future<?> job = jobs.get(jobKey);
39 if (job != null)
40 {
41 cancelJob(job);
42 }
43
44 jobs.put(jobKey, jobExecutor.scheduleAtFixedRate(new Job(jobClass, jobDataMap), getDelay(startTime), repeatInterval, TimeUnit.MILLISECONDS));
45 }
46
47 @Override
48 public synchronized void unscheduleJob(String jobKey)
49 {
50 final Future<?> job = jobs.remove(jobKey);
51 if (job != null)
52 {
53 cancelJob(job);
54 }
55 else
56 {
57 throw new IllegalArgumentException("Attempted to unschedule unknown job: " + jobKey);
58 }
59 }
60
61 protected void cancelJob(Future<?> job)
62 {
63 job.cancel(false);
64 }
65
66 private long getDelay(Date startTime)
67 {
68 final long time = startTime.getTime() - System.currentTimeMillis();
69 return time > 0 ? time : 0;
70 }
71
72 private static class Job implements Runnable
73 {
74
75 private final Class<? extends PluginJob> jobClass;
76 private final Map<String, Object> jobDataMap;
77
78 private Job(Class<? extends PluginJob> jobClass, Map<String, Object> jobDataMap)
79 {
80 this.jobClass = jobClass;
81 this.jobDataMap = jobDataMap;
82 }
83
84 @Override
85 public void run()
86 {
87 PluginJob job;
88 try
89 {
90 job = jobClass.newInstance();
91 } catch (final InstantiationException ie)
92 {
93 throw new IllegalStateException("Error instantiating job", ie);
94 } catch (final IllegalAccessException iae)
95 {
96 throw new IllegalStateException("Cannot access job class", iae);
97 }
98 job.execute(jobDataMap);
99 }
100 }
101
102 }