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 // the InheritableThreadLocal.remove method was introduced in JDK 1.5
103 // Thus, invoking clear() on previous JDK's will fail
104 inheritableThreadLocal.remove();
105 }
106 }
107
108 /**
109 * Returns the keys in the MDC as a {@link Set} of {@link String}s The
110 * returned value can be null.
111 *
112 * @return the keys in the MDC
113 */
114 public Set getKeys() {
115 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
116 if (hashMap != null) {
117 return hashMap.keySet();
118 } else {
119 return null;
120 }
121 }
122 /**
123 * Return a copy of the current thread's context map.
124 * Returned value may be null.
125 *
126 */
127 public Map getCopyOfContextMap() {
128 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
129 if (hashMap != null) {
130 return new HashMap(hashMap);
131 } else {
132 return null;
133 }
134 }
135
136 public void setContextMap(Map contextMap) {
137 HashMap hashMap = (HashMap) inheritableThreadLocal.get();
138 if (hashMap != null) {
139 hashMap.clear();
140 hashMap.putAll(contextMap);
141 } else {
142 hashMap = new HashMap(contextMap);
143 inheritableThreadLocal.set(hashMap);
144 }
145 }
146
147 }