BasicMDCAdapter xref

View Javadoc

    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.helpers;
    26
    27  import org.slf4j.spi.MDCAdapter;
    28
    29  import java.util.*;
    30  import java.util.Map;
    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 was initially inspired by  logback's LogbackMDCAdapter. However,
    37   * LogbackMDCAdapter has evolved and is now considerably more sophisticated.
    38   *
    39   * @author Ceki Gulcu
    40   * @author Maarten Bosteels
    41   *
    42   * @since 1.5.0
    43   */
    44  public class BasicMDCAdapter implements MDCAdapter {
    45
    46    private InheritableThreadLocal inheritableThreadLocal = new InheritableThreadLocal();
    47
    48    static boolean isJDK14() {
    49      try {
    50        String javaVersion = System.getProperty("java.version");
    51        return javaVersion.startsWith("1.4");
    52      } catch(SecurityException se) {
    53        // punt and assume JDK 1.5 or later
    54        return false;
    55      }
    56    }
    57
    58    static boolean IS_JDK14 = isJDK14();
    59
    60
    61    /**
    62     * Put a context value (the <code>val</code> parameter) as identified with
    63     * the <code>key</code> parameter into the current thread's context map.
    64     * Note that contrary to log4j, the <code>val</code> parameter can be null.
    65     *
    66     * <p>
    67     * If the current thread does not have a context map it is created as a side
    68     * effect of this call.
    69     *
    70     * @throws IllegalArgumentException
    71     *                 in case the "key" parameter is null
    72     */
    73    public void put(String key, String val) {
    74      if (key == null) {
    75        throw new IllegalArgumentException("key cannot be null");
    76      }
    77      Map map = (Map) inheritableThreadLocal.get();
    78      if (map == null) {
    79        map = Collections.synchronizedMap(new HashMap());
    80        inheritableThreadLocal.set(map);
    81      }
    82      map.put(key, val);
    83    }
    84
    85    /**
    86     * Get the context identified by the <code>key</code> parameter.
    87     */
    88    public String get(String key) {
    89      Map Map = (Map) inheritableThreadLocal.get();
    90      if ((Map != null) && (key != null)) {
    91        return (String) Map.get(key);
    92      } else {
    93        return null;
    94      }
    95    }
    96
    97    /**
    98     * Remove the the context identified by the <code>key</code> parameter.
    99     */
    100   public void remove(String key) {
    101     Map map = (Map) inheritableThreadLocal.get();
    102     if (map != null) {
    103       map.remove(key);
    104     }
    105   }
    106
    107   /**
    108    * Clear all entries in the MDC.
    109    */
    110   public void clear() {
    111     Map map = (Map) inheritableThreadLocal.get();
    112     if (map != null) {
    113       map.clear();
    114       // the InheritableThreadLocal.remove method was introduced in JDK 1.5
    115       // Thus, invoking clear() on previous JDK 1.4 will fail
    116       if(isJDK14()) {
    117         inheritableThreadLocal.set(null);
    118       }  else {
    119         inheritableThreadLocal.remove();
    120       }
    121     }
    122   }
    123
    124   /**
    125    * Returns the keys in the MDC as a {@link Set} of {@link String}s The
    126    * returned value can be null.
    127    *
    128    * @return the keys in the MDC
    129    */
    130   public Set getKeys() {
    131     Map map = (Map) inheritableThreadLocal.get();
    132     if (map != null) {
    133       return map.keySet();
    134     } else {
    135       return null;
    136     }
    137   }
    138   /**
    139    * Return a copy of the current thread's context map.
    140    * Returned value may be null.
    141    *
    142    */
    143   public Map getCopyOfContextMap() {
    144     Map oldMap = (Map) inheritableThreadLocal.get();
    145     if (oldMap != null) {
    146        Map newMap = Collections.synchronizedMap(new HashMap());
    147        synchronized (oldMap) {
    148          newMap.putAll(oldMap);
    149        }
    150        return  newMap;
    151     } else {
    152       return null;
    153     }
    154   }
    155
    156   public void setContextMap(Map contextMap) {
    157     Map map = Collections.synchronizedMap(new HashMap(contextMap));
    158     inheritableThreadLocal.set(map);
    159   }
    160
    161 }