21
21
import java .util .HashMap ;
22
22
import java .util .Map ;
23
23
import java .util .Objects ;
24
+ import java .util .WeakHashMap ;
24
25
import org .apache .logging .log4j .util .BiConsumer ;
25
26
import org .apache .logging .log4j .util .ReadOnlyStringMap ;
26
27
import org .apache .logging .log4j .util .StringMap ;
@@ -41,13 +42,16 @@ public class JdkMapAdapterStringMap implements StringMap {
41
42
}
42
43
return left .compareTo (right );
43
44
};
45
+ // Cache of known unmodifiable map implementations.
46
+ // It is a cache, no need to synchronise it between threads.
47
+ private static Map <Class <?>, Void > UNMODIFIABLE_MAPS_CACHE = new WeakHashMap <>();
44
48
45
49
private final Map <String , String > map ;
46
50
private boolean immutable = false ;
47
51
private transient String [] sortedKeys ;
48
52
49
53
public JdkMapAdapterStringMap () {
50
- this (new HashMap <String , String >(), false );
54
+ this (new HashMap <>(), false );
51
55
}
52
56
53
57
/**
@@ -57,25 +61,41 @@ public JdkMapAdapterStringMap() {
57
61
@ Deprecated
58
62
public JdkMapAdapterStringMap (final Map <String , String > map ) {
59
63
this .map = Objects .requireNonNull (map , "map" );
60
- try {
61
- map .replace (Strings .EMPTY , Strings .EMPTY , Strings .EMPTY );
62
- } catch (final UnsupportedOperationException ignored ) {
64
+ // Known immutable implementations
65
+ if (UNMODIFIABLE_MAPS_CACHE .containsKey (map .getClass ())) {
63
66
immutable = true ;
67
+ } else {
68
+ // Check with a NO-OP replacement
69
+ try {
70
+ map .replace (Strings .EMPTY , Strings .EMPTY , Strings .EMPTY );
71
+ } catch (final UnsupportedOperationException ignored ) {
72
+ final WeakHashMap <Class <?>, Void > cache = new WeakHashMap <>(UNMODIFIABLE_MAPS_CACHE );
73
+ cache .put (map .getClass (), null );
74
+ UNMODIFIABLE_MAPS_CACHE = cache ;
75
+ immutable = true ;
76
+ }
64
77
}
65
78
}
66
79
67
80
/**
81
+ * Constructs a new {@link StringMap}, based on a JDK map.
82
+ * <p>
83
+ * The underlying map should not be modified after this call.
84
+ * </p>
85
+ * <p>
86
+ * If the {@link Map} implementation does not allow modifications, {@code frozen} should be set to {@code true}.
87
+ * </p>
68
88
* @param map a JDK map,
69
- * @param immutable must be {@code true} if the map is immutable or it should not be modified .
89
+ * @param frozen if {@code true} this collection will be immutable .
70
90
*/
71
- public JdkMapAdapterStringMap (final Map <String , String > map , final boolean immutable ) {
91
+ public JdkMapAdapterStringMap (final Map <String , String > map , final boolean frozen ) {
72
92
this .map = Objects .requireNonNull (map , "map" );
73
- this .immutable = immutable ;
93
+ this .immutable = frozen ;
74
94
}
75
95
76
96
@ Override
77
97
public Map <String , String > toMap () {
78
- return map ;
98
+ return new HashMap <>( map ) ;
79
99
}
80
100
81
101
private void assertNotFrozen () {
0 commit comments