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 final CronRunnable runnable = new CronRunnable(command, cronExpression);
119 final ScheduledFuture<?> future = schedule(runnable, nextFireInterval(cronExpression), TimeUnit.MILLISECONDS);
120 final CronScheduledFuture<?> cronScheduledFuture = new CronScheduledFuture<>(future);
121 runnable.setScheduledFuture(cronScheduledFuture);
122 return cronScheduledFuture;
123 }
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public ScheduledFuture<?> scheduleAtFixedRate(final Runnable command, final long initialDelay, final long period, final TimeUnit unit) {
138 return executorService.scheduleAtFixedRate(command, initialDelay, period, unit);
139 }
140
141
142
143
144
145
146
147
148
149
150
151 public ScheduledFuture<?> scheduleWithFixedDelay(final Runnable command, final long initialDelay, final long delay, final TimeUnit unit) {
152 return executorService.scheduleWithFixedDelay(command, initialDelay, delay, unit);
153 }
154
155 private class CronRunnable implements Runnable {
156
157 private final CronExpression cronExpression;
158 private final Runnable runnable;
159 private CronScheduledFuture<?> scheduledFuture;
160
161 public CronRunnable(final Runnable runnable, final CronExpression cronExpression) {
162 this.cronExpression = cronExpression;
163 this.runnable = runnable;
164 }
165
166 public void setScheduledFuture(final CronScheduledFuture<?> future) {
167 this.scheduledFuture = future;
168 }
169
170 @Override
171 public void run() {
172 try {
173 runnable.run();
174 } catch(final Throwable ex) {
175 LOGGER.error("Error running command", ex);
176 } finally {
177 final ScheduledFuture<?> future = schedule(this, nextFireInterval(cronExpression), TimeUnit.MILLISECONDS);
178 scheduledFuture.setScheduledFuture(future);
179 }
180 }
181 }
182
183 private long nextFireInterval(final CronExpression cronExpression) {
184 final Date now = new Date();
185 final Date fireDate = cronExpression.getNextValidTimeAfter(now);
186 return fireDate.getTime() - now.getTime();
187 }
188
189 }