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