1 /*
2 * Copyright (c) 2004-2008 QOS.ch
3 * All rights reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining
6 * a copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sublicense, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23 */
24 package org.slf4j.helpers;
25
26 import org.slf4j.spi.MDCAdapter;
27
28 import java.util.HashMap;
29 import java.util.Map;
30 import java.util.Set;
31
32 /**
33 * Basic MDC implementation, which can be used with logging systems that lack
34 * out-of-the-box MDC support.
35 *
36 * This code is largely based on logback's <a
37 * href="http://svn.qos.ch/viewvc/logback/trunk/logback-classic/src/main/java/org/slf4j/impl/LogbackMDCAdapter.java">
38 * LogbackMDCAdapter</a>.
39 *
40 * @author Ceki Gulcu
41 * @author Maarten Bosteels
42 *
43 * @since 1.5.0
44 */
45 public class BasicMDCAdapter implements MDCAdapter {
46
47 private InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
48
49 /**
50 * Put a context value (the <code>val</code> parameter) as identified with
51 * the <code>key</code> parameter into the current thread's context map.
52 * Note that contrary to log4j, the <code>val</code> parameter can be null.
53 *
54 * <p>
55 * If the current thread does not have a context map it is created as a side
56 * effect of this call.
57 *
58 * @throws IllegalArgumentException
59 * in case the "key" parameter is null
60 */
61 public void put(String key, String val) {
62 if (key == null) {
63 throw new IllegalArgumentException("key cannot be null");
64 }
65 HashMap map = (HashMap) inheritableThreadLocal.get();
66 if (map == null) {
67 map = new HashMap();
68 inheritableThreadLocal.set(map);
69 }
70 map.put(key, val);
71 }
72
73 /**
74 * Get the context identified by the <code>key</code> parameter.
75 */
76 public String get(String key) {
77 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
78 if ((hashMap != null) && (key != null)) {
79 return (String) hashMap.get(key);
80 } else {
81 return null;
82 }
83 }
84
85 /**
86 * Remove the the context identified by the <code>key</code> parameter.
87 */
88 public void remove(String key) {
89 HashMap map = (HashMap) inheritableThreadLocal.get();
90 if (map != null) {
91 map.remove(key);
92 }
93 }
94
95 /**
96 * Clear all entries in the MDC.
97 */
98 public void clear() {
99 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
100 if (hashMap != null) {
101 hashMap.clear();
102 inheritableThreadLocal.remove();
103 }
104 }
105
106 /**
107 * Returns the keys in the MDC as a {@link Set} of {@link String}s The
108 * returned value can be null.
109 *
110 * @return the keys in the MDC
111 */
112 public Set getKeys() {
113 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
114 if (hashMap != null) {
115 return hashMap.keySet();
116 } else {
117 return null;
118 }
119 }
120 /**
121 * Return a copy of the current thread's context map.
122 * Returned value may be null.
123 *
124 */
125 public Map getCopyOfContextMap() {
126 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
127 if (hashMap != null) {
128 return new HashMap(hashMap);
129 } else {
130 return null;
131 }
132 }
133
134 public void setContextMap(Map contextMap) {
135 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
136 if (hashMap != null) {
137 hashMap.clear();
138 hashMap.putAll(contextMap);
139 } else {
140 hashMap = new HashMap(contextMap);
141 inheritableThreadLocal.set(hashMap);
142 }
143 }
144
145 }