LOG4J2-1349 made ThreadContextMap classes abstract

Project: http://git-wip-us.apache.org/repos/asf/logging-log4j2/repo
Commit: http://git-wip-us.apache.org/repos/asf/logging-log4j2/commit/efb22938
Tree: http://git-wip-us.apache.org/repos/asf/logging-log4j2/tree/efb22938
Diff: http://git-wip-us.apache.org/repos/asf/logging-log4j2/diff/efb22938

Branch: refs/heads/LOG4J2-1349-gcfree-threadcontext
Commit: efb2293850576385684b6ace9e9f3dbb3e3107a2
Parents: 1118b27
Author: rpopma <[email protected]>
Authored: Fri Aug 19 23:14:00 2016 +0900
Committer: rpopma <[email protected]>
Committed: Tue Aug 23 00:31:04 2016 +0900

----------------------------------------------------------------------
 ...AbstractCopyOnWriteMutableThreadContext.java | 173 +++++++++++++++++++
 ...AbstractGarbageFreeMutableThreadContext.java | 171 ++++++++++++++++++
 .../CopyOnWriteSortedArrayThreadContext.java    | 156 -----------------
 .../log4j/spi/SortedArrayThreadContext.java     | 156 -----------------
 4 files changed, 344 insertions(+), 312 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/efb22938/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractCopyOnWriteMutableThreadContext.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractCopyOnWriteMutableThreadContext.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractCopyOnWriteMutableThreadContext.java
new file mode 100644
index 0000000..fe6c367
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractCopyOnWriteMutableThreadContext.java
@@ -0,0 +1,173 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.spi;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.logging.log4j.util.PropertiesUtil;
+
+/**
+ * ThreadContextMap implementation backed by {@code MutableContextData}.
+ * A new ThreadContext Map is created each time it is updated and the Map 
stored is always
+ * immutable. This means the Map can be passed to other threads without 
concern that it will be updated. Since it is
+ * expected that the Map will be passed to many more log events than the 
number of keys it contains the performance
+ * should be much better than if the Map was copied for each event.
+ */
+public abstract class AbstractCopyOnWriteMutableThreadContext implements 
ThreadContextMap {
+    /**
+     * Property name ({@value} ) for selecting {@code InheritableThreadLocal} 
(value "true") or plain
+     * {@code ThreadLocal} (value is not "true") in the implementation.
+     */
+    public static final String INHERITABLE_MAP = 
"isThreadContextMapInheritable";
+
+    private final ThreadLocal<MutableContextData> localMap;
+
+    public AbstractCopyOnWriteMutableThreadContext() {
+        this.localMap = createThreadLocalMap();
+    }
+
+    // LOG4J2-479: by default, use a plain ThreadLocal, only use 
InheritableThreadLocal if configured.
+    // (This method is package protected for JUnit tests.)
+    private ThreadLocal<MutableContextData> createThreadLocalMap() {
+        final PropertiesUtil managerProps = PropertiesUtil.getProperties();
+        final boolean inheritable = 
managerProps.getBooleanProperty(INHERITABLE_MAP);
+        if (inheritable) {
+            return new InheritableThreadLocal<MutableContextData>() {
+                @Override
+                protected MutableContextData childValue(final 
MutableContextData parentValue) {
+                    return parentValue != null ? 
createMutableContextData(parentValue) : null;
+                }
+            };
+        }
+        // if not inheritable, return plain ThreadLocal with null as initial 
value
+        return new ThreadLocal<>();
+    }
+
+    protected abstract MutableContextData createMutableContextData();
+
+    protected abstract MutableContextData createMutableContextData(final 
MutableContextData original);
+
+    @Override
+    public void put(final String key, final String value) {
+        MutableContextData map = localMap.get();
+        map = map == null ? createMutableContextData() : 
createMutableContextData(map);
+        map.putValue(key, value);
+        localMap.set(map);
+    }
+
+    @Override
+    public void putAll(final Map<String, String> values) {
+        if (values == null || values.isEmpty()) {
+            return;
+        }
+        MutableContextData map = localMap.get();
+        map = map == null ? createMutableContextData() : 
createMutableContextData(map);
+        for (final Map.Entry<String, String> entry : values.entrySet()) {
+            map.putValue(entry.getKey(), entry.getValue());
+        }
+        localMap.set(map);
+    }
+
+    @Override
+    public String get(final String key) {
+        final MutableContextData map = localMap.get();
+        return map == null ? null : (String) map.getValue(key);
+    }
+
+    @Override
+    public void remove(final String key) {
+        final MutableContextData map = localMap.get();
+        if (map != null) {
+            final MutableContextData copy = createMutableContextData(map);
+            copy.remove(key);
+            localMap.set(copy);
+        }
+    }
+
+    @Override
+    public void clear() {
+        localMap.remove();
+    }
+
+    @Override
+    public boolean containsKey(final String key) {
+        final MutableContextData map = localMap.get();
+        return map != null && map.containsKey(key);
+    }
+
+    @Override
+    public Map<String, String> getCopy() {
+        final MutableContextData map = localMap.get();
+        return map == null ? Collections.<String, String>emptyMap() : 
map.asMap();
+    }
+
+    public ContextData getContextData() {
+        return localMap.get();
+    }
+
+    @Override
+    public Map<String, String> getImmutableMapOrNull() {
+        final MutableContextData map = localMap.get();
+        return map == null ? null : Collections.unmodifiableMap(map.asMap());
+    }
+
+    @Override
+    public boolean isEmpty() {
+        final MutableContextData map = localMap.get();
+        return map == null || map.size() == 0;
+    }
+
+    @Override
+    public String toString() {
+        final MutableContextData map = localMap.get();
+        return map == null ? "{}" : map.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        final MutableContextData map = this.localMap.get();
+        result = prime * result + ((map == null) ? 0 : map.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof ThreadContextMap)) {
+            return false;
+        }
+        final ThreadContextMap other = (ThreadContextMap) obj;
+        final Map<String, String> map = this.getImmutableMapOrNull();
+        final Map<String, String> otherMap = other.getImmutableMapOrNull();
+        if (map == null) {
+            if (otherMap != null) {
+                return false;
+            }
+        } else if (!map.equals(otherMap)) {
+            return false;
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/efb22938/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractGarbageFreeMutableThreadContext.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractGarbageFreeMutableThreadContext.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractGarbageFreeMutableThreadContext.java
new file mode 100644
index 0000000..45010a0
--- /dev/null
+++ 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/AbstractGarbageFreeMutableThreadContext.java
@@ -0,0 +1,171 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.spi;
+
+import java.util.Collections;
+import java.util.Map;
+
+import org.apache.logging.log4j.util.PropertiesUtil;
+
+/**
+ * Garbage-free ThreadContextMap implementation backed by {@code 
MutableContextData}.
+ */
+public abstract class AbstractGarbageFreeMutableThreadContext implements 
ThreadContextMap {
+    /**
+     * Property name ({@value} ) for selecting {@code InheritableThreadLocal} 
(value "true") or plain
+     * {@code ThreadLocal} (value is not "true") in the implementation.
+     */
+    public static final String INHERITABLE_MAP = 
"isThreadContextMapInheritable";
+
+    private final ThreadLocal<MutableContextData> localMap;
+
+    public AbstractGarbageFreeMutableThreadContext() {
+        this.localMap = createThreadLocalMap();
+    }
+
+    // LOG4J2-479: by default, use a plain ThreadLocal, only use 
InheritableThreadLocal if configured.
+    // (This method is package protected for JUnit tests.)
+    private ThreadLocal<MutableContextData> createThreadLocalMap() {
+        final PropertiesUtil managerProps = PropertiesUtil.getProperties();
+        final boolean inheritable = 
managerProps.getBooleanProperty(INHERITABLE_MAP);
+        if (inheritable) {
+            return new InheritableThreadLocal<MutableContextData>() {
+                @Override
+                protected MutableContextData childValue(final 
MutableContextData parentValue) {
+                    return parentValue != null ? 
createMutableContextData(parentValue) : null;
+                }
+            };
+        }
+        // if not inheritable, return plain ThreadLocal with null as initial 
value
+        return new ThreadLocal<>();
+    }
+
+    protected abstract MutableContextData createMutableContextData();
+
+    protected abstract MutableContextData createMutableContextData(final 
MutableContextData original);
+
+    private MutableContextData getThreadLocalMap() {
+        MutableContextData map = localMap.get();
+        if (map == null) {
+            map = createMutableContextData();
+            localMap.set(map);
+        }
+        return map;
+    }
+
+    @Override
+    public void put(final String key, final String value) {
+        getThreadLocalMap().putValue(key, value);
+    }
+
+    @Override
+    public void putAll(final Map<String, String> values) {
+        if (values == null || values.isEmpty()) {
+            return;
+        }
+        final MutableContextData map = getThreadLocalMap();
+        for (final Map.Entry<String, String> entry : values.entrySet()) {
+            map.putValue(entry.getKey(), entry.getValue());
+        }
+    }
+
+    @Override
+    public String get(final String key) {
+        final MutableContextData map = localMap.get();
+        return map == null ? null : (String) map.getValue(key);
+    }
+
+    @Override
+    public void remove(final String key) {
+        final MutableContextData map = localMap.get();
+        if (map != null) {
+            map.remove(key);
+        }
+    }
+
+    @Override
+    public void clear() {
+        localMap.remove();
+    }
+
+    @Override
+    public boolean containsKey(final String key) {
+        final MutableContextData map = localMap.get();
+        return map != null && map.containsKey(key);
+    }
+
+    @Override
+    public Map<String, String> getCopy() {
+        final MutableContextData map = localMap.get();
+        return map == null ? Collections.<String, String>emptyMap() : 
map.asMap();
+    }
+
+    public ContextData getContextData() {
+        return localMap.get();
+    }
+
+    @Override
+    public Map<String, String> getImmutableMapOrNull() {
+        final MutableContextData map = localMap.get();
+        return map == null ? null : Collections.unmodifiableMap(map.asMap());
+    }
+
+    @Override
+    public boolean isEmpty() {
+        final MutableContextData map = localMap.get();
+        return map == null || map.size() == 0;
+    }
+
+    @Override
+    public String toString() {
+        final MutableContextData map = localMap.get();
+        return map == null ? "{}" : map.toString();
+    }
+
+    @Override
+    public int hashCode() {
+        final int prime = 31;
+        int result = 1;
+        final MutableContextData map = this.localMap.get();
+        result = prime * result + ((map == null) ? 0 : map.hashCode());
+        return result;
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (this == obj) {
+            return true;
+        }
+        if (obj == null) {
+            return false;
+        }
+        if (!(obj instanceof ThreadContextMap)) {
+            return false;
+        }
+        final ThreadContextMap other = (ThreadContextMap) obj;
+        final Map<String, String> map = this.getImmutableMapOrNull();
+        final Map<String, String> otherMap = other.getImmutableMapOrNull();
+        if (map == null) {
+            if (otherMap != null) {
+                return false;
+            }
+        } else if (!map.equals(otherMap)) {
+            return false;
+        }
+        return true;
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/efb22938/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContext.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContext.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContext.java
deleted file mode 100644
index be172b4..0000000
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/CopyOnWriteSortedArrayThreadContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.spi;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.logging.log4j.util.PropertiesUtil;
-
-/**
- * ThreadContextMap implementation backed by {@code SortedArrayContextData}.
- * A new ThreadContext Map is created each time it is updated and the Map 
stored is always
- * immutable. This means the Map can be passed to other threads without 
concern that it will be updated. Since it is
- * expected that the Map will be passed to many more log events than the 
number of keys it contains the performance
- * should be much better than if the Map was copied for each event.
- */
-public class CopyOnWriteSortedArrayThreadContext implements ThreadContextMap {
-    /**
-     * Property name ({@value} ) for selecting {@code InheritableThreadLocal} 
(value "true") or plain
-     * {@code ThreadLocal} (value is not "true") in the implementation.
-     */
-    public static final String INHERITABLE_MAP = 
"isThreadContextMapInheritable";
-
-    private final ThreadLocal<ArrayContextData> localMap;
-
-    public CopyOnWriteSortedArrayThreadContext() {
-        this.localMap = createThreadLocalMap();
-    }
-
-    // LOG4J2-479: by default, use a plain ThreadLocal, only use 
InheritableThreadLocal if configured.
-    // (This method is package protected for JUnit tests.)
-    static ThreadLocal<ArrayContextData> createThreadLocalMap() {
-        final PropertiesUtil managerProps = PropertiesUtil.getProperties();
-        final boolean inheritable = 
managerProps.getBooleanProperty(INHERITABLE_MAP);
-        if (inheritable) {
-            return new InheritableThreadLocal<ArrayContextData>() {
-                @Override
-                protected ArrayContextData childValue(final ArrayContextData 
parentValue) {
-                    return parentValue != null ? new 
ArrayContextData(parentValue) : null;
-                }
-            };
-        }
-        // if not inheritable, return plain ThreadLocal with null as initial 
value
-        return new ThreadLocal<>();
-    }
-
-    @Override
-    public void put(final String key, final String value) {
-        ArrayContextData map = localMap.get();
-        map = map == null ? new ArrayContextData() : new ArrayContextData(map);
-        map.put(key, value);
-        localMap.set(map);
-    }
-
-    @Override
-    public String get(final String key) {
-        final ArrayContextData map = localMap.get();
-        return map == null ? null : map.get(key);
-    }
-
-    @Override
-    public void remove(final String key) {
-        final ArrayContextData map = localMap.get();
-        if (map != null) {
-            final ArrayContextData copy = new ArrayContextData(map);
-            copy.remove(key);
-            localMap.set(copy);
-        }
-    }
-
-    @Override
-    public void clear() {
-        localMap.remove();
-    }
-
-    @Override
-    public boolean containsKey(final String key) {
-        final ArrayContextData map = localMap.get();
-        return map != null && map.containsKey(key);
-    }
-
-    @Override
-    public Map<String, String> getCopy() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? Collections.<String, String>emptyMap() : 
map.asMap();
-    }
-
-    public ContextData getContextData() {
-        return localMap.get();
-    }
-
-    @Override
-    public Map<String, String> getImmutableMapOrNull() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? null : Collections.unmodifiableMap(map.asMap());
-    }
-
-    @Override
-    public boolean isEmpty() {
-        final ArrayContextData map = localMap.get();
-        return map == null || map.size() == 0;
-    }
-
-    @Override
-    public String toString() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? "{}" : map.toString();
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        final ArrayContextData map = this.localMap.get();
-        result = prime * result + ((map == null) ? 0 : map.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof ThreadContextMap)) {
-            return false;
-        }
-        final ThreadContextMap other = (ThreadContextMap) obj;
-        final Map<String, String> map = this.getImmutableMapOrNull();
-        final Map<String, String> otherMap = other.getImmutableMapOrNull();
-        if (map == null) {
-            if (otherMap != null) {
-                return false;
-            }
-        } else if (!map.equals(otherMap)) {
-            return false;
-        }
-        return true;
-    }
-}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/efb22938/log4j-api/src/main/java/org/apache/logging/log4j/spi/SortedArrayThreadContext.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/SortedArrayThreadContext.java
 
b/log4j-api/src/main/java/org/apache/logging/log4j/spi/SortedArrayThreadContext.java
deleted file mode 100644
index f3438c5..0000000
--- 
a/log4j-api/src/main/java/org/apache/logging/log4j/spi/SortedArrayThreadContext.java
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.spi;
-
-import java.util.Collections;
-import java.util.Map;
-
-import org.apache.logging.log4j.util.PropertiesUtil;
-
-/**
- * Garbage-free ThreadContextMap implementation backed by {@code 
SortedArrayContextData}.
- */
-public class SortedArrayThreadContext implements ThreadContextMap {
-    /**
-     * Property name ({@value} ) for selecting {@code InheritableThreadLocal} 
(value "true") or plain
-     * {@code ThreadLocal} (value is not "true") in the implementation.
-     */
-    public static final String INHERITABLE_MAP = 
"isThreadContextMapInheritable";
-
-    private final ThreadLocal<ArrayContextData> localMap;
-
-    public SortedArrayThreadContext() {
-        this.localMap = createThreadLocalMap();
-    }
-
-    // LOG4J2-479: by default, use a plain ThreadLocal, only use 
InheritableThreadLocal if configured.
-    // (This method is package protected for JUnit tests.)
-    static ThreadLocal<ArrayContextData> createThreadLocalMap() {
-        final PropertiesUtil managerProps = PropertiesUtil.getProperties();
-        final boolean inheritable = 
managerProps.getBooleanProperty(INHERITABLE_MAP);
-        if (inheritable) {
-            return new InheritableThreadLocal<ArrayContextData>() {
-                @Override
-                protected ArrayContextData childValue(final ArrayContextData 
parentValue) {
-                    return parentValue != null ? new 
ArrayContextData(parentValue) : null;
-                }
-            };
-        }
-        // if not inheritable, return plain ThreadLocal with null as initial 
value
-        return new ThreadLocal<>();
-    }
-
-    private ArrayContextData getThreadLocalMap() {
-        ArrayContextData map = localMap.get();
-        if (map == null) {
-            map = new ArrayContextData();
-            localMap.set(map);
-        }
-        return map;
-    }
-
-    @Override
-    public void put(final String key, final String value) {
-        getThreadLocalMap().put(key, value);
-    }
-
-    @Override
-    public String get(final String key) {
-        final ArrayContextData map = localMap.get();
-        return map == null ? null : map.get(key);
-    }
-
-    @Override
-    public void remove(final String key) {
-        final ArrayContextData map = localMap.get();
-        if (map != null) {
-            map.remove(key);
-        }
-    }
-
-    @Override
-    public void clear() {
-        localMap.remove();
-    }
-
-    @Override
-    public boolean containsKey(final String key) {
-        final ArrayContextData map = localMap.get();
-        return map != null && map.containsKey(key);
-    }
-
-    @Override
-    public Map<String, String> getCopy() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? Collections.<String, String>emptyMap() : 
map.asMap();
-    }
-
-    public ContextData getContextData() {
-        return localMap.get();
-    }
-
-    @Override
-    public Map<String, String> getImmutableMapOrNull() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? null : Collections.unmodifiableMap(map.asMap());
-    }
-
-    @Override
-    public boolean isEmpty() {
-        final ArrayContextData map = localMap.get();
-        return map == null || map.size() == 0;
-    }
-
-    @Override
-    public String toString() {
-        final ArrayContextData map = localMap.get();
-        return map == null ? "{}" : map.toString();
-    }
-
-    @Override
-    public int hashCode() {
-        final int prime = 31;
-        int result = 1;
-        final ArrayContextData map = this.localMap.get();
-        result = prime * result + ((map == null) ? 0 : map.hashCode());
-        return result;
-    }
-
-    @Override
-    public boolean equals(final Object obj) {
-        if (this == obj) {
-            return true;
-        }
-        if (obj == null) {
-            return false;
-        }
-        if (!(obj instanceof ThreadContextMap)) {
-            return false;
-        }
-        final ThreadContextMap other = (ThreadContextMap) obj;
-        final Map<String, String> map = this.getImmutableMapOrNull();
-        final Map<String, String> otherMap = other.getImmutableMapOrNull();
-        if (map == null) {
-            if (otherMap != null) {
-                return false;
-            }
-        } else if (!map.equals(otherMap)) {
-            return false;
-        }
-        return true;
-    }
-}

Reply via email to