1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.mina.filter.logging;
21
22 import java.net.InetSocketAddress;
23 import java.util.EnumSet;
24 import java.util.HashSet;
25 import java.util.Map;
26 import java.util.Set;
27 import java.util.Arrays;
28 import java.util.concurrent.ConcurrentHashMap;
29
30 import org.apache.mina.core.filterchain.IoFilterEvent;
31 import org.apache.mina.core.session.AttributeKey;
32 import org.apache.mina.core.session.IoSession;
33 import org.apache.mina.filter.util.CommonEventFilter;
34 import org.slf4j.MDC;
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73 public class MdcInjectionFilter extends CommonEventFilter {
74
75
76
77 public enum MdcKey {
78
79 handlerClass,
80
81
82 remoteAddress,
83
84
85 localAddress,
86
87
88 remoteIp,
89
90
91 remotePort,
92
93
94 localIp,
95
96
97 localPort
98 }
99
100
101 private static final AttributeKeyteKey.html#AttributeKey">AttributeKey CONTEXT_KEY = new AttributeKey(MdcInjectionFilter.class, "context");
102
103 private ThreadLocal<Integer> callDepth = new ThreadLocal<Integer>() {
104 @Override
105 protected Integer initialValue() {
106 return 0;
107 }
108 };
109
110 private EnumSet<MdcKey> mdcKeys;
111
112
113
114
115
116
117
118
119 public MdcInjectionFilter(EnumSet<MdcKey> keys) {
120 this.mdcKeys = keys.clone();
121 }
122
123
124
125
126
127
128
129
130 public MdcInjectionFilter(MdcKey... keys) {
131 Set<MdcKey> keySet = new HashSet<>(Arrays.asList(keys));
132 this.mdcKeys = EnumSet.copyOf(keySet);
133 }
134
135
136
137
138 public MdcInjectionFilter() {
139 this.mdcKeys = EnumSet.allOf(MdcKey.class);
140 }
141
142
143
144
145 @Override
146 protected void filter(IoFilterEvent event) throws Exception {
147
148
149 int currentCallDepth = callDepth.get();
150 callDepth.set(currentCallDepth + 1);
151 Map<String, String> context = getAndFillContext(event.getSession());
152
153 if (currentCallDepth == 0) {
154
155 for (Map.Entry<String, String> e : context.entrySet()) {
156 MDC.put(e.getKey(), e.getValue());
157 }
158 }
159
160 try {
161
162 event.fire();
163 } finally {
164 if (currentCallDepth == 0) {
165
166 for (String key : context.keySet()) {
167 MDC.remove(key);
168 }
169 callDepth.remove();
170 } else {
171 callDepth.set(currentCallDepth);
172 }
173 }
174 }
175
176 private Map<String, String> getAndFillContext(final IoSession session) {
177 Map<String, String> context = getContext(session);
178 if (context.isEmpty()) {
179 fillContext(session, context);
180 }
181 return context;
182 }
183
184 @SuppressWarnings("unchecked")
185 private static Map<String, String> getContext(final IoSession session) {
186 Map<String, String> context = (Map<String, String>) session.getAttribute(CONTEXT_KEY);
187
188 if (context == null) {
189 context = new ConcurrentHashMap<>();
190 session.setAttribute(CONTEXT_KEY, context);
191 }
192 return context;
193 }
194
195
196
197
198
199
200
201 protected void fillContext(final IoSession session, final Map<String, String> context) {
202 if (mdcKeys.contains(MdcKey.handlerClass)) {
203 context.put(MdcKey.handlerClass.name(), session.getHandler().getClass().getName());
204 }
205
206 if (mdcKeys.contains(MdcKey.remoteAddress)) {
207 context.put(MdcKey.remoteAddress.name(), session.getRemoteAddress().toString());
208 }
209
210 if (mdcKeys.contains(MdcKey.localAddress)) {
211 context.put(MdcKey.localAddress.name(), session.getLocalAddress().toString());
212 }
213
214 if (session.getTransportMetadata().getAddressType() == InetSocketAddress.class) {
215 InetSocketAddress remoteAddress = (InetSocketAddress) session.getRemoteAddress();
216 InetSocketAddress localAddress = (InetSocketAddress) session.getLocalAddress();
217
218 if (mdcKeys.contains(MdcKey.remoteIp)) {
219 context.put(MdcKey.remoteIp.name(), remoteAddress.getAddress().getHostAddress());
220 }
221
222 if (mdcKeys.contains(MdcKey.remotePort)) {
223 context.put(MdcKey.remotePort.name(), String.valueOf(remoteAddress.getPort()));
224 }
225
226 if (mdcKeys.contains(MdcKey.localIp)) {
227 context.put(MdcKey.localIp.name(), localAddress.getAddress().getHostAddress());
228 }
229
230 if (mdcKeys.contains(MdcKey.localPort)) {
231 context.put(MdcKey.localPort.name(), String.valueOf(localAddress.getPort()));
232 }
233 }
234 }
235
236
237
238
239
240
241
242
243 public static String getProperty(IoSession session, String key) {
244 if (key == null) {
245 throw new IllegalArgumentException("key should not be null");
246 }
247
248 Map<String, String> context = getContext(session);
249 String answer = context.get(key);
250
251 if (answer != null) {
252 return answer;
253 }
254
255 return MDC.get(key);
256 }
257
258
259
260
261
262
263
264
265 public static void setProperty(IoSession session, String key, String value) {
266 if (key == null) {
267 throw new IllegalArgumentException("key should not be null");
268 }
269
270 if (value == null) {
271 removeProperty(session, key);
272 }
273
274 Map<String, String> context = getContext(session);
275 context.put(key, value);
276 MDC.put(key, value);
277 }
278
279
280
281
282
283
284
285 public static void removeProperty(IoSession session, String key) {
286 if (key == null) {
287 throw new IllegalArgumentException("key should not be null");
288 }
289
290 Map<String, String> context = getContext(session);
291 context.remove(key);
292 MDC.remove(key);
293 }
294 }