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