MDC.java
  1  /*
  2   * Copyright 1999-2005 The Apache Software Foundation.
  3   * 
  4   * Licensed under the Apache License, Version 2.0 (the "License");
  5   * you may not use this file except in compliance with the License.
  6   * You may obtain a copy of the License at
  7   * 
  8   *      http://www.apache.org/licenses/LICENSE-2.0
  9   * 
 10   * Unless required by applicable law or agreed to in writing, software
 11   * distributed under the License is distributed on an "AS IS" BASIS,
 12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 13   * See the License for the specific language governing permissions and
 14   * limitations under the License.
 15   */
 16  
 17  package org.apache.log4j;
 18  
 19  import java.util.Hashtable;
 20  import org.apache.log4j.helpers.Loader;
 21  import org.apache.log4j.helpers.ThreadLocalMap;
 22  
 23  /**
 24     The MDC class is similar to the {@link NDC} class except that it is
 25     based on a map instead of a stack. It provides <em>mapped
 26     diagnostic contexts</em>. A <em>Mapped Diagnostic Context</em>, or
 27     MDC in short, is an instrument for distinguishing interleaved log
 28     output from different sources. Log output is typically interleaved
 29     when a server handles multiple clients near-simultaneously.
 30  
 31     <p><b><em>The MDC is managed on a per thread basis</em></b>. A
 32     child thread automatically inherits a <em>copy</em> of the mapped
 33     diagnostic context of its parent.
 34    
 35     <p>The MDC class requires JDK 1.2 or above. Under JDK 1.1 the MDC
 36     will always return empty values but otherwise will not affect or
 37     harm your application.
 38     
 39     @since 1.2
 40  
 41     @author Ceki G&uuml;lc&uuml; */
 42  public class MDC {
 43    
 44    final static MDC mdc = new MDC();
 45    
 46    static final int HT_SIZE = 7;
 47  
 48    boolean java1;
 49    
 50    Object tlm;
 51    
 52    private
 53    MDC() {
 54      java1 = Loader.isJava1();
 55      if(!java1) {
 56        tlm = new ThreadLocalMap();
 57      }
 58    }
 59  
 60    /**
 61       Put a context value (the <code>o</code> parameter) as identified
 62       with the <code>key</code> parameter into the current thread's
 63       context map.
 64  
 65       <p>If the current thread does not have a context map it is
 66       created as a side effect.
 67      
 68     */
 69    static
 70    public
 71    void put(String key, Object o) {
 72      mdc.put0(key, o);
 73    }
 74    
 75    /**
 76       Get the context identified by the <code>key</code> parameter.
 77  
 78       <p>This method has no side effects.
 79     */
 80    static 
 81    public
 82    Object get(String key) {
 83      return mdc.get0(key);
 84    }
 85  
 86    /**
 87       Remove the the context identified by the <code>key</code>
 88       parameter.
 89  
 90    */
 91    static 
 92    public
 93    void remove(String key) {
 94      mdc.remove0(key);
 95    }
 96  
 97  
 98    /**
 99     * Get the current thread's MDC as a hashtable. This method is
100     * intended to be used internally.  
101     * */
102    public static Hashtable getContext() {
103      return mdc.getContext0();
104    }
105  
106  
107    private
108    void put0(String key, Object o) {
109      if(java1) {
110        return;
111      } else {
112        Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
113        if(ht == null) {
114          ht = new Hashtable(HT_SIZE);
115          ((ThreadLocalMap)tlm).set(ht);
116        }    
117        ht.put(key, o);
118      }
119    }
120    
121    private
122    Object get0(String key) {
123      if(java1) {
124        return null;
125      } else {       
126        Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
127        if(ht != null && key != null) {
128          return ht.get(key);
129        } else {
130          return null;
131        }
132      }
133    }
134  
135    private
136    void remove0(String key) {
137      if(!java1) {
138        Hashtable ht = (Hashtable) ((ThreadLocalMap)tlm).get();
139        if(ht != null) {
140          ht.remove(key);
141        } 
142      }
143    }
144  
145  
146    private
147    Hashtable getContext0() {
148       if(java1) {
149        return null;
150      } else {       
151        return (Hashtable) ((ThreadLocalMap)tlm).get();
152      }
153    }
154  }