1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.config;
18
19 import org.apache.logging.log4j.Logger;
20 import org.apache.logging.log4j.core.AbstractLifeCycle;
21 import org.apache.logging.log4j.core.async.DaemonThreadFactory;
22 import org.apache.logging.log4j.core.util.CronExpression;
23 import org.apache.logging.log4j.status.StatusLogger;
24
25 import java.util.Date;
26 import java.util.concurrent.Callable;
27 import java.util.concurrent.ScheduledExecutorService;
28 import java.util.concurrent.ScheduledFuture;
29 import java.util.concurrent.ScheduledThreadPoolExecutor;
30 import java.util.concurrent.TimeUnit;
31
32
33
34
35 public class ConfigurationScheduler extends AbstractLifeCycle {
36
37 private static final Logger LOGGER = StatusLogger.getLogger();
38 private static final long serialVersionUID = 4570411889877332287L;
39 private ScheduledExecutorService executorService;
40
41 private int scheduledItems = 0;
42
43
44 @Override
45 public void start() {
46 super.start();
47 if (scheduledItems > 0) {
48 LOGGER.debug("Starting {} Log4j2Scheduled threads", scheduledItems);
49 if (scheduledItems > 5) {
50 scheduledItems = 5;
51 }
52 executorService = new ScheduledThreadPoolExecutor(scheduledItems, new DaemonThreadFactory("Log4j2Scheduled-"));
53 } else {
54 LOGGER.debug("No scheduled items");
55 }
56 }
57
58 @Override
59 public void stop() {
60 if (executorService != null) {
61 LOGGER.debug("Stopping Log4j2Scheduled threads.");
62 executorService.shutdown();
63 }
64 super.stop();
65 }
66
67
68
69
70 public void incrementScheduledItems() {
71 if (!isStarted()) {
72 ++scheduledItems;
73 } else {
74 LOGGER.error("Attempted to increment scheduled items after start");
75 }
76 }
77
78
79
80
81 public void decrementScheduledItems() {
82 if (!isStarted() && scheduledItems > 0) {
83 --scheduledItems;
84 }
85 }
86
87
88
89
90
91
92
93
94
95 public <V> ScheduledFuture<V> schedule(Callable<V> callable, long delay, TimeUnit unit) {
96 return executorService.schedule(callable, delay, unit);
97 }
98
99
100
101
102
103
104
105
106
107 public ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) {
108 return executorService.schedule(command, delay, unit);
109 }
110
111
112
113
114
115
116
117
118 public CronScheduledFuture<?> scheduleWithCron(CronExpression cronExpression, Runnable command) {
119 CronRunnable runnable = new CronRunnable(command, cronExpression);
120 ScheduledFuture<?> future = schedule(runnable, nextFireInterval(cronExpression), TimeUnit.MILLISECONDS);
121 CronScheduledFuture<?> cronScheduledFuture = new CronScheduledFuture<>(future);
122 runnable.setScheduledFuture(cronScheduledFuture);
123 return cronScheduledFuture;
124 }
125
126
127
128
129
130
131
132
133
134
135
136
137
138 public ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) {
139 return executorService.scheduleAtFixedRate(command, initialDelay, period, unit);
140 }
141
142
143
144
145
146
147
148
149
150
151
152 public ScheduledFuture<?> scheduleWithFixedDelay(Runnable command, long initialDelay, long delay, TimeUnit unit) {
153 return executorService.scheduleWithFixedDelay(command, initialDelay, delay, unit);
154 }
155
156 private class CronRunnable implements Runnable {
157
158 private final CronExpression cronExpression;
159 private final Runnable runnable;
160 private CronScheduledFuture<?> scheduledFuture;
161
162 public CronRunnable(Runnable runnable, CronExpression cronExpression) {
163 this.cronExpression = cronExpression;
164 this.runnable = runnable;
165 }
166
167 public void setScheduledFuture(CronScheduledFuture<?> future) {
168 this.scheduledFuture = future;
169 }
170
171 public void run() {
172 try {
173 runnable.run();
174 } catch(Throwable ex) {
175 LOGGER.error("Error running command", ex);
176 } finally {
177 ScheduledFuture<?> future = schedule(this, nextFireInterval(cronExpression), TimeUnit.MILLISECONDS);
178 scheduledFuture.setScheduledFuture(future);
179 }
180 }
181 }
182
183 private long nextFireInterval(CronExpression cronExpression) {
184 Date now = new Date();
185 Date fireDate = cronExpression.getNextValidTimeAfter(now);
186 return fireDate.getTime() - now.getTime();
187 }
188
189 }