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 ScheduledExecutorService executorService;
39
40 private int scheduledItems = 0;
41
42
43 @Override
44 public void start() {
45 super.start();
46 if (scheduledItems > 0) {
47 LOGGER.debug("Starting {} Log4j2Scheduled threads", scheduledItems);
48 if (scheduledItems > 5) {
49 scheduledItems = 5;
50 }
51 executorService = new ScheduledThreadPoolExecutor(scheduledItems, new DaemonThreadFactory("Log4j2Scheduled-"));
52 } else {
53 LOGGER.debug("No scheduled items");
54 }
55 }
56
57 @Override
58 public void stop() {
59 if (executorService != null) {
60 LOGGER.debug("Stopping Log4j2Scheduled threads.");
61 executorService.shutdown();
62 }
63 super.stop();
64 }
65
66
67
68
69 public void incrementScheduledItems() {
70 if (!isStarted()) {
71 ++scheduledItems;
72 } else {
73 LOGGER.error("Attempted to increment scheduled items after start");
74 }
75 }
76
77
78
79
80 public void decrementScheduledItems() {
81 if (!isStarted() && scheduledItems > 0) {
82 --scheduledItems;
83 }
84 }
85
86
87
88
89
90
91
92
93
94 public <V> ScheduledFuture<V> schedule(final Callable<V> callable, final long delay, final TimeUnit unit) {
95 return executorService.schedule(callable, delay, unit);
96 }
97
98
99
100
101
102
103
104
105
106 public ScheduledFuture<?> schedule(final Runnable command, final long delay, final TimeUnit unit) {
107 return executorService.schedule(command, delay, unit);
108 }
109
110
111
112
113
114
115
116
117 public CronScheduledFuture<?> scheduleWithCron(final CronExpression cronExpression, final Runnable command) {
118 Date fireDate = cronExpression.getNextValidTimeAfter(new Date());
119 final CronRunnable runnable = new CronRunnable(command, cronExpression);
120 final ScheduledFuture<?> future = schedule(runnable, nextFireInterval(fireDate), TimeUnit.MILLISECONDS);
121 final CronScheduledFuture<?> cronScheduledFuture = new CronScheduledFuture<>(future, fireDate);
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(final Runnable command, final long initialDelay, final long period, final 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(final Runnable command, final long initialDelay, final long delay, final TimeUnit unit) {
153 return executorService.scheduleWithFixedDelay(command, initialDelay, delay, unit);
154 }
155
156 public long nextFireInterval(Date fireDate) {
157 return fireDate.getTime() - new Date().getTime();
158 }
159
160 public class CronRunnable implements Runnable {
161
162 private final CronExpression cronExpression;
163 private final Runnable runnable;
164 private CronScheduledFuture<?> scheduledFuture;
165
166 public CronRunnable(final Runnable runnable, final CronExpression cronExpression) {
167 this.cronExpression = cronExpression;
168 this.runnable = runnable;
169 }
170
171 public void setScheduledFuture(final CronScheduledFuture<?> future) {
172 this.scheduledFuture = future;
173 }
174
175
176
177 @Override
178 public void run() {
179 try {
180 runnable.run();
181 } catch(final Throwable ex) {
182 LOGGER.error("Error running command", ex);
183 } finally {
184 Date fireDate = cronExpression.getNextInvalidTimeAfter(new Date());
185 final ScheduledFuture<?> future = schedule(this, nextFireInterval(fireDate), TimeUnit.MILLISECONDS);
186 scheduledFuture.reset(future, fireDate);
187 }
188 }
189 }
190
191 }