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