1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.classic.util;
15
16 import org.slf4j.helpers.ThreadLocalMapOfStacks;
17 import org.slf4j.spi.MDCAdapter;
18
19 import java.util.Collections;
20 import java.util.Deque;
21 import java.util.HashMap;
22 import java.util.Map;
23 import java.util.Set;
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41 public class LogbackMDCAdapter implements MDCAdapter {
42
43
44
45
46
47 final ThreadLocal<Map<String, String>> readWriteThreadLocalMap = new ThreadLocal<Map<String, String>>();
48 final ThreadLocal<Map<String, String>> readOnlyThreadLocalMap = new ThreadLocal<Map<String, String>>();
49 private final ThreadLocalMapOfStacks threadLocalMapOfDeques = new ThreadLocalMapOfStacks();
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68 public void put(String key, String val) throws IllegalArgumentException {
69 if (key == null) {
70 throw new IllegalArgumentException("key cannot be null");
71 }
72 Map<String, String> current = readWriteThreadLocalMap.get();
73 if (current == null) {
74 current = new HashMap<String, String>();
75 readWriteThreadLocalMap.set(current);
76 }
77
78 current.put(key, val);
79 nullifyReadOnlyThreadLocalMap();
80 }
81
82
83
84
85
86
87
88 @Override
89 public String get(String key) {
90 Map<String, String> hashMap = readWriteThreadLocalMap.get();
91
92 if ((hashMap != null) && (key != null)) {
93 return hashMap.get(key);
94 } else {
95 return null;
96 }
97 }
98
99
100
101
102
103 @Override
104 public void remove(String key) {
105 if (key == null) {
106 return;
107 }
108
109 Map<String, String> current = readWriteThreadLocalMap.get();
110 if (current != null) {
111 current.remove(key);
112 nullifyReadOnlyThreadLocalMap();
113 }
114 }
115
116 private void nullifyReadOnlyThreadLocalMap() {
117 readOnlyThreadLocalMap.set(null);
118 }
119
120
121
122
123 @Override
124 public void clear() {
125 readWriteThreadLocalMap.set(null);
126 nullifyReadOnlyThreadLocalMap();
127 }
128
129
130
131
132
133
134
135 @SuppressWarnings("unchecked")
136 public Map<String, String> getPropertyMap() {
137 Map<String, String> readOnlyMap = readOnlyThreadLocalMap.get();
138 if (readOnlyMap == null) {
139 Map<String, String> current = readWriteThreadLocalMap.get();
140 if (current != null) {
141 final Map<String, String> tempMap = new HashMap<String, String>(current);
142 readOnlyMap = Collections.unmodifiableMap(tempMap);
143 readOnlyThreadLocalMap.set(readOnlyMap);
144 }
145 }
146 return readOnlyMap;
147 }
148
149
150
151
152
153 public Map getCopyOfContextMap() {
154 Map<String, String> readOnlyMap = getPropertyMap();
155 if (readOnlyMap == null) {
156 return null;
157 } else {
158 return new HashMap<String, String>(readOnlyMap);
159 }
160 }
161
162
163
164
165
166 public Set<String> getKeys() {
167 Map<String, String> readOnlyMap = getPropertyMap();
168
169 if (readOnlyMap != null) {
170 return readOnlyMap.keySet();
171 } else {
172 return null;
173 }
174 }
175
176 @SuppressWarnings("unchecked")
177 public void setContextMap(Map contextMap) {
178 if (contextMap != null) {
179 readWriteThreadLocalMap.set(new HashMap<String, String>(contextMap));
180 } else {
181 readWriteThreadLocalMap.set(null);
182 }
183 nullifyReadOnlyThreadLocalMap();
184 }
185
186
187 @Override
188 public void pushByKey(String key, String value) {
189 threadLocalMapOfDeques.pushByKey(key, value);
190 }
191
192 @Override
193 public String popByKey(String key) {
194 return threadLocalMapOfDeques.popByKey(key);
195 }
196
197 @Override
198 public Deque<String> getCopyOfDequeByKey(String key) {
199 return threadLocalMapOfDeques.getCopyOfDequeByKey(key);
200 }
201
202 @Override
203 public void clearDequeByKey(String key) {
204 threadLocalMapOfDeques.clearDequeByKey(key);
205 }
206
207 }