1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.logging.log4j;
19
20 import java.io.Serializable;
21 import java.util.AbstractCollection;
22 import java.util.Collection;
23 import java.util.Collections;
24 import java.util.Iterator;
25 import java.util.List;
26 import java.util.Map;
27 import java.util.NoSuchElementException;
28
29 import org.apache.logging.log4j.message.ParameterizedMessage;
30 import org.apache.logging.log4j.spi.DefaultThreadContextMap;
31 import org.apache.logging.log4j.spi.DefaultThreadContextStack;
32 import org.apache.logging.log4j.spi.NoOpThreadContextMap;
33 import org.apache.logging.log4j.spi.ThreadContextMap;
34 import org.apache.logging.log4j.spi.ThreadContextMap2;
35 import org.apache.logging.log4j.spi.ThreadContextMapFactory;
36 import org.apache.logging.log4j.spi.ThreadContextStack;
37 import org.apache.logging.log4j.status.StatusLogger;
38 import org.apache.logging.log4j.util.PropertiesUtil;
39
40
41
42
43
44
45
46
47 public final class ThreadContext {
48
49
50
51
52 private static class EmptyThreadContextStack extends AbstractCollection<String> implements ThreadContextStack {
53
54 private static final long serialVersionUID = 1L;
55
56 private static final Iterator<String> EMPTY_ITERATOR = new EmptyIterator<>();
57
58 @Override
59 public String pop() {
60 return null;
61 }
62
63 @Override
64 public String peek() {
65 return null;
66 }
67
68 @Override
69 public void push(final String message) {
70 throw new UnsupportedOperationException();
71 }
72
73 @Override
74 public int getDepth() {
75 return 0;
76 }
77
78 @Override
79 public List<String> asList() {
80 return Collections.emptyList();
81 }
82
83 @Override
84 public void trim(final int depth) {
85
86 }
87
88 @Override
89 public boolean equals(final Object o) {
90
91 return (o instanceof Collection) && ((Collection<?>) o).isEmpty();
92 }
93
94 @Override
95 public int hashCode() {
96
97 return 1;
98 }
99
100 @Override
101 public ContextStack copy() {
102 return this;
103 }
104
105 @Override
106 public <T> T[] toArray(final T[] a) {
107 throw new UnsupportedOperationException();
108 }
109
110 @Override
111 public boolean add(final String e) {
112 throw new UnsupportedOperationException();
113 }
114
115 @Override
116 public boolean containsAll(final Collection<?> c) {
117 return false;
118 }
119
120 @Override
121 public boolean addAll(final Collection<? extends String> c) {
122 throw new UnsupportedOperationException();
123 }
124
125 @Override
126 public boolean removeAll(final Collection<?> c) {
127 throw new UnsupportedOperationException();
128 }
129
130 @Override
131 public boolean retainAll(final Collection<?> c) {
132 throw new UnsupportedOperationException();
133 }
134
135 @Override
136 public Iterator<String> iterator() {
137 return EMPTY_ITERATOR;
138 }
139
140 @Override
141 public int size() {
142 return 0;
143 }
144
145 @Override
146 public ContextStack getImmutableStackOrNull() {
147 return this;
148 }
149 }
150
151
152
153
154
155
156 private static class EmptyIterator<E> implements Iterator<E> {
157
158 @Override
159 public boolean hasNext() {
160 return false;
161 }
162
163 @Override
164 public E next() {
165 throw new NoSuchElementException("This is an empty iterator!");
166 }
167
168 @Override
169 public void remove() {
170
171 }
172 }
173
174
175
176
177
178 @SuppressWarnings("PublicStaticCollectionField")
179
180 public static final Map<String, String> EMPTY_MAP = Collections.emptyMap();
181
182
183
184
185
186 @SuppressWarnings("PublicStaticCollectionField")
187 public static final ThreadContextStack EMPTY_STACK = new EmptyThreadContextStack();
188
189 private static final String DISABLE_MAP = "disableThreadContextMap";
190 private static final String DISABLE_STACK = "disableThreadContextStack";
191 private static final String DISABLE_ALL = "disableThreadContext";
192
193 private static boolean disableAll;
194 private static boolean useMap;
195 private static boolean useStack;
196 private static ThreadContextMap contextMap;
197 private static ThreadContextStack contextStack;
198 private static final Logger LOGGER = StatusLogger.getLogger();
199
200 static {
201 init();
202 }
203
204 private ThreadContext() {
205
206 }
207
208
209
210
211 static void init() {
212 contextMap = null;
213 final PropertiesUtil managerProps = PropertiesUtil.getProperties();
214 disableAll = managerProps.getBooleanProperty(DISABLE_ALL);
215 useStack = !(managerProps.getBooleanProperty(DISABLE_STACK) || disableAll);
216 useMap = !(managerProps.getBooleanProperty(DISABLE_MAP) || disableAll);
217
218 contextStack = new DefaultThreadContextStack(useStack);
219 if (!useMap) {
220 contextMap = new NoOpThreadContextMap();
221 } else {
222 contextMap = ThreadContextMapFactory.createThreadContextMap();
223 }
224 }
225
226
227
228
229
230
231
232
233
234
235
236
237 public static void put(final String key, final String value) {
238 contextMap.put(key, value);
239 }
240
241
242
243
244
245
246
247
248
249
250 public static void putAll(final Map<String, String> m) {
251 if (contextMap instanceof ThreadContextMap2) {
252 ((ThreadContextMap2) contextMap).putAll(m);
253 } else if (contextMap instanceof DefaultThreadContextMap) {
254 ((DefaultThreadContextMap) contextMap).putAll(m);
255 } else {
256 for (final Map.Entry<String, String> entry: m.entrySet()) {
257 contextMap.put(entry.getKey(), entry.getValue());
258 }
259 }
260 }
261
262
263
264
265
266
267
268
269
270
271
272 public static String get(final String key) {
273 return contextMap.get(key);
274 }
275
276
277
278
279
280
281 public static void remove(final String key) {
282 contextMap.remove(key);
283 }
284
285
286
287
288 public static void clearMap() {
289 contextMap.clear();
290 }
291
292
293
294
295 public static void clearAll() {
296 clearMap();
297 clearStack();
298 }
299
300
301
302
303
304
305
306 public static boolean containsKey(final String key) {
307 return contextMap.containsKey(key);
308 }
309
310
311
312
313
314
315 public static Map<String, String> getContext() {
316 return contextMap.getCopy();
317 }
318
319
320
321
322
323
324 public static Map<String, String> getImmutableContext() {
325 final Map<String, String> map = contextMap.getImmutableMapOrNull();
326 return map == null ? EMPTY_MAP : map;
327 }
328
329
330
331
332
333
334
335
336
337 static ThreadContextMap getThreadContextMap() {
338 return contextMap;
339 }
340
341
342
343
344
345
346 public static boolean isEmpty() {
347 return contextMap.isEmpty();
348 }
349
350
351
352
353 public static void clearStack() {
354 contextStack.clear();
355 }
356
357
358
359
360
361
362 public static ContextStack cloneStack() {
363 return contextStack.copy();
364 }
365
366
367
368
369
370
371 public static ContextStack getImmutableStack() {
372 final ContextStack result = contextStack.getImmutableStackOrNull();
373 return result == null ? EMPTY_STACK : result;
374 }
375
376
377
378
379
380
381 public static void setStack(final Collection<String> stack) {
382 if (stack.isEmpty() || !useStack) {
383 return;
384 }
385 contextStack.clear();
386 contextStack.addAll(stack);
387 }
388
389
390
391
392
393
394
395
396 public static int getDepth() {
397 return contextStack.getDepth();
398 }
399
400
401
402
403
404
405
406
407
408
409
410 public static String pop() {
411 return contextStack.pop();
412 }
413
414
415
416
417
418
419
420
421
422
423
424 public static String peek() {
425 return contextStack.peek();
426 }
427
428
429
430
431
432
433
434
435
436
437 public static void push(final String message) {
438 contextStack.push(message);
439 }
440
441
442
443
444
445
446
447
448
449
450
451
452
453 public static void push(final String message, final Object... args) {
454 contextStack.push(ParameterizedMessage.format(message, args));
455 }
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473 public static void removeStack() {
474 contextStack.clear();
475 }
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509 public static void trim(final int depth) {
510 contextStack.trim(depth);
511 }
512
513
514
515
516 public interface ContextStack extends Serializable, Collection<String> {
517
518
519
520
521
522
523
524 String pop();
525
526
527
528
529
530
531 String peek();
532
533
534
535
536
537
538 void push(String message);
539
540
541
542
543
544
545 int getDepth();
546
547
548
549
550
551
552 List<String> asList();
553
554
555
556
557
558
559 void trim(int depth);
560
561
562
563
564
565
566 ContextStack copy();
567
568
569
570
571
572
573
574 ContextStack getImmutableStackOrNull();
575 }
576 }