1 /*
2 * Copyright (c) 2004-2007 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
25 package org.slf4j;
26
27 import java.util.Map;
28
29 import org.slf4j.helpers.BasicMDCAdapter;
30 import org.slf4j.helpers.Util;
31 import org.slf4j.impl.StaticMDCBinder;
32 import org.slf4j.spi.MDCAdapter;
33
34 /**
35 * This class hides and serves as a substitute for the underlying logging
36 * system's MDC implementation.
37 *
38 * <p>
39 * If the underlying logging system offers MDC functionality, then SLF4J's MDC,
40 * i.e. this class, will delegate to the underlying system's MDC. Note that at
41 * this time, only two logging systems, namely log4j and logback, offer MDC
42 * functionality. If the underlying system does not support MDC, e.g. java.util.logging,
43 * then SLF4J will use a {@link BasicMDCAdapter}.
44 *
45 * <p>
46 * Thus, as a SLF4J user, you can take advantage of MDC in the presence of log4j
47 * logback, or java.util.logging, but without forcing these systems as dependencies
48 * upon your users.
49 *
50 * <p>
51 * For more information on MDC please see the <a
52 * href="http://logback.qos.ch/manual/mdc.html">chapter on MDC</a> in the
53 * logback manual.
54 *
55 * <p>
56 * Please note that all methods in this class are static.
57 *
58 * @author Ceki Gülcü
59 * @since 1.4.1
60 */
61 public class MDC {
62
63 static final String NULL_MDCA_URL = "http://www.slf4j.org/codes.html#null_MDCA";
64 static final String NO_STATIC_MDC_BINDER_URL = "http://www.slf4j.org/codes.html#no_static_mdc_binder";
65 static MDCAdapter mdcAdapter;
66
67 private MDC() {
68 }
69
70 static {
71 try {
72 mdcAdapter = StaticMDCBinder.SINGLETON.getMDCA();
73 } catch (NoClassDefFoundError ncde) {
74 String msg = ncde.getMessage();
75 if (msg != null && msg.indexOf("org/slf4j/impl/StaticMDCBinder") != -1) {
76 Util
77 .reportFailure("Failed to load class \"org.slf4j.impl.StaticMDCBinder\".");
78 Util.reportFailure("See " + NO_STATIC_MDC_BINDER_URL
79 + " for further details.");
80
81 }
82 throw ncde;
83 } catch (Exception e) {
84 // we should never get here
85 Util.reportFailure("Could not bind with an instance of class ["
86 + StaticMDCBinder.SINGLETON.getMDCAdapterClassStr() + "]", e);
87 }
88 }
89
90 /**
91 * Put a context value (the <code>val</code> parameter) as identified with
92 * the <code>key</code> parameter into the current thread's context map.
93 * The <code>key</code> parameter cannot be null. The <code>val</code> parameter
94 * can be null only if the underlying implementation supports it.
95 *
96 * <p>
97 * This method delegates all work to the MDC of the underlying logging system.
98 *
99 * @throws IllegalArgumentException in case the "key" parameter is null
100 */
101 public static void put(String key, String val) throws IllegalArgumentException {
102 if (key == null) {
103 throw new IllegalArgumentException("key parameter cannot be null");
104 }
105 if (mdcAdapter == null) {
106 throw new IllegalStateException("MDCAdapter cannot be null. See also "
107 + NULL_MDCA_URL);
108 }
109 mdcAdapter.put(key, val);
110 }
111
112 /**
113 * Get the context identified by the <code>key</code> parameter. The
114 * <code>key</code> parameter cannot be null.
115 *
116 * <p>This method delegates all work to the MDC of the underlying logging system.
117 *
118 * @return the string value identified by the <code>key</code> parameter.
119 * @throws IllegalArgumentException in case the "key" parameter is null
120 */
121 public static String get(String key) throws IllegalArgumentException {
122 if (key == null) {
123 throw new IllegalArgumentException("key parameter cannot be null");
124 }
125
126 if (mdcAdapter == null) {
127 throw new IllegalStateException("MDCAdapter cannot be null. See also "
128 + NULL_MDCA_URL);
129 }
130 return mdcAdapter.get(key);
131 }
132
133 /**
134 * Remove the the context identified by the <code>key</code> parameter using
135 * the underlying system's MDC implementation. The <code>key</code> parameter
136 * cannot be null. This method does nothing if there is no previous value
137 * associated with <code>key</code>.
138 *
139 * @throws IllegalArgumentException in case the "key" parameter is null
140 */
141 public static void remove(String key) throws IllegalArgumentException {
142 if (key == null) {
143 throw new IllegalArgumentException("key parameter cannot be null");
144 }
145
146 if (mdcAdapter == null) {
147 throw new IllegalStateException("MDCAdapter cannot be null. See also "
148 + NULL_MDCA_URL);
149 }
150 mdcAdapter.remove(key);
151 }
152
153 /**
154 * Clear all entries in the MDC of the underlying implementation.
155 */
156 public static void clear() {
157 if (mdcAdapter == null) {
158 throw new IllegalStateException("MDCAdapter cannot be null. See also "
159 + NULL_MDCA_URL);
160 }
161 mdcAdapter.clear();
162 }
163
164 /**
165 * Return a copy of the current thread's context map, with keys and
166 * values of type String. Returned value may be null.
167 *
168 * @return A copy of the current thread's context map. May be null.
169 * @since 1.5.1
170 */
171 public static Map getCopyOfContextMap() {
172 if (mdcAdapter == null) {
173 throw new IllegalStateException("MDCAdapter cannot be null. See also "
174 + NULL_MDCA_URL);
175 }
176 return mdcAdapter.getCopyOfContextMap();
177 }
178
179 /**
180 * Set the current thread's context map by first clearing any existing
181 * map and then copying the map passed as parameter. The context map passed
182 * as parameter must only contain keys and values of type String.
183 *
184 * @param contextMap must contain only keys and values of type String
185 * @since 1.5.1
186 */
187 public static void setContextMap(Map contextMap) {
188 if (mdcAdapter == null) {
189 throw new IllegalStateException("MDCAdapter cannot be null. See also "
190 + NULL_MDCA_URL);
191 }
192 mdcAdapter.setContextMap(contextMap);
193 }
194
195
196 /**
197 * Returns the MDCAdapter instance currently in use.
198 *
199 * @return the MDcAdapter instance currently in use.
200 * @since 1.4.2
201 */
202 public static MDCAdapter getMDCAdapter() {
203 return mdcAdapter;
204 }
205
206
207 }