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   * @author Lukasz Cwik
    42   *
    43   * @since 1.5.0
    44   */
    45  public class BasicMDCAdapter implements MDCAdapter {
    46
    47      private InheritableThreadLocal<Map<String, String>> inheritableThreadLocal = new InheritableThreadLocal<Map<String, String>>() {
    48          @Override
    49          protected Map<String, String> childValue(Map<String, String> parentValue) {
    50              if (parentValue == null) {
    51                  return null;
    52              }
    53              return new HashMap<String, String>(parentValue);
    54          }
    55      };
    56
    57      /**
    58       * Put a context value (the <code>val</code> parameter) as identified with
    59       * the <code>key</code> parameter into the current thread's context map.
    60       * Note that contrary to log4j, the <code>val</code> parameter can be null.
    61       *
    62       * <p>
    63       * If the current thread does not have a context map it is created as a side
    64       * effect of this call.
    65       *
    66       * @throws IllegalArgumentException
    67       *                 in case the "key" parameter is null
    68       */
    69      public void put(String key, String val) {
    70          if (key == null) {
    71              throw new IllegalArgumentException("key cannot be null");
    72          }
    73          Map<String, String> map = inheritableThreadLocal.get();
    74          if (map == null) {
    75              map = new HashMap<String, String>();
    76              inheritableThreadLocal.set(map);
    77          }
    78          map.put(key, val);
    79      }
    80
    81      /**
    82       * Get the context identified by the <code>key</code> parameter.
    83       */
    84      public String get(String key) {
    85          Map<String, String> map = inheritableThreadLocal.get();
    86          if ((map != null) && (key != null)) {
    87              return map.get(key);
    88          } else {
    89              return null;
    90          }
    91      }
    92
    93      /**
    94       * Remove the the context identified by the <code>key</code> parameter.
    95       */
    96      public void remove(String key) {
    97          Map<String, String> map = inheritableThreadLocal.get();
    98          if (map != null) {
    99              map.remove(key);
    100         }
    101     }
    102
    103     /**
    104      * Clear all entries in the MDC.
    105      */
    106     public void clear() {
    107         Map<String, String> map = inheritableThreadLocal.get();
    108         if (map != null) {
    109             map.clear();
    110             inheritableThreadLocal.remove();
    111         }
    112     }
    113
    114     /**
    115      * Returns the keys in the MDC as a {@link Set} of {@link String}s The
    116      * returned value can be null.
    117      *
    118      * @return the keys in the MDC
    119      */
    120     public Set<String> getKeys() {
    121         Map<String, String> map = inheritableThreadLocal.get();
    122         if (map != null) {
    123             return map.keySet();
    124         } else {
    125             return null;
    126         }
    127     }
    128
    129     /**
    130      * Return a copy of the current thread's context map.
    131      * Returned value may be null.
    132      *
    133      */
    134     public Map<String, String> getCopyOfContextMap() {
    135         Map<String, String> oldMap = inheritableThreadLocal.get();
    136         if (oldMap != null) {
    137             return new HashMap<String, String>(oldMap);
    138         } else {
    139             return null;
    140         }
    141     }
    142
    143     public void setContextMap(Map<String, String> contextMap) {
    144         inheritableThreadLocal.set(new HashMap<String, String>(contextMap));
    145     }
    146 }