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