You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by ma...@apache.org on 2022/11/06 20:37:30 UTC
[logging-log4j2] 01/02: LOG4J2-3626 - Flatten ThreadContextMap with default methods
This is an automated email from the ASF dual-hosted git repository.
mattsicker pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/logging-log4j2.git
commit e96557e29843b2b3a4237db5ebb248f35a14bd81
Author: Matt Sicker <ma...@apache.org>
AuthorDate: Sun Nov 6 14:36:07 2022 -0600
LOG4J2-3626 - Flatten ThreadContextMap with default methods
Signed-off-by: Matt Sicker <ma...@apache.org>
---
.../org/apache/logging/log4j/ThreadContext.java | 22 +-----
.../log4j/spi/CleanableThreadContextMap.java | 18 +----
.../CopyOnWriteSortedArrayThreadContextMap.java | 4 +-
.../logging/log4j/spi/DefaultThreadContextMap.java | 4 +-
.../GarbageFreeSortedArrayThreadContextMap.java | 4 +-
.../logging/log4j/spi/NoOpThreadContextMap.java | 21 +++++
.../logging/log4j/spi/ObjectThreadContextMap.java | 36 +--------
.../apache/logging/log4j/spi/ThreadContextMap.java | 91 +++++++++++++++++++++-
.../logging/log4j/spi/ThreadContextMap2.java | 32 +-------
.../apache/logging/log4j/util/PropertiesUtil.java | 2 +-
.../logging/log4j/perf/nogc/OpenHashStringMap.java | 19 +++--
.../org/apache/logging/slf4j/MDCContextMap.java | 10 +--
src/changes/changes.xml | 3 +
13 files changed, 149 insertions(+), 117 deletions(-)
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java b/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
index c61ca0701c..75f4d932c5 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
@@ -18,13 +18,11 @@
package org.apache.logging.log4j;
import org.apache.logging.log4j.message.ParameterizedMessage;
-import org.apache.logging.log4j.spi.CleanableThreadContextMap;
import org.apache.logging.log4j.spi.DefaultThreadContextMap;
import org.apache.logging.log4j.spi.DefaultThreadContextStack;
import org.apache.logging.log4j.spi.NoOpThreadContextMap;
import org.apache.logging.log4j.spi.ReadOnlyThreadContextMap;
import org.apache.logging.log4j.spi.ThreadContextMap;
-import org.apache.logging.log4j.spi.ThreadContextMap2;
import org.apache.logging.log4j.spi.ThreadContextMapFactory;
import org.apache.logging.log4j.spi.ThreadContextStack;
import org.apache.logging.log4j.util.PropertiesUtil;
@@ -274,15 +272,7 @@ public final class ThreadContext {
* @since 2.7
*/
public static void putAll(final Map<String, String> m) {
- if (contextMap instanceof ThreadContextMap2) {
- ((ThreadContextMap2) contextMap).putAll(m);
- } else if (contextMap instanceof DefaultThreadContextMap) {
- ((DefaultThreadContextMap) contextMap).putAll(m);
- } else {
- for (final Map.Entry<String, String> entry: m.entrySet()) {
- contextMap.put(entry.getKey(), entry.getValue());
- }
- }
+ contextMap.putAll(m);
}
/**
@@ -316,15 +306,7 @@ public final class ThreadContext {
* @since 2.8
*/
public static void removeAll(final Iterable<String> keys) {
- if (contextMap instanceof CleanableThreadContextMap) {
- ((CleanableThreadContextMap) contextMap).removeAll(keys);
- } else if (contextMap instanceof DefaultThreadContextMap) {
- ((DefaultThreadContextMap) contextMap).removeAll(keys);
- } else {
- for (final String key : keys) {
- contextMap.remove(key);
- }
- }
+ contextMap.removeAll(keys);
}
/**
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CleanableThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CleanableThreadContextMap.java
index f32a06e6e0..9f0dd3e7df 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CleanableThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CleanableThreadContextMap.java
@@ -17,23 +17,13 @@
package org.apache.logging.log4j.spi;
/**
- * Extension service provider interface to implement additional custom MDC behavior for
- * {@link org.apache.logging.log4j.ThreadContext}.
+ * Legacy interface for backward compatibility with extensions to ThreadContextMap.
+ * These methods have since been moved to default methods on ThreadContextMap.
*
* @see ThreadContextMap
* @since 2.8
+ * @deprecated use {@link ThreadContextMap} directly
*/
+@Deprecated(since = "3.0.0")
public interface CleanableThreadContextMap extends ThreadContextMap2 {
-
- /**
- * Removes all given context map keys from the current thread's context map.
- *
- * <p>If the current thread does not have a context map it is
- * created as a side effect.</p>
-
- * @param keys The keys.
- * @since 2.8
- */
- void removeAll(final Iterable<String> keys);
-
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
index ea0a0fd5e4..27e29cfb39 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContextMap.java
@@ -18,11 +18,11 @@ package org.apache.logging.log4j.spi;
import org.apache.logging.log4j.util.LazyBoolean;
import org.apache.logging.log4j.util.LazyInt;
+import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.SortedArrayStringMap;
import org.apache.logging.log4j.util.StringMap;
-import org.apache.logging.log4j.util.PropertiesUtil;
import java.util.Collections;
import java.util.HashMap;
@@ -38,7 +38,7 @@ import java.util.Objects;
*
* @since 2.7
*/
-class CopyOnWriteSortedArrayThreadContextMap implements ReadOnlyThreadContextMap, ObjectThreadContextMap, CopyOnWrite {
+class CopyOnWriteSortedArrayThreadContextMap implements ReadOnlyThreadContextMap, ThreadContextMap, CopyOnWrite {
/**
* Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/DefaultThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/DefaultThreadContextMap.java
index 2efec39f7b..665480ee2e 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/DefaultThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/DefaultThreadContextMap.java
@@ -18,10 +18,10 @@ package org.apache.logging.log4j.spi;
import org.apache.logging.log4j.util.BiConsumer;
import org.apache.logging.log4j.util.LazyBoolean;
+import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.TriConsumer;
-import org.apache.logging.log4j.util.PropertiesUtil;
import java.util.Collections;
import java.util.HashMap;
@@ -90,6 +90,7 @@ public class DefaultThreadContextMap implements ThreadContextMap, ReadOnlyString
localMap.set(Collections.unmodifiableMap(map));
}
+ @Override
public void putAll(final Map<String, String> m) {
if (!useMap) {
return;
@@ -116,6 +117,7 @@ public class DefaultThreadContextMap implements ThreadContextMap, ReadOnlyString
}
}
+ @Override
public void removeAll(final Iterable<String> keys) {
final Map<String, String> map = localMap.get();
if (map != null) {
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java
index 08f5bb9924..f46c014f7e 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/GarbageFreeSortedArrayThreadContextMap.java
@@ -18,11 +18,11 @@ package org.apache.logging.log4j.spi;
import org.apache.logging.log4j.util.LazyBoolean;
import org.apache.logging.log4j.util.LazyInt;
+import org.apache.logging.log4j.util.PropertiesUtil;
import org.apache.logging.log4j.util.PropertyEnvironment;
import org.apache.logging.log4j.util.ReadOnlyStringMap;
import org.apache.logging.log4j.util.SortedArrayStringMap;
import org.apache.logging.log4j.util.StringMap;
-import org.apache.logging.log4j.util.PropertiesUtil;
import java.util.Collections;
import java.util.HashMap;
@@ -38,7 +38,7 @@ import java.util.Objects;
* </p>
* @since 2.7
*/
-class GarbageFreeSortedArrayThreadContextMap implements ReadOnlyThreadContextMap, ObjectThreadContextMap {
+class GarbageFreeSortedArrayThreadContextMap implements ReadOnlyThreadContextMap, ThreadContextMap {
/**
* Property name ({@value} ) for selecting {@code InheritableThreadLocal} (value "true") or plain
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/NoOpThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/NoOpThreadContextMap.java
index 2f858fce32..f46ffec06b 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/NoOpThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/NoOpThreadContextMap.java
@@ -62,4 +62,25 @@ public class NoOpThreadContextMap implements ThreadContextMap {
@Override
public void remove(final String key) {
}
+
+ @Override
+ public void putAll(final Map<String, String> map) {
+ }
+
+ @Override
+ public void removeAll(final Iterable<String> keys) {
+ }
+
+ @Override
+ public <V> V getValue(final String key) {
+ return null;
+ }
+
+ @Override
+ public <V> void putValue(final String key, final V value) {
+ }
+
+ @Override
+ public <V> void putAllValues(final Map<String, V> values) {
+ }
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ObjectThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ObjectThreadContextMap.java
index c4bc014d3a..aa07de1baf 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ObjectThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ObjectThreadContextMap.java
@@ -16,42 +16,14 @@
*/
package org.apache.logging.log4j.spi;
-import java.util.Map;
-
/**
- * Extension service provider interface to allow putting Object values in the
- * {@link org.apache.logging.log4j.ThreadContext}.
+ * Legacy interface for backward compatibility with extensions to ThreadContextMap.
+ * These methods have since been moved to default methods on ThreadContextMap.
*
* @see ThreadContextMap
* @since 2.8
+ * @deprecated use {@link ThreadContextMap} directly
*/
+@Deprecated(since = "3.0.0")
public interface ObjectThreadContextMap extends CleanableThreadContextMap {
-
- /**
- * Returns the Object value for the specified key, or {@code null} if the specified key does not exist in this
- * collection.
- *
- * @param key the key whose value to return
- * @param <V> The type of the returned value.
- * @return the value for the specified key or {@code null}
- */
- <V> V getValue(String key);
-
- /**
- * Puts the specified key-value pair into the collection.
- *
- * @param key the key to add or remove. Keys may be {@code null}.
- * @param <V> The type of the stored and returned value.
- * @param value the value to add. Values may be {@code null}.
- */
- <V> void putValue(String key, V value);
-
- /**
- * Puts all given key-value pairs into the collection.
- *
- * @param values the map of key-value pairs to add
- * @param <V> The type of the value being added.
- */
- <V> void putAllValues(Map<String, V> values);
-
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap.java
index 5040bb928e..af357b20c6 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap.java
@@ -16,9 +16,12 @@
*/
package org.apache.logging.log4j.spi;
-import java.util.Map;
-
import org.apache.logging.log4j.ThreadContext;
+import org.apache.logging.log4j.util.Cast;
+import org.apache.logging.log4j.util.SortedArrayStringMap;
+import org.apache.logging.log4j.util.StringMap;
+
+import java.util.Map;
/**
* Service provider interface to implement custom MDC behavior for {@link org.apache.logging.log4j.ThreadContext}.
@@ -26,6 +29,9 @@ import org.apache.logging.log4j.ThreadContext;
* Since 2.8, {@code ThreadContextMap} implementations that implement the {@link ReadOnlyThreadContextMap} interface
* are accessible to applications via the {@link ThreadContext#getThreadContextMap()} method.
* </p>
+ * <p>
+ * Since 3.0.0, {@code ThreadContextMap} combines all its extension interfaces into default methods on this interface.
+ * </p>
*/
public interface ThreadContextMap {
@@ -86,4 +92,85 @@ public interface ThreadContextMap {
* @param key The key to remove.
*/
void remove(final String key);
+
+ /**
+ * Puts all given context map entries into the current thread's
+ * context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.</p>
+ * @param map The map.
+ * @since 3.0.0
+ */
+ default void putAll(Map<String, String> map) {
+ map.forEach(this::put);
+ }
+
+ /**
+ * Returns the context data for reading. Note that regardless of whether the returned context data has been
+ * {@linkplain StringMap#freeze() frozen} (made read-only) or not, callers should not attempt to modify
+ * the returned data structure.
+ *
+ * @return the {@code StringMap}
+ * @since 3.0.0
+ */
+ default StringMap getReadOnlyContextData() {
+ if (this instanceof ReadOnlyThreadContextMap) {
+ return ((ReadOnlyThreadContextMap) this).getReadOnlyContextData();
+ }
+ final Map<String, String> copy = getCopy();
+ StringMap map = new SortedArrayStringMap(copy.size());
+ copy.forEach(map::putValue);
+ map.freeze();
+ return map;
+ }
+
+ /**
+ * Removes all given context map keys from the current thread's context map.
+ *
+ * <p>If the current thread does not have a context map it is
+ * created as a side effect.</p>
+
+ * @param keys The keys.
+ * @since 3.0.0
+ */
+ default void removeAll(Iterable<String> keys) {
+ keys.forEach(this::remove);
+ }
+
+ /**
+ * Returns the Object value for the specified key, or {@code null} if the specified key does not exist in this
+ * collection.
+ *
+ * @param key the key whose value to return
+ * @param <V> The type of the returned value.
+ * @return the value for the specified key or {@code null}
+ * @since 3.0.0
+ */
+ default <V> V getValue(String key) {
+ return Cast.cast(get(key));
+ }
+
+ /**
+ * Puts the specified key-value pair into the collection.
+ *
+ * @param key the key to add or remove. Keys may be {@code null}.
+ * @param <V> The type of the stored and returned value.
+ * @param value the value to add. Values may be {@code null}.
+ * @since 3.0.0
+ */
+ default <V> void putValue(String key, V value) {
+ put(key, value != null ? value.toString() : null);
+ }
+
+ /**
+ * Puts all given key-value pairs into the collection.
+ *
+ * @param values the map of key-value pairs to add
+ * @param <V> The type of the value being added.
+ * @since 3.0.0
+ */
+ default <V> void putAllValues(Map<String, V> values) {
+ values.forEach(this::putValue);
+ }
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap2.java b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap2.java
index b48d5ab90b..1ec419da32 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap2.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/spi/ThreadContextMap2.java
@@ -16,38 +16,14 @@
*/
package org.apache.logging.log4j.spi;
-import java.util.Map;
-
-import org.apache.logging.log4j.util.StringMap;
-
/**
- * Extension service provider interface to implement additional custom MDC behavior for
- * {@link org.apache.logging.log4j.ThreadContext}.
- *
- * Consider implementing {@link CleanableThreadContextMap} instead.
+ * Legacy interface for backward compatibility with extensions to ThreadContextMap.
+ * These methods have since been moved to default methods on ThreadContextMap.
*
* @see ThreadContextMap
* @since 2.7
+ * @deprecated use {@link ThreadContextMap} directly
*/
+@Deprecated(since = "3.0.0")
public interface ThreadContextMap2 extends ThreadContextMap {
-
- /**
- * Puts all given context map entries into the current thread's
- * context map.
- *
- * <p>If the current thread does not have a context map it is
- * created as a side effect.</p>
- * @param map The map.
- * @since 2.7
- */
- void putAll(final Map<String, String> map);
-
- /**
- * Returns the context data for reading. Note that regardless of whether the returned context data has been
- * {@linkplain StringMap#freeze() frozen} (made read-only) or not, callers should not attempt to modify
- * the returned data structure.
- *
- * @return the {@code StringMap}
- */
- StringMap getReadOnlyContextData();
}
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index 74abfe51d3..a12a22538e 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -115,7 +115,7 @@ public class PropertiesUtil implements PropertyEnvironment {
*
* @return the main Log4j PropertiesUtil instance.
*/
- public static PropertyEnvironment getProperties() {
+ public static PropertiesUtil getProperties() {
return COMPONENT_PROPERTIES.value();
}
diff --git a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashStringMap.java b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashStringMap.java
index f976869278..942641506e 100644
--- a/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashStringMap.java
+++ b/log4j-perf/src/main/java/org/apache/logging/log4j/perf/nogc/OpenHashStringMap.java
@@ -16,6 +16,12 @@
*/
package org.apache.logging.log4j.perf.nogc;
+import org.apache.logging.log4j.spi.ThreadContextMap;
+import org.apache.logging.log4j.util.BiConsumer;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.StringMap;
+import org.apache.logging.log4j.util.TriConsumer;
+
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
@@ -26,12 +32,6 @@ import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
-import org.apache.logging.log4j.util.ReadOnlyStringMap;
-import org.apache.logging.log4j.util.StringMap;
-import org.apache.logging.log4j.spi.ThreadContextMap;
-import org.apache.logging.log4j.util.BiConsumer;
-import org.apache.logging.log4j.util.TriConsumer;
-
/**
* Open hash map-based implementation of the {@code ReadOnlyStringMap} interface.
* Implementation based on <a href="http://fastutil.di.unimi.it/">fastutil</a>'s
@@ -485,7 +485,8 @@ public class OpenHashStringMap<K, V> implements StringMap, ThreadContextMap {
}
/** {@inheritDoc} */
- public void putAll(final Map<? extends K, ? extends V> map) {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public void putAll(final Map map) {
if (loadFactor <= .5) {
// The resulting map will be sized for m.size() elements
ensureCapacity(map.size());
@@ -493,9 +494,7 @@ public class OpenHashStringMap<K, V> implements StringMap, ThreadContextMap {
// The resulting map will be tentatively sized for size() + m.size() elements
tryCapacity(size() + map.size());
}
- for (final Map.Entry<? extends K, ? extends V> entry : map.entrySet()) {
- putObjectValue(entry.getKey(), entry.getValue());
- }
+ map.forEach((key, value) -> putObjectValue((K) key, (V) value));
}
private V putObjectValue(final K k, final V v) {
diff --git a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/MDCContextMap.java b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/MDCContextMap.java
index b04d358236..f224d16ede 100644
--- a/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/MDCContextMap.java
+++ b/log4j-to-slf4j/src/main/java/org/apache/logging/slf4j/MDCContextMap.java
@@ -16,18 +16,18 @@
*/
package org.apache.logging.slf4j;
-import java.util.Map;
-import java.util.Map.Entry;
-
-import org.apache.logging.log4j.spi.CleanableThreadContextMap;
+import org.apache.logging.log4j.spi.ThreadContextMap;
import org.apache.logging.log4j.util.SortedArrayStringMap;
import org.apache.logging.log4j.util.StringMap;
import org.slf4j.MDC;
+import java.util.Map;
+import java.util.Map.Entry;
+
/**
* Bind the ThreadContextMap to the SLF4J MDC.
*/
-public class MDCContextMap implements CleanableThreadContextMap {
+public class MDCContextMap implements ThreadContextMap {
private static final StringMap EMPTY_CONTEXT_DATA = new SortedArrayStringMap(1);
static {
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index d3f790c843..c96d40f79a 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -31,6 +31,9 @@
- "remove" - Removed
-->
<release version="3.0.0" date="2022-MM-DD" description="GA Release 3.0.0">
+ <action issue="LOG4J2-3626" dev="mattsicker" type="update">
+ Flatten the ThreadContextMap interfaces with default methods.
+ </action>
<action issue="LOG4J2-3300" dev="mattsicker" type="add">
Add conditional annotations to support more declarative binding factory bundle classes.
</action>