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