Skip to content

Commit 35adca4

Browse files
committed
implement putAll and putAllCloseable
Implements putAll and putAllCloseable described in SLF4J-387 Signed-off-by: Nikolas Grottendieck <[email protected]>
1 parent 7c62cf8 commit 35adca4

File tree

5 files changed

+375
-1
lines changed

5 files changed

+375
-1
lines changed

slf4j-api/src/main/java/org/slf4j/MDC.java

Lines changed: 73 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,9 @@
2525
package org.slf4j;
2626

2727
import java.io.Closeable;
28+
import java.util.HashSet;
2829
import java.util.Map;
30+
import java.util.Set;
2931

3032
import org.slf4j.helpers.BasicMDCAdapter;
3133
import org.slf4j.helpers.NOPMDCAdapter;
@@ -72,13 +74,25 @@ public class MDC {
7274
*/
7375
public static class MDCCloseable implements Closeable {
7476
private final String key;
77+
private final Set<String> keys;
7578

7679
private MDCCloseable(String key) {
7780
this.key = key;
81+
this.keys = null;
82+
}
83+
84+
private MDCCloseable(Set<String> keys) {
85+
this.key = null;
86+
this.keys = new HashSet<>(keys);
7887
}
7988

8089
public void close() {
81-
MDC.remove(this.key);
90+
if (this.key != null) {
91+
MDC.remove(this.key);
92+
}
93+
if (this.keys != null) {
94+
this.keys.forEach(MDC::remove);
95+
}
8296
}
8397
}
8498

@@ -121,6 +135,31 @@ public static void put(String key, String val) throws IllegalArgumentException {
121135
mdcAdapter.put(key, val);
122136
}
123137

138+
/**
139+
* Put a diagnostic context map (the <code>entries</code> parameter) as identified with each
140+
* <code>key</code> into the current thread's diagnostic context map. The
141+
* <code>entries</code> parameter and its <code>keys</code> cannot be null. The
142+
* <code>value</code> of each entry can be null only if the underlying implementation
143+
* supports it.
144+
*
145+
* <p>
146+
* This method delegates all work to the MDC of the underlying logging system.
147+
*
148+
* @param entries entries to put in the map
149+
*
150+
* @throws IllegalArgumentException
151+
* in case the "entries" parameter is null
152+
*/
153+
public static void putAll(Map<String, String> entries) throws IllegalArgumentException {
154+
if (entries == null) {
155+
throw new IllegalArgumentException("entries parameter cannot be null");
156+
}
157+
if (mdcAdapter == null) {
158+
throw new IllegalStateException("MDCAdapter cannot be null. See also " + NULL_MDCA_URL);
159+
}
160+
entries.forEach((k,v) -> mdcAdapter.put(k, v));
161+
}
162+
124163
/**
125164
* Put a diagnostic context value (the <code>val</code> parameter) as identified with the
126165
* <code>key</code> parameter into the current thread's diagnostic context map. The
@@ -154,6 +193,39 @@ public static MDCCloseable putCloseable(String key, String val) throws IllegalAr
154193
return new MDCCloseable(key);
155194
}
156195

196+
/**
197+
* Put a diagnostic context map (the <code>entries</code> parameter) as identified with each
198+
* <code>key</code> into the current thread's diagnostic context map. The
199+
* <code>entries</code> parameter and its <code>keys</code> cannot be null. The
200+
* <code>value</code> of each entry can be null only if the underlying implementation
201+
* supports it.
202+
*
203+
* <p>
204+
* This method delegates all work to the MDC of the underlying logging system.
205+
* <p>
206+
* This method returns a <code>Closeable</code> object which can remove all <code>keys</code>
207+
* that are part of the <code>entries</code> when <code>close</code> is called.
208+
*
209+
* <p>
210+
* Useful with Java 9 for example :
211+
* <code>
212+
* try(MDC.MDCCloseable closeable = MDC.putAllCloseable(Map.of(key1, value, key2, value2)) {
213+
* ....
214+
* }
215+
* </code>
216+
*
217+
* @param entries entries to put in the map
218+
* @return a <code>Closeable</code> who can remove all originally supplied <code>keys</code>
219+
* when <code>close</code> is called.
220+
*
221+
* @throws IllegalArgumentException
222+
* in case the "entries" parameter is null
223+
*/
224+
public static MDCCloseable putAllCloseable(Map<String, String> entries) throws IllegalArgumentException {
225+
MDC.putAll(entries);
226+
return new MDCCloseable(entries.keySet());
227+
}
228+
157229
/**
158230
* Get the diagnostic context identified by the <code>key</code> parameter. The
159231
* <code>key</code> parameter cannot be null.

slf4j-jdk14/src/test/java/org/slf4j/jul/InvocationTest.java

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@
3030
import org.junit.Test;
3131
import org.slf4j.*;
3232

33+
import java.util.HashMap;
34+
import java.util.Map;
3335
import java.util.logging.Handler;
3436
import java.util.logging.Level;
3537
import java.util.logging.LogRecord;
@@ -170,6 +172,127 @@ public void testMDC() {
170172
}
171173
}
172174

175+
@Test
176+
public void testMDCContextMapValues() {
177+
Map<String, String> map = new HashMap<>();
178+
map.put("ka", "va");
179+
map.put("kb", "vb");
180+
181+
MDC.put("k", "v");
182+
assertEquals("v", MDC.get("k"));
183+
MDC.setContextMap(map);
184+
assertNull(MDC.get("k"));
185+
assertEquals("va", MDC.get("ka"));
186+
assertEquals("vb", MDC.get("kb"));
187+
}
188+
189+
190+
@Test
191+
public void testMDCPutAll() {
192+
Map<String, String> values = new HashMap<>();
193+
values.put("k1", "v1");
194+
values.put("k2", "v2");
195+
196+
MDC.put("k", "v");
197+
MDC.putAll(values);
198+
199+
assertNotNull(MDC.get("k"));
200+
assertNotNull(MDC.get("k1"));
201+
assertNotNull(MDC.get("k2"));
202+
MDC.remove("k1");
203+
MDC.remove("k2");
204+
assertNotNull(MDC.get("k"));
205+
assertNull(MDC.get("k1"));
206+
assertNull(MDC.get("k2"));
207+
MDC.clear();
208+
}
209+
210+
@Test
211+
public void testMDCCloseable() {
212+
MDC.put("pre", "v");
213+
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("try-with", "v")) {
214+
assertNotNull(MDC.get("pre"));
215+
assertNotNull(MDC.get("try-with"));
216+
assertNull(MDC.get("post"));
217+
}
218+
MDC.put("post", "v");
219+
assertNotNull(MDC.get("pre"));
220+
assertNull(MDC.get("try-with"));
221+
assertNotNull(MDC.get("post"));
222+
MDC.clear();
223+
}
224+
225+
@Test
226+
public void testMDCCloseableOverwrites() {
227+
MDC.put("pre", "v");
228+
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("pre", "v2")) {
229+
assertNotNull(MDC.get("pre"));
230+
assertEquals("v2", MDC.get("pre"));
231+
assertNull(MDC.get("post"));
232+
}
233+
MDC.put("post", "v");
234+
assertNull(MDC.get("pre"));
235+
assertNotNull(MDC.get("post"));
236+
MDC.clear();
237+
}
238+
239+
@Test
240+
public void testMDCCloseablePutAll() {
241+
Map<String, String> values = new HashMap<>();
242+
values.put("try-with", "v");
243+
244+
MDC.put("pre", "v");
245+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
246+
assertNotNull(MDC.get("pre"));
247+
assertNotNull(MDC.get("try-with"));
248+
assertNull(MDC.get("post"));
249+
}
250+
MDC.put("post", "v");
251+
assertNotNull(MDC.get("pre"));
252+
assertNull(MDC.get("try-with"));
253+
assertNotNull(MDC.get("post"));
254+
MDC.clear();
255+
}
256+
257+
@Test
258+
public void testMDCCloseablePutAllOverwrites() {
259+
Map<String, String> values = new HashMap<>();
260+
values.put("pre", "v2");
261+
values.put("try-with", "v");
262+
263+
MDC.put("pre", "v");
264+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
265+
assertNotNull(MDC.get("pre"));
266+
assertEquals("v2", MDC.get("pre"));
267+
assertNotNull(MDC.get("try-with"));
268+
assertNull(MDC.get("post"));
269+
}
270+
MDC.put("post", "v");
271+
assertNull(MDC.get("pre"));
272+
assertNull(MDC.get("try-with"));
273+
assertNotNull(MDC.get("post"));
274+
MDC.clear();
275+
}
276+
277+
@Test
278+
public void testMDCCloseablePutAllImmutable() {
279+
Map<String, String> values = new HashMap<>();
280+
values.put("try-with", "v");
281+
282+
MDC.put("pre", "v");
283+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
284+
values.remove("try-with");
285+
assertNotNull(MDC.get("pre"));
286+
assertNotNull(MDC.get("try-with"));
287+
assertNull(MDC.get("post"));
288+
}
289+
MDC.put("post", "v");
290+
assertNotNull(MDC.get("pre"));
291+
assertNull(MDC.get("try-with"));
292+
assertNotNull(MDC.get("post"));
293+
MDC.clear();
294+
}
295+
173296
private void assertLogMessage(String expected, int index) {
174297
LogRecord logRecord = listHandler.recordList.get(index);
175298
Assert.assertNotNull(logRecord);

slf4j-log4j12/src/test/java/org/slf4j/log4j12/InvocationTest.java

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,112 @@ public void testMDCContextMapValues() {
188188
assertEquals("vb", MDC.get("kb"));
189189
}
190190

191+
@Test
192+
public void testMDCPutAll() {
193+
Map<String, String> values = new HashMap<>();
194+
values.put("k1", "v1");
195+
values.put("k2", "v2");
196+
197+
MDC.put("k", "v");
198+
MDC.putAll(values);
199+
200+
assertNotNull(MDC.get("k"));
201+
assertNotNull(MDC.get("k1"));
202+
assertNotNull(MDC.get("k2"));
203+
MDC.remove("k1");
204+
MDC.remove("k2");
205+
assertNotNull(MDC.get("k"));
206+
assertNull(MDC.get("k1"));
207+
assertNull(MDC.get("k2"));
208+
MDC.clear();
209+
}
210+
211+
@Test
212+
public void testMDCCloseable() {
213+
MDC.put("pre", "v");
214+
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("try-with", "v")) {
215+
assertNotNull(MDC.get("pre"));
216+
assertNotNull(MDC.get("try-with"));
217+
assertNull(MDC.get("post"));
218+
}
219+
MDC.put("post", "v");
220+
assertNotNull(MDC.get("pre"));
221+
assertNull(MDC.get("try-with"));
222+
assertNotNull(MDC.get("post"));
223+
MDC.clear();
224+
}
225+
226+
@Test
227+
public void testMDCCloseableOverwrites() {
228+
MDC.put("pre", "v");
229+
try(MDC.MDCCloseable mdcCloseable = MDC.putCloseable("pre", "v2")) {
230+
assertNotNull(MDC.get("pre"));
231+
assertEquals("v2", MDC.get("pre"));
232+
assertNull(MDC.get("post"));
233+
}
234+
MDC.put("post", "v");
235+
assertNull(MDC.get("pre"));
236+
assertNotNull(MDC.get("post"));
237+
MDC.clear();
238+
}
239+
240+
@Test
241+
public void testMDCCloseablePutAllImmutable() {
242+
Map<String, String> values = new HashMap<>();
243+
values.put("try-with", "v");
244+
245+
MDC.put("pre", "v");
246+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
247+
values.remove("try-with");
248+
assertNotNull(MDC.get("pre"));
249+
assertNotNull(MDC.get("try-with"));
250+
assertNull(MDC.get("post"));
251+
}
252+
MDC.put("post", "v");
253+
assertNotNull(MDC.get("pre"));
254+
assertNull(MDC.get("try-with"));
255+
assertNotNull(MDC.get("post"));
256+
MDC.clear();
257+
}
258+
259+
@Test
260+
public void testMDCCloseablePutAll() {
261+
Map<String, String> values = new HashMap<>();
262+
values.put("try-with", "v");
263+
264+
MDC.put("pre", "v");
265+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
266+
assertNotNull(MDC.get("pre"));
267+
assertNotNull(MDC.get("try-with"));
268+
assertNull(MDC.get("post"));
269+
}
270+
MDC.put("post", "v");
271+
assertNotNull(MDC.get("pre"));
272+
assertNull(MDC.get("try-with"));
273+
assertNotNull(MDC.get("post"));
274+
MDC.clear();
275+
}
276+
277+
@Test
278+
public void testMDCCloseablePutAllOverwrites() {
279+
Map<String, String> values = new HashMap<>();
280+
values.put("pre", "v2");
281+
values.put("try-with", "v");
282+
283+
MDC.put("pre", "v");
284+
try(MDC.MDCCloseable mdcCloseable = MDC.putAllCloseable(values)) {
285+
assertNotNull(MDC.get("pre"));
286+
assertEquals("v2", MDC.get("pre"));
287+
assertNotNull(MDC.get("try-with"));
288+
assertNull(MDC.get("post"));
289+
}
290+
MDC.put("post", "v");
291+
assertNull(MDC.get("pre"));
292+
assertNull(MDC.get("try-with"));
293+
assertNotNull(MDC.get("post"));
294+
MDC.clear();
295+
}
296+
191297
@Test
192298
public void testCallerInfo() {
193299
Logger logger = LoggerFactory.getLogger("testMarker");

0 commit comments

Comments
 (0)