From d32a71defc1c8b52ae0d6d5266b800b569c674a8 Mon Sep 17 00:00:00 2001 From: "Piotr P. Karwasz" Date: Fri, 15 Dec 2023 23:39:42 +0100 Subject: [PATCH] Mark `JdkMapAdapterStringMap` as frozen if map is immutable This PR marks `StringMap`s generated from Java `Map`s as frozen if the wrapped map is immutable. Fixes #2098 --- .../core/impl/JdkMapAdapterStringMapTest.java | 20 ++++++++++++++ .../core/impl/JdkMapAdapterStringMap.java | 5 ++++ ...apAdapterStringMap_detect_immutability.xml | 26 +++++++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 src/changelog/.3.x.x/2098_JdkMapAdapterStringMap_detect_immutability.xml diff --git a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMapTest.java b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMapTest.java index 2948e96ddcc..65e894814d7 100644 --- a/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMapTest.java +++ b/log4j-core-test/src/test/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMapTest.java @@ -16,6 +16,7 @@ */ package org.apache.logging.log4j.core.impl; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertNotEquals; @@ -24,11 +25,16 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import static org.junit.jupiter.api.Assertions.fail; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.stream.Stream; import org.apache.logging.log4j.util.BiConsumer; import org.apache.logging.log4j.util.TriConsumer; import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests the JdkMapAdapterStringMap class. @@ -812,4 +818,18 @@ public void testForEachTriConsumer() throws Exception { original.forEach(COUNTER, state); assertEquals(state.count, original.size()); } + + static Stream testImmutability() { + return Stream.of( + Arguments.of(new HashMap<>(), false), + Arguments.of(Map.of(), true), + Arguments.of(Collections.emptyMap(), true), + Arguments.of(Collections.unmodifiableMap(new HashMap<>()), true)); + } + + @ParameterizedTest + @MethodSource + void testImmutability(final Map map, final boolean frozen) { + assertThat(new JdkMapAdapterStringMap(map).isFrozen()).as("Frozen").isEqualTo(frozen); + } } diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMap.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMap.java index 94cdedf33db..8da3952cd8f 100644 --- a/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMap.java +++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/impl/JdkMapAdapterStringMap.java @@ -52,6 +52,11 @@ public JdkMapAdapterStringMap() { public JdkMapAdapterStringMap(final Map map) { this.map = Objects.requireNonNull(map, "map"); + try { + map.replace(Strings.EMPTY, Strings.EMPTY, Strings.EMPTY); + } catch (final UnsupportedOperationException ignored) { + immutable = true; + } } @Override diff --git a/src/changelog/.3.x.x/2098_JdkMapAdapterStringMap_detect_immutability.xml b/src/changelog/.3.x.x/2098_JdkMapAdapterStringMap_detect_immutability.xml new file mode 100644 index 00000000000..7f3b88b3ce1 --- /dev/null +++ b/src/changelog/.3.x.x/2098_JdkMapAdapterStringMap_detect_immutability.xml @@ -0,0 +1,26 @@ + + + + + + Mark `JdkMapAdapterStringMap` as frozen if map is immutable. + +