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 }