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 <[email protected]> AuthorDate: Sun Nov 6 14:36:07 2022 -0600 LOG4J2-3626 - Flatten ThreadContextMap with default methods Signed-off-by: Matt Sicker <[email protected]> --- .../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>
