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