1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core;
15
16 import static ch.qos.logback.core.CoreConstants.CONTEXT_NAME_KEY;
17 import static ch.qos.logback.core.CoreConstants.HOSTNAME_KEY;
18
19 import java.util.ArrayList;
20 import java.util.HashMap;
21 import java.util.List;
22 import java.util.Map;
23 import java.util.concurrent.*;
24 import java.util.concurrent.locks.ReentrantLock;
25
26 import ch.qos.logback.core.rolling.helper.FileNamePattern;
27 import ch.qos.logback.core.spi.ConfigurationEvent;
28 import ch.qos.logback.core.spi.ConfigurationEventListener;
29 import ch.qos.logback.core.spi.LifeCycle;
30 import ch.qos.logback.core.spi.SequenceNumberGenerator;
31 import ch.qos.logback.core.status.InfoStatus;
32 import ch.qos.logback.core.status.StatusManager;
33 import ch.qos.logback.core.util.ExecutorServiceUtil;
34 import ch.qos.logback.core.util.NetworkAddressUtil;
35
36 public class ContextBase implements Context, LifeCycle {
37
38 private long birthTime = System.currentTimeMillis();
39
40 private String name;
41 private StatusManager sm = new BasicStatusManager();
42
43
44
45 Map<String, String> propertyMap = new HashMap<String, String>();
46 Map<String, Object> objectMap = new ConcurrentHashMap<>();
47
48 protected ReentrantLock configurationLock = new ReentrantLock();
49
50 final private List<ConfigurationEventListener> configurationEventListenerList = new CopyOnWriteArrayList<>();
51
52 private ScheduledExecutorService scheduledExecutorService;
53
54 private ThreadPoolExecutor threadPoolExecutor;
55 private ExecutorService alternateExecutorService;
56
57
58 protected List<ScheduledFuture<?>> scheduledFutures = new ArrayList<ScheduledFuture<?>>(1);
59 private LifeCycleManager lifeCycleManager;
60 private SequenceNumberGenerator sequenceNumberGenerator;
61
62
63 private volatile boolean started;
64
65 public ContextBase() {
66 }
67
68 public StatusManager getStatusManager() {
69 return sm;
70 }
71
72
73
74
75
76
77
78
79
80
81
82
83 public void setStatusManager(StatusManager statusManager) {
84
85 if (statusManager == null) {
86 throw new IllegalArgumentException("null StatusManager not allowed");
87 }
88 this.sm = statusManager;
89 }
90
91 public Map<String, String> getCopyOfPropertyMap() {
92 return new HashMap<String, String>(propertyMap);
93 }
94
95 public void putProperty(String key, String val) {
96 if (HOSTNAME_KEY.equalsIgnoreCase(key)) {
97 putHostnameProperty(val);
98 } else {
99 this.propertyMap.put(key, val);
100 }
101 }
102
103 @Override
104 public void addSubstitutionProperty(String key, String value) {
105 if (key == null || value == null) {
106 return;
107 }
108
109 value = value.trim();
110 propertyMap.put(key, value);
111 }
112
113
114
115
116
117
118
119
120 public String getProperty(String key) {
121 if (CONTEXT_NAME_KEY.equals(key))
122 return getName();
123 if (HOSTNAME_KEY.equalsIgnoreCase(key)) {
124 return lazyGetHostname();
125 }
126
127 return (String) this.propertyMap.get(key);
128 }
129
130 private String lazyGetHostname() {
131 String hostname = (String) this.propertyMap.get(HOSTNAME_KEY);
132 if (hostname == null) {
133 hostname = new NetworkAddressUtil(this).safelyGetLocalHostName();
134 putHostnameProperty(hostname);
135 }
136 return hostname;
137 }
138
139 private void putHostnameProperty(String hostname) {
140 String existingHostname = (String) this.propertyMap.get(HOSTNAME_KEY);
141 if (existingHostname == null) {
142 this.propertyMap.put(CoreConstants.HOSTNAME_KEY, hostname);
143 } else {
144
145 }
146 }
147
148 public Object getObject(String key) {
149 return objectMap.get(key);
150 }
151
152 public void putObject(String key, Object value) {
153 objectMap.put(key, value);
154 }
155
156 public void removeObject(String key) {
157 objectMap.remove(key);
158 }
159
160 public String getName() {
161 return name;
162 }
163
164 @Override
165 public void start() {
166
167
168
169 started = true;
170 }
171
172 public void stop() {
173
174
175 stopExecutorServices();
176
177 started = false;
178 }
179
180 public boolean isStarted() {
181 return started;
182 }
183
184
185
186
187
188 public void reset() {
189
190 removeShutdownHook();
191 getLifeCycleManager().reset();
192 propertyMap.clear();
193 objectMap.clear();
194 }
195
196
197
198
199
200
201
202
203
204 public void setName(String name) throws IllegalStateException {
205 if (name != null && name.equals(this.name)) {
206 return;
207 }
208 if (this.name == null || CoreConstants.DEFAULT_CONTEXT_NAME.equals(this.name)) {
209 this.name = name;
210 } else {
211 throw new IllegalStateException("Context has been already given a name");
212 }
213 }
214
215 public long getBirthTime() {
216 return birthTime;
217 }
218
219 public ReentrantLock getConfigurationLock() {
220 return configurationLock;
221 }
222
223
224
225 @Override
226 public synchronized ExecutorService getExecutorService() {
227 if (threadPoolExecutor == null) {
228 threadPoolExecutor = (ThreadPoolExecutor) ExecutorServiceUtil.newThreadPoolExecutor();
229 }
230 return threadPoolExecutor;
231 }
232
233 @Override
234 public synchronized ExecutorService getAlternateExecutorService() {
235 if(alternateExecutorService == null) {
236 alternateExecutorService = ExecutorServiceUtil.newAlternateThreadPoolExecutor();
237 }
238 return alternateExecutorService;
239 }
240
241 @Override
242 public synchronized ScheduledExecutorService getScheduledExecutorService() {
243 if (scheduledExecutorService == null) {
244 scheduledExecutorService = ExecutorServiceUtil.newScheduledExecutorService();
245 }
246 return scheduledExecutorService;
247 }
248
249 private synchronized void stopExecutorServices() {
250 ExecutorServiceUtil.shutdown(scheduledExecutorService);
251 scheduledExecutorService = null;
252
253 ExecutorServiceUtil.shutdown(threadPoolExecutor);
254 threadPoolExecutor = null;
255 }
256
257 private void removeShutdownHook() {
258 Thread hook = (Thread) getObject(CoreConstants.SHUTDOWN_HOOK_THREAD);
259 if (hook != null) {
260 removeObject(CoreConstants.SHUTDOWN_HOOK_THREAD);
261
262 try {
263 sm.add(new InfoStatus("Removing shutdownHook " + hook, this));
264 Runtime runtime = Runtime.getRuntime();
265 boolean result = runtime.removeShutdownHook(hook);
266 sm.add(new InfoStatus("ShutdownHook removal result: " + result, this));
267 } catch (IllegalStateException e) {
268
269
270 }
271 }
272 }
273
274 public void register(LifeCycle component) {
275 getLifeCycleManager().register(component);
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289
290 synchronized LifeCycleManager getLifeCycleManager() {
291 if (lifeCycleManager == null) {
292 lifeCycleManager = new LifeCycleManager();
293 }
294 return lifeCycleManager;
295 }
296
297 @Override
298 public String toString() {
299 return name;
300 }
301
302 @Override
303 public void addScheduledFuture(ScheduledFuture<?> scheduledFuture) {
304 scheduledFutures.add(scheduledFuture);
305 }
306
307
308
309
310 @Deprecated
311 public List<ScheduledFuture<?>> getScheduledFutures() {
312 return getCopyOfScheduledFutures();
313 }
314
315 public List<ScheduledFuture<?>> getCopyOfScheduledFutures() {
316 return new ArrayList<ScheduledFuture<?>>(scheduledFutures);
317 }
318
319 public SequenceNumberGenerator getSequenceNumberGenerator() {
320 return sequenceNumberGenerator;
321 }
322
323 public void setSequenceNumberGenerator(SequenceNumberGenerator sequenceNumberGenerator) {
324 this.sequenceNumberGenerator = sequenceNumberGenerator;
325 }
326
327 @Override
328 public void addConfigurationEventListener(ConfigurationEventListener listener) {
329 configurationEventListenerList.add(listener);
330 }
331
332 @Override
333 public void removeConfigurationEventListener(ConfigurationEventListener listener) {
334 configurationEventListenerList.remove(listener);
335 }
336
337 @Override
338 public void fireConfigurationEvent(ConfigurationEvent configurationEvent) {
339 configurationEventListenerList.forEach( l -> l.listen(configurationEvent));
340 }
341 }