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 public static final int DEFAULT_POOL_SIZE = 5;
20 private final ScheduledExecutorService jobExecutor;
21 private final Map<String, Future<?>> jobs;
22
23 public ExecutorPluginScheduler() {
24 this(Executors.newScheduledThreadPool(DEFAULT_POOL_SIZE));
25 }
26
27 public ExecutorPluginScheduler(ScheduledExecutorService executor) {
28 this.jobExecutor = executor;
29 this.jobs = new ConcurrentHashMap<String, Future<?>>();
30 }
31
32 @Override
33 public synchronized void scheduleJob(String jobKey, Class<? extends PluginJob> jobClass, Map<String, Object> jobDataMap, Date startTime, long repeatInterval) {
34 final Future<?> job = jobs.get(jobKey);
35 if (job != null) {
36 cancelJob(job);
37 }
38
39 jobs.put(jobKey, jobExecutor.scheduleAtFixedRate(new Job(jobClass, jobDataMap), getDelay(startTime), repeatInterval, TimeUnit.MILLISECONDS));
40 }
41
42 @Override
43 public synchronized void unscheduleJob(String jobKey) {
44 final Future<?> job = jobs.remove(jobKey);
45 if (job != null) {
46 cancelJob(job);
47 } else {
48 throw new IllegalArgumentException("Attempted to unschedule unknown job: " + jobKey);
49 }
50 }
51
52 protected void cancelJob(Future<?> job) {
53 job.cancel(false);
54 }
55
56 private long getDelay(Date startTime) {
57 final long time = startTime.getTime() - System.currentTimeMillis();
58 return time > 0 ? time : 0;
59 }
60
61 private static class Job implements Runnable {
62
63 private final Class<? extends PluginJob> jobClass;
64 private final Map<String, Object> jobDataMap;
65
66 private Job(Class<? extends PluginJob> jobClass, Map<String, Object> jobDataMap) {
67 this.jobClass = jobClass;
68 this.jobDataMap = jobDataMap;
69 }
70
71 @Override
72 public void run() {
73 PluginJob job;
74 try {
75 job = jobClass.newInstance();
76 } catch (final InstantiationException ie) {
77 throw new IllegalStateException("Error instantiating job", ie);
78 } catch (final IllegalAccessException iae) {
79 throw new IllegalStateException("Cannot access job class", iae);
80 }
81 job.execute(jobDataMap);
82 }
83 }
84
85 }