http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedArrayStringMapTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedArrayStringMapTest.java
 
b/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedArrayStringMapTest.java
new file mode 100644
index 0000000..42bfce7
--- /dev/null
+++ 
b/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedArrayStringMapTest.java
@@ -0,0 +1,772 @@
+package org.apache.logging.log4j.util;/*
+ * 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.
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.lang.reflect.Field;
+import java.util.ConcurrentModificationException;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Tests the SortedArrayStringMap class.
+ */
+public class SortedArrayStringMapTest {
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorDisallowsNegativeCapacity() throws Exception {
+        new SortedArrayStringMap(-1);
+    }
+
+    @Test(expected = IllegalArgumentException.class)
+    public void testConstructorDisallowsZeroCapacity() throws Exception {
+        new SortedArrayStringMap(0);
+    }
+
+    @Test
+    public void testConstructorIgnoresNull() throws Exception {
+        assertEquals(0, new SortedArrayStringMap(null).size());
+    }
+
+    @Test
+    public void testToString() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        assertEquals("{3=3value, B=Bvalue, a=avalue}", original.toString());
+    }
+
+    @Test
+    public void testSerialization() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        final byte[] binary = serialize(original);
+        final SortedArrayStringMap copy = deserialize(binary);
+        assertEquals(original, copy);
+    }
+
+    private byte[] serialize(final SortedArrayStringMap data) throws 
IOException {
+        final ByteArrayOutputStream arr = new ByteArrayOutputStream();
+        final ObjectOutputStream out = new ObjectOutputStream(arr);
+        out.writeObject(data);
+        return arr.toByteArray();
+    }
+
+    private SortedArrayStringMap deserialize(final byte[] binary) throws 
IOException, ClassNotFoundException {
+        final ByteArrayInputStream inArr = new ByteArrayInputStream(binary);
+        final ObjectInputStream in = new ObjectInputStream(inArr);
+        final SortedArrayStringMap result = (SortedArrayStringMap) 
in.readObject();
+        return result;
+    }
+
+    @Test
+    public void testPutAll() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        final SortedArrayStringMap other = new SortedArrayStringMap();
+        other.putAll(original);
+        assertEquals(original, other);
+
+        other.putValue("3", "otherValue");
+        assertNotEquals(original, other);
+
+        other.putValue("3", null);
+        assertNotEquals(original, other);
+
+        other.putValue("3", "3value");
+        assertEquals(original, other);
+    }
+
+    @Test
+    public void testEquals() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        assertEquals(original, original); // equal to itself
+
+        final SortedArrayStringMap other = new SortedArrayStringMap();
+        other.putValue("a", "avalue");
+        assertNotEquals(original, other);
+
+        other.putValue("B", "Bvalue");
+        assertNotEquals(original, other);
+
+        other.putValue("3", "3value");
+        assertEquals(original, other);
+
+        other.putValue("3", "otherValue");
+        assertNotEquals(original, other);
+
+        other.putValue("3", null);
+        assertNotEquals(original, other);
+
+        other.putValue("3", "3value");
+        assertEquals(original, other);
+    }
+
+    @Test
+    public void testToMap() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        final Map<String, Object> expected = new HashMap<>();
+        expected.put("a", "avalue");
+        expected.put("B", "Bvalue");
+        expected.put("3", "3value");
+
+        assertEquals(expected, original.toMap());
+
+        try {
+            original.toMap().put("abc", "xyz");
+        } catch (final UnsupportedOperationException ex) {
+            fail("Expected map to be mutable, but " + ex);
+        }
+    }
+
+    @Test
+    public void testPutAll_KeepsExistingValues() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.putValue("b", "bbb");
+        original.putValue("c", "ccc");
+        assertEquals("size", 3, original.size());
+
+        // add empty context data
+        original.putAll(new SortedArrayStringMap());
+        assertEquals("size after put empty", 3, original.size());
+        assertEquals("aaa", original.getValue("a"));
+        assertEquals("bbb", original.getValue("b"));
+        assertEquals("ccc", original.getValue("c"));
+
+        final SortedArrayStringMap other = new SortedArrayStringMap();
+        other.putValue("1", "111");
+        other.putValue("2", "222");
+        other.putValue("3", "333");
+        original.putAll(other);
+
+        assertEquals("size after put other", 6, original.size());
+        assertEquals("aaa", original.getValue("a"));
+        assertEquals("bbb", original.getValue("b"));
+        assertEquals("ccc", original.getValue("c"));
+        assertEquals("111", original.getValue("1"));
+        assertEquals("222", original.getValue("2"));
+        assertEquals("333", original.getValue("3"));
+    }
+
+    @Test
+    public void testPutAllSelfDoesNotModify() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.putValue("b", "bbb");
+        original.putValue("c", "ccc");
+        assertEquals("size", 3, original.size());
+
+        // putAll with self
+        original.putAll(original);
+        assertEquals("size after put empty", 3, original.size());
+        assertEquals("aaa", original.getValue("a"));
+        assertEquals("bbb", original.getValue("b"));
+        assertEquals("ccc", original.getValue("c"));
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationBiConsumerPut() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new BiConsumer<String, Object>() {
+            @Override
+            public void accept(final String s, final Object o) {
+                original.putValue("c", "other");
+            }
+        });
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationBiConsumerPutValue() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new BiConsumer<String, Object>() {
+            @Override
+            public void accept(final String s, final Object o) {
+                original.putValue("c", "other");
+            }
+        });
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationBiConsumerRemove() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new BiConsumer<String, Object>() {
+            @Override
+            public void accept(final String s, final Object o) {
+                original.remove("a");
+            }
+        });
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationBiConsumerClear() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new BiConsumer<String, Object>() {
+            @Override
+            public void accept(final String s, final Object o) {
+                original.clear();
+            }
+        });
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationTriConsumerPut() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new TriConsumer<String, Object, Object>() {
+            @Override
+            public void accept(final String s, final Object o, final Object 
o2) {
+                original.putValue("c", "other");
+            }
+        }, null);
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationTriConsumerPutValue() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new TriConsumer<String, Object, Object>() {
+            @Override
+            public void accept(final String s, final Object o, final Object 
o2) {
+                original.putValue("c", "other");
+            }
+        }, null);
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationTriConsumerRemove() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new TriConsumer<String, Object, Object>() {
+            @Override
+            public void accept(final String s, final Object o, final Object 
o2) {
+                original.remove("a");
+            }
+        }, null);
+    }
+
+    @Test(expected = ConcurrentModificationException.class)
+    public void testConcurrentModificationTriConsumerClear() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.forEach(new TriConsumer<String, Object, Object>() {
+            @Override
+            public void accept(final String s, final Object o, final Object 
o2) {
+                original.clear();
+            }
+        }, null);
+    }
+
+    @Test
+    public void testInitiallyNotFrozen() {
+        assertFalse(new SortedArrayStringMap().isFrozen());
+    }
+
+    @Test
+    public void testIsFrozenAfterCallingFreeze() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        assertFalse("before freeze", original.isFrozen());
+        original.freeze();
+        assertTrue("after freeze", original.isFrozen());
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testFreezeProhibitsPutValue() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.freeze();
+        original.putValue("a", "aaa");
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testFreezeProhibitsRemove() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("b", "bbb");
+        original.freeze();
+        original.remove("b"); // existing key: modifies the collection
+    }
+
+    @Test
+    public void testFreezeAllowsRemoveOfNonExistingKey() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("b", "bbb");
+        original.freeze();
+        original.remove("a"); // no actual modification
+    }
+
+    @Test
+    public void testFreezeAllowsRemoveIfEmpty() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.freeze();
+        original.remove("a"); // no exception
+    }
+
+    @Test(expected = UnsupportedOperationException.class)
+    public void testFreezeProhibitsClear() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "aaa");
+        original.freeze();
+        original.clear();
+    }
+
+    @Test
+    public void testFreezeAllowsClearIfEmpty() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.freeze();
+        original.clear();
+    }
+
+    @Test
+    public void testPutInsertsInAlphabeticOrder() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue");
+
+        assertEquals("avalue", original.getValue("a"));
+        assertEquals("avalue", original.getValueAt(2));
+
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("Bvalue", original.getValueAt(1));
+
+        assertEquals("3value", original.getValue("3"));
+        assertEquals("3value", original.getValueAt(0));
+
+        assertEquals("cvalue", original.getValue("c"));
+        assertEquals("cvalue", original.getValueAt(3));
+
+        assertEquals("dvalue", original.getValue("d"));
+        assertEquals("dvalue", original.getValueAt(4));
+    }
+
+    @Test
+    public void testPutValueInsertsInAlphabeticOrder() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue");
+
+        assertEquals("avalue", original.getValue("a"));
+        assertEquals("avalue", original.getValueAt(2));
+
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("Bvalue", original.getValueAt(1));
+
+        assertEquals("3value", original.getValue("3"));
+        assertEquals("3value", original.getValueAt(0));
+
+        assertEquals("cvalue", original.getValue("c"));
+        assertEquals("cvalue", original.getValueAt(3));
+
+        assertEquals("dvalue", original.getValue("d"));
+        assertEquals("dvalue", original.getValueAt(4));
+    }
+
+    @Test
+    public void testNullKeysAllowed() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue");
+        assertEquals(5, original.size());
+        assertEquals("{3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", 
original.toString());
+
+        original.putValue(null, "nullvalue");
+        assertEquals(6, original.size());
+        assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
+
+        original.putValue(null, "otherNullvalue");
+        assertEquals("{null=otherNullvalue, 3=3value, B=Bvalue, a=avalue, 
c=cvalue, d=dvalue}", original.toString());
+        assertEquals(6, original.size());
+
+        original.putValue(null, "nullvalue");
+        assertEquals(6, original.size());
+        assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
+
+        original.putValue(null, "abc");
+        assertEquals(6, original.size());
+        assertEquals("{null=abc, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
+    }
+
+    @Test
+    public void testNullKeysCopiedToAsMap() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue");
+        assertEquals(5, original.size());
+
+        final HashMap<String, String> expected = new HashMap<>();
+        expected.put("a", "avalue");
+        expected.put("B", "Bvalue");
+        expected.put("3", "3value");
+        expected.put("c", "cvalue");
+        expected.put("d", "dvalue");
+        assertEquals("initial", expected, original.toMap());
+
+        original.putValue(null, "nullvalue");
+        expected.put(null, "nullvalue");
+        assertEquals(6, original.size());
+        assertEquals("with null key", expected, original.toMap());
+
+        original.putValue(null, "otherNullvalue");
+        expected.put(null, "otherNullvalue");
+        assertEquals(6, original.size());
+        assertEquals("with null key value2", expected, original.toMap());
+
+        original.putValue(null, "nullvalue");
+        expected.put(null, "nullvalue");
+        assertEquals(6, original.size());
+        assertEquals("with null key value1 again", expected, original.toMap());
+
+        original.putValue(null, "abc");
+        expected.put(null, "abc");
+        assertEquals(6, original.size());
+        assertEquals("with null key value3", expected, original.toMap());
+    }
+
+    @Test
+    public void testRemove() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        assertEquals(1, original.size());
+        assertEquals("avalue", original.getValue("a"));
+
+        original.remove("a");
+        assertEquals(0, original.size());
+        assertNull("no a val", original.getValue("a"));
+
+        original.remove("B");
+        assertEquals(0, original.size());
+        assertNull("no B val", original.getValue("B"));
+    }
+
+    @Test
+    public void testRemoveNullsOutRemovedSlot() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("b", "bvalue");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue");
+        original.remove("a");
+        original.remove("b");
+        original.remove("c");
+        original.remove("d");
+        assertNull(original.getValueAt(0));
+
+        // ensure slots in the values array are nulled out
+        final Field f = SortedArrayStringMap.class.getDeclaredField("values");
+        f.setAccessible(true);
+        final Object[] values = (Object[]) f.get(original);
+        for (int i = 0; i < values.length; i++) {
+            assertNull(values[i]);
+        }
+    }
+
+    @Test
+    public void testRemoveWhenFull() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("b", "bvalue");
+        original.putValue("c", "cvalue");
+        original.putValue("d", "dvalue"); // default capacity = 4
+        original.remove("d");
+    }
+
+    @Test
+    public void testNullValuesArePreserved() {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        assertEquals(1, original.size());
+        assertEquals("avalue", original.getValue("a"));
+
+        original.putValue("a", null);
+        assertEquals(1, original.size());
+        assertNull("no a val", original.getValue("a"));
+
+        original.putValue("B", null);
+        assertEquals(2, original.size());
+        assertNull("no B val", original.getValue("B"));
+    }
+
+    @Test
+    public void testGet() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        assertEquals("avalue", original.getValue("a"));
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("3value", original.getValue("3"));
+
+        original.putValue("0", "0value");
+        assertEquals("0value", original.getValue("0"));
+        assertEquals("3value", original.getValue("3"));
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("avalue", original.getValue("a"));
+    }
+
+    @Test
+    public void testGetValue_GetValueAt() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        assertEquals("avalue", original.getValue("a"));
+        assertEquals("avalue", original.getValueAt(2));
+
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("Bvalue", original.getValueAt(1));
+
+        assertEquals("3value", original.getValue("3"));
+        assertEquals("3value", original.getValueAt(0));
+
+        original.putValue("0", "0value");
+        assertEquals("0value", original.getValue("0"));
+        assertEquals("0value", original.getValueAt(0));
+        assertEquals("3value", original.getValue("3"));
+        assertEquals("3value", original.getValueAt(1));
+        assertEquals("Bvalue", original.getValue("B"));
+        assertEquals("Bvalue", original.getValueAt(2));
+        assertEquals("avalue", original.getValue("a"));
+        assertEquals("avalue", original.getValueAt(3));
+    }
+
+    @Test
+    public void testClear() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+        assertEquals(3, original.size());
+
+        original.clear();
+        assertEquals(0, original.size());
+
+        // ensure slots in the values array are nulled out
+        final Field f = SortedArrayStringMap.class.getDeclaredField("values");
+        f.setAccessible(true);
+        final Object[] values = (Object[]) f.get(original);
+        for (int i = 0; i < values.length; i++) {
+            assertNull(values[i]);
+        }
+    }
+
+    @Test
+    public void testIndexOfKey() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        assertEquals(0, original.indexOfKey("a"));
+
+        original.putValue("B", "Bvalue");
+        assertEquals(1, original.indexOfKey("a"));
+        assertEquals(0, original.indexOfKey("B"));
+
+        original.putValue("3", "3value");
+        assertEquals(2, original.indexOfKey("a"));
+        assertEquals(1, original.indexOfKey("B"));
+        assertEquals(0, original.indexOfKey("3"));
+
+        original.putValue("A", "AAA");
+        assertEquals(3, original.indexOfKey("a"));
+        assertEquals(2, original.indexOfKey("B"));
+        assertEquals(1, original.indexOfKey("A"));
+        assertEquals(0, original.indexOfKey("3"));
+
+        original.putValue("C", "CCC");
+        assertEquals(4, original.indexOfKey("a"));
+        assertEquals(3, original.indexOfKey("C"));
+        assertEquals(2, original.indexOfKey("B"));
+        assertEquals(1, original.indexOfKey("A"));
+        assertEquals(0, original.indexOfKey("3"));
+
+        original.putValue("2", "222");
+        assertEquals(5, original.indexOfKey("a"));
+        assertEquals(4, original.indexOfKey("C"));
+        assertEquals(3, original.indexOfKey("B"));
+        assertEquals(2, original.indexOfKey("A"));
+        assertEquals(1, original.indexOfKey("3"));
+        assertEquals(0, original.indexOfKey("2"));
+    }
+
+    @Test
+    public void testContainsKey() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        assertFalse("a", original.containsKey("a"));
+        assertFalse("B", original.containsKey("B"));
+        assertFalse("3", original.containsKey("3"));
+        assertFalse("A", original.containsKey("A"));
+
+        original.putValue("a", "avalue");
+        assertTrue("a", original.containsKey("a"));
+        assertFalse("B", original.containsKey("B"));
+        assertFalse("3", original.containsKey("3"));
+        assertFalse("A", original.containsKey("A"));
+
+        original.putValue("B", "Bvalue");
+        assertTrue("a", original.containsKey("a"));
+        assertTrue("B", original.containsKey("B"));
+        assertFalse("3", original.containsKey("3"));
+        assertFalse("A", original.containsKey("A"));
+
+        original.putValue("3", "3value");
+        assertTrue("a", original.containsKey("a"));
+        assertTrue("B", original.containsKey("B"));
+        assertTrue("3", original.containsKey("3"));
+        assertFalse("A", original.containsKey("A"));
+
+        original.putValue("A", "AAA");
+        assertTrue("a", original.containsKey("a"));
+        assertTrue("B", original.containsKey("B"));
+        assertTrue("3", original.containsKey("3"));
+        assertTrue("A", original.containsKey("A"));
+    }
+
+    @Test
+    public void testGetValueAt() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        assertEquals("a", original.getKeyAt(0));
+        assertEquals("avalue", original.getValueAt(0));
+
+        original.putValue("B", "Bvalue");
+        assertEquals("B", original.getKeyAt(0));
+        assertEquals("Bvalue", original.getValueAt(0));
+        assertEquals("a", original.getKeyAt(1));
+        assertEquals("avalue", original.getValueAt(1));
+
+        original.putValue("3", "3value");
+        assertEquals("3", original.getKeyAt(0));
+        assertEquals("3value", original.getValueAt(0));
+        assertEquals("B", original.getKeyAt(1));
+        assertEquals("Bvalue", original.getValueAt(1));
+        assertEquals("a", original.getKeyAt(2));
+        assertEquals("avalue", original.getValueAt(2));
+    }
+
+    @Test
+    public void testSizeAndIsEmpty() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        assertEquals(0, original.size());
+        assertTrue("initial", original.isEmpty());
+
+        original.putValue("a", "avalue");
+        assertEquals(1, original.size());
+        assertFalse("size=" + original.size(), original.isEmpty());
+
+        original.putValue("B", "Bvalue");
+        assertEquals(2, original.size());
+        assertFalse("size=" + original.size(), original.isEmpty());
+
+        original.putValue("3", "3value");
+        assertEquals(3, original.size());
+        assertFalse("size=" + original.size(), original.isEmpty());
+
+        original.remove("B");
+        assertEquals(2, original.size());
+        assertFalse("size=" + original.size(), original.isEmpty());
+
+        original.remove("3");
+        assertEquals(1, original.size());
+        assertFalse("size=" + original.size(), original.isEmpty());
+
+        original.remove("a");
+        assertEquals(0, original.size());
+        assertTrue("size=" + original.size(), original.isEmpty());
+    }
+
+    @Test
+    public void testForEachBiConsumer() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        original.forEach(new BiConsumer<String, String>() {
+            int count = 0;
+            @Override
+            public void accept(final String key, final String value) {
+                assertEquals("key", key, original.getKeyAt(count));
+                assertEquals("val", value, original.getValueAt(count));
+                count++;
+                assertTrue("count should not exceed size but was " + count, 
count <= original.size());
+            }
+        });
+    }
+
+    static class State {
+        SortedArrayStringMap data;
+        int count;
+    }
+    static TriConsumer<String, String, State> COUNTER = new 
TriConsumer<String, String, State>() {
+        @Override
+        public void accept(final String key, final String value, final State 
state) {
+            assertEquals("key", key, state.data.getKeyAt(state.count));
+            assertEquals("val", value, state.data.getValueAt(state.count));
+            state.count++;
+            assertTrue("count should not exceed size but was " + state.count,
+                    state.count <= state.data.size());
+        }
+    };
+
+    @Test
+    public void testForEachTriConsumer() throws Exception {
+        final SortedArrayStringMap original = new SortedArrayStringMap();
+        original.putValue("a", "avalue");
+        original.putValue("B", "Bvalue");
+        original.putValue("3", "3value");
+
+        final State state = new State();
+        state.data = original;
+        original.forEach(COUNTER, state);
+        assertEquals(state.count, original.size());
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedStringArrayMapTest.java
----------------------------------------------------------------------
diff --git 
a/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedStringArrayMapTest.java
 
b/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedStringArrayMapTest.java
deleted file mode 100644
index 00f98e6..0000000
--- 
a/log4j-api/src/test/java/org/apache/logging/log4j/util/SortedStringArrayMapTest.java
+++ /dev/null
@@ -1,772 +0,0 @@
-package org.apache.logging.log4j.util;/*
- * 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.
- */
-
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.lang.reflect.Field;
-import java.util.ConcurrentModificationException;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.junit.Test;
-
-import static org.junit.Assert.*;
-
-/**
- * Tests the SortedStringArrayMap class.
- */
-public class SortedStringArrayMapTest {
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testConstructorDisallowsNegativeCapacity() throws Exception {
-        new SortedStringArrayMap(-1);
-    }
-
-    @Test(expected = IllegalArgumentException.class)
-    public void testConstructorDisallowsZeroCapacity() throws Exception {
-        new SortedStringArrayMap(0);
-    }
-
-    @Test
-    public void testConstructorIgnoresNull() throws Exception {
-        assertEquals(0, new SortedStringArrayMap(null).size());
-    }
-
-    @Test
-    public void testToString() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        assertEquals("{3=3value, B=Bvalue, a=avalue}", original.toString());
-    }
-
-    @Test
-    public void testSerialization() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        final byte[] binary = serialize(original);
-        final SortedStringArrayMap copy = deserialize(binary);
-        assertEquals(original, copy);
-    }
-
-    private byte[] serialize(final SortedStringArrayMap data) throws 
IOException {
-        final ByteArrayOutputStream arr = new ByteArrayOutputStream();
-        final ObjectOutputStream out = new ObjectOutputStream(arr);
-        out.writeObject(data);
-        return arr.toByteArray();
-    }
-
-    private SortedStringArrayMap deserialize(final byte[] binary) throws 
IOException, ClassNotFoundException {
-        final ByteArrayInputStream inArr = new ByteArrayInputStream(binary);
-        final ObjectInputStream in = new ObjectInputStream(inArr);
-        final SortedStringArrayMap result = (SortedStringArrayMap) 
in.readObject();
-        return result;
-    }
-
-    @Test
-    public void testPutAll() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        final SortedStringArrayMap other = new SortedStringArrayMap();
-        other.putAll(original);
-        assertEquals(original, other);
-
-        other.putValue("3", "otherValue");
-        assertNotEquals(original, other);
-
-        other.putValue("3", null);
-        assertNotEquals(original, other);
-
-        other.putValue("3", "3value");
-        assertEquals(original, other);
-    }
-
-    @Test
-    public void testEquals() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        assertEquals(original, original); // equal to itself
-
-        final SortedStringArrayMap other = new SortedStringArrayMap();
-        other.putValue("a", "avalue");
-        assertNotEquals(original, other);
-
-        other.putValue("B", "Bvalue");
-        assertNotEquals(original, other);
-
-        other.putValue("3", "3value");
-        assertEquals(original, other);
-
-        other.putValue("3", "otherValue");
-        assertNotEquals(original, other);
-
-        other.putValue("3", null);
-        assertNotEquals(original, other);
-
-        other.putValue("3", "3value");
-        assertEquals(original, other);
-    }
-
-    @Test
-    public void testToMap() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        final Map<String, Object> expected = new HashMap<>();
-        expected.put("a", "avalue");
-        expected.put("B", "Bvalue");
-        expected.put("3", "3value");
-
-        assertEquals(expected, original.toMap());
-
-        try {
-            original.toMap().put("abc", "xyz");
-        } catch (final UnsupportedOperationException ex) {
-            fail("Expected map to be mutable, but " + ex);
-        }
-    }
-
-    @Test
-    public void testPutAll_KeepsExistingValues() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.putValue("b", "bbb");
-        original.putValue("c", "ccc");
-        assertEquals("size", 3, original.size());
-
-        // add empty context data
-        original.putAll(new SortedStringArrayMap());
-        assertEquals("size after put empty", 3, original.size());
-        assertEquals("aaa", original.getValue("a"));
-        assertEquals("bbb", original.getValue("b"));
-        assertEquals("ccc", original.getValue("c"));
-
-        final SortedStringArrayMap other = new SortedStringArrayMap();
-        other.putValue("1", "111");
-        other.putValue("2", "222");
-        other.putValue("3", "333");
-        original.putAll(other);
-
-        assertEquals("size after put other", 6, original.size());
-        assertEquals("aaa", original.getValue("a"));
-        assertEquals("bbb", original.getValue("b"));
-        assertEquals("ccc", original.getValue("c"));
-        assertEquals("111", original.getValue("1"));
-        assertEquals("222", original.getValue("2"));
-        assertEquals("333", original.getValue("3"));
-    }
-
-    @Test
-    public void testPutAllSelfDoesNotModify() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.putValue("b", "bbb");
-        original.putValue("c", "ccc");
-        assertEquals("size", 3, original.size());
-
-        // putAll with self
-        original.putAll(original);
-        assertEquals("size after put empty", 3, original.size());
-        assertEquals("aaa", original.getValue("a"));
-        assertEquals("bbb", original.getValue("b"));
-        assertEquals("ccc", original.getValue("c"));
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationBiConsumerPut() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new BiConsumer<String, Object>() {
-            @Override
-            public void accept(final String s, final Object o) {
-                original.putValue("c", "other");
-            }
-        });
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationBiConsumerPutValue() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new BiConsumer<String, Object>() {
-            @Override
-            public void accept(final String s, final Object o) {
-                original.putValue("c", "other");
-            }
-        });
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationBiConsumerRemove() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new BiConsumer<String, Object>() {
-            @Override
-            public void accept(final String s, final Object o) {
-                original.remove("a");
-            }
-        });
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationBiConsumerClear() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new BiConsumer<String, Object>() {
-            @Override
-            public void accept(final String s, final Object o) {
-                original.clear();
-            }
-        });
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationTriConsumerPut() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new TriConsumer<String, Object, Object>() {
-            @Override
-            public void accept(final String s, final Object o, final Object 
o2) {
-                original.putValue("c", "other");
-            }
-        }, null);
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationTriConsumerPutValue() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new TriConsumer<String, Object, Object>() {
-            @Override
-            public void accept(final String s, final Object o, final Object 
o2) {
-                original.putValue("c", "other");
-            }
-        }, null);
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationTriConsumerRemove() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new TriConsumer<String, Object, Object>() {
-            @Override
-            public void accept(final String s, final Object o, final Object 
o2) {
-                original.remove("a");
-            }
-        }, null);
-    }
-
-    @Test(expected = ConcurrentModificationException.class)
-    public void testConcurrentModificationTriConsumerClear() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.forEach(new TriConsumer<String, Object, Object>() {
-            @Override
-            public void accept(final String s, final Object o, final Object 
o2) {
-                original.clear();
-            }
-        }, null);
-    }
-
-    @Test
-    public void testInitiallyNotFrozen() {
-        assertFalse(new SortedStringArrayMap().isFrozen());
-    }
-
-    @Test
-    public void testIsFrozenAfterCallingFreeze() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        assertFalse("before freeze", original.isFrozen());
-        original.freeze();
-        assertTrue("after freeze", original.isFrozen());
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testFreezeProhibitsPutValue() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.freeze();
-        original.putValue("a", "aaa");
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testFreezeProhibitsRemove() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("b", "bbb");
-        original.freeze();
-        original.remove("b"); // existing key: modifies the collection
-    }
-
-    @Test
-    public void testFreezeAllowsRemoveOfNonExistingKey() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("b", "bbb");
-        original.freeze();
-        original.remove("a"); // no actual modification
-    }
-
-    @Test
-    public void testFreezeAllowsRemoveIfEmpty() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.freeze();
-        original.remove("a"); // no exception
-    }
-
-    @Test(expected = UnsupportedOperationException.class)
-    public void testFreezeProhibitsClear() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "aaa");
-        original.freeze();
-        original.clear();
-    }
-
-    @Test
-    public void testFreezeAllowsClearIfEmpty() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.freeze();
-        original.clear();
-    }
-
-    @Test
-    public void testPutInsertsInAlphabeticOrder() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue");
-
-        assertEquals("avalue", original.getValue("a"));
-        assertEquals("avalue", original.getValueAt(2));
-
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("Bvalue", original.getValueAt(1));
-
-        assertEquals("3value", original.getValue("3"));
-        assertEquals("3value", original.getValueAt(0));
-
-        assertEquals("cvalue", original.getValue("c"));
-        assertEquals("cvalue", original.getValueAt(3));
-
-        assertEquals("dvalue", original.getValue("d"));
-        assertEquals("dvalue", original.getValueAt(4));
-    }
-
-    @Test
-    public void testPutValueInsertsInAlphabeticOrder() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue");
-
-        assertEquals("avalue", original.getValue("a"));
-        assertEquals("avalue", original.getValueAt(2));
-
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("Bvalue", original.getValueAt(1));
-
-        assertEquals("3value", original.getValue("3"));
-        assertEquals("3value", original.getValueAt(0));
-
-        assertEquals("cvalue", original.getValue("c"));
-        assertEquals("cvalue", original.getValueAt(3));
-
-        assertEquals("dvalue", original.getValue("d"));
-        assertEquals("dvalue", original.getValueAt(4));
-    }
-
-    @Test
-    public void testNullKeysAllowed() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue");
-        assertEquals(5, original.size());
-        assertEquals("{3=3value, B=Bvalue, a=avalue, c=cvalue, d=dvalue}", 
original.toString());
-
-        original.putValue(null, "nullvalue");
-        assertEquals(6, original.size());
-        assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
-
-        original.putValue(null, "otherNullvalue");
-        assertEquals("{null=otherNullvalue, 3=3value, B=Bvalue, a=avalue, 
c=cvalue, d=dvalue}", original.toString());
-        assertEquals(6, original.size());
-
-        original.putValue(null, "nullvalue");
-        assertEquals(6, original.size());
-        assertEquals("{null=nullvalue, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
-
-        original.putValue(null, "abc");
-        assertEquals(6, original.size());
-        assertEquals("{null=abc, 3=3value, B=Bvalue, a=avalue, c=cvalue, 
d=dvalue}", original.toString());
-    }
-
-    @Test
-    public void testNullKeysCopiedToAsMap() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue");
-        assertEquals(5, original.size());
-
-        final HashMap<String, String> expected = new HashMap<>();
-        expected.put("a", "avalue");
-        expected.put("B", "Bvalue");
-        expected.put("3", "3value");
-        expected.put("c", "cvalue");
-        expected.put("d", "dvalue");
-        assertEquals("initial", expected, original.toMap());
-
-        original.putValue(null, "nullvalue");
-        expected.put(null, "nullvalue");
-        assertEquals(6, original.size());
-        assertEquals("with null key", expected, original.toMap());
-
-        original.putValue(null, "otherNullvalue");
-        expected.put(null, "otherNullvalue");
-        assertEquals(6, original.size());
-        assertEquals("with null key value2", expected, original.toMap());
-
-        original.putValue(null, "nullvalue");
-        expected.put(null, "nullvalue");
-        assertEquals(6, original.size());
-        assertEquals("with null key value1 again", expected, original.toMap());
-
-        original.putValue(null, "abc");
-        expected.put(null, "abc");
-        assertEquals(6, original.size());
-        assertEquals("with null key value3", expected, original.toMap());
-    }
-
-    @Test
-    public void testRemove() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        assertEquals(1, original.size());
-        assertEquals("avalue", original.getValue("a"));
-
-        original.remove("a");
-        assertEquals(0, original.size());
-        assertNull("no a val", original.getValue("a"));
-
-        original.remove("B");
-        assertEquals(0, original.size());
-        assertNull("no B val", original.getValue("B"));
-    }
-
-    @Test
-    public void testRemoveNullsOutRemovedSlot() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("b", "bvalue");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue");
-        original.remove("a");
-        original.remove("b");
-        original.remove("c");
-        original.remove("d");
-        assertNull(original.getValueAt(0));
-
-        // ensure slots in the values array are nulled out
-        final Field f = SortedStringArrayMap.class.getDeclaredField("values");
-        f.setAccessible(true);
-        final Object[] values = (Object[]) f.get(original);
-        for (int i = 0; i < values.length; i++) {
-            assertNull(values[i]);
-        }
-    }
-
-    @Test
-    public void testRemoveWhenFull() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("b", "bvalue");
-        original.putValue("c", "cvalue");
-        original.putValue("d", "dvalue"); // default capacity = 4
-        original.remove("d");
-    }
-
-    @Test
-    public void testNullValuesArePreserved() {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        assertEquals(1, original.size());
-        assertEquals("avalue", original.getValue("a"));
-
-        original.putValue("a", null);
-        assertEquals(1, original.size());
-        assertNull("no a val", original.getValue("a"));
-
-        original.putValue("B", null);
-        assertEquals(2, original.size());
-        assertNull("no B val", original.getValue("B"));
-    }
-
-    @Test
-    public void testGet() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        assertEquals("avalue", original.getValue("a"));
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("3value", original.getValue("3"));
-
-        original.putValue("0", "0value");
-        assertEquals("0value", original.getValue("0"));
-        assertEquals("3value", original.getValue("3"));
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("avalue", original.getValue("a"));
-    }
-
-    @Test
-    public void testGetValue_GetValueAt() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        assertEquals("avalue", original.getValue("a"));
-        assertEquals("avalue", original.getValueAt(2));
-
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("Bvalue", original.getValueAt(1));
-
-        assertEquals("3value", original.getValue("3"));
-        assertEquals("3value", original.getValueAt(0));
-
-        original.putValue("0", "0value");
-        assertEquals("0value", original.getValue("0"));
-        assertEquals("0value", original.getValueAt(0));
-        assertEquals("3value", original.getValue("3"));
-        assertEquals("3value", original.getValueAt(1));
-        assertEquals("Bvalue", original.getValue("B"));
-        assertEquals("Bvalue", original.getValueAt(2));
-        assertEquals("avalue", original.getValue("a"));
-        assertEquals("avalue", original.getValueAt(3));
-    }
-
-    @Test
-    public void testClear() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-        assertEquals(3, original.size());
-
-        original.clear();
-        assertEquals(0, original.size());
-
-        // ensure slots in the values array are nulled out
-        final Field f = SortedStringArrayMap.class.getDeclaredField("values");
-        f.setAccessible(true);
-        final Object[] values = (Object[]) f.get(original);
-        for (int i = 0; i < values.length; i++) {
-            assertNull(values[i]);
-        }
-    }
-
-    @Test
-    public void testIndexOfKey() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        assertEquals(0, original.indexOfKey("a"));
-
-        original.putValue("B", "Bvalue");
-        assertEquals(1, original.indexOfKey("a"));
-        assertEquals(0, original.indexOfKey("B"));
-
-        original.putValue("3", "3value");
-        assertEquals(2, original.indexOfKey("a"));
-        assertEquals(1, original.indexOfKey("B"));
-        assertEquals(0, original.indexOfKey("3"));
-
-        original.putValue("A", "AAA");
-        assertEquals(3, original.indexOfKey("a"));
-        assertEquals(2, original.indexOfKey("B"));
-        assertEquals(1, original.indexOfKey("A"));
-        assertEquals(0, original.indexOfKey("3"));
-
-        original.putValue("C", "CCC");
-        assertEquals(4, original.indexOfKey("a"));
-        assertEquals(3, original.indexOfKey("C"));
-        assertEquals(2, original.indexOfKey("B"));
-        assertEquals(1, original.indexOfKey("A"));
-        assertEquals(0, original.indexOfKey("3"));
-
-        original.putValue("2", "222");
-        assertEquals(5, original.indexOfKey("a"));
-        assertEquals(4, original.indexOfKey("C"));
-        assertEquals(3, original.indexOfKey("B"));
-        assertEquals(2, original.indexOfKey("A"));
-        assertEquals(1, original.indexOfKey("3"));
-        assertEquals(0, original.indexOfKey("2"));
-    }
-
-    @Test
-    public void testContainsKey() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        assertFalse("a", original.containsKey("a"));
-        assertFalse("B", original.containsKey("B"));
-        assertFalse("3", original.containsKey("3"));
-        assertFalse("A", original.containsKey("A"));
-
-        original.putValue("a", "avalue");
-        assertTrue("a", original.containsKey("a"));
-        assertFalse("B", original.containsKey("B"));
-        assertFalse("3", original.containsKey("3"));
-        assertFalse("A", original.containsKey("A"));
-
-        original.putValue("B", "Bvalue");
-        assertTrue("a", original.containsKey("a"));
-        assertTrue("B", original.containsKey("B"));
-        assertFalse("3", original.containsKey("3"));
-        assertFalse("A", original.containsKey("A"));
-
-        original.putValue("3", "3value");
-        assertTrue("a", original.containsKey("a"));
-        assertTrue("B", original.containsKey("B"));
-        assertTrue("3", original.containsKey("3"));
-        assertFalse("A", original.containsKey("A"));
-
-        original.putValue("A", "AAA");
-        assertTrue("a", original.containsKey("a"));
-        assertTrue("B", original.containsKey("B"));
-        assertTrue("3", original.containsKey("3"));
-        assertTrue("A", original.containsKey("A"));
-    }
-
-    @Test
-    public void testGetValueAt() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        assertEquals("a", original.getKeyAt(0));
-        assertEquals("avalue", original.getValueAt(0));
-
-        original.putValue("B", "Bvalue");
-        assertEquals("B", original.getKeyAt(0));
-        assertEquals("Bvalue", original.getValueAt(0));
-        assertEquals("a", original.getKeyAt(1));
-        assertEquals("avalue", original.getValueAt(1));
-
-        original.putValue("3", "3value");
-        assertEquals("3", original.getKeyAt(0));
-        assertEquals("3value", original.getValueAt(0));
-        assertEquals("B", original.getKeyAt(1));
-        assertEquals("Bvalue", original.getValueAt(1));
-        assertEquals("a", original.getKeyAt(2));
-        assertEquals("avalue", original.getValueAt(2));
-    }
-
-    @Test
-    public void testSizeAndIsEmpty() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        assertEquals(0, original.size());
-        assertTrue("initial", original.isEmpty());
-
-        original.putValue("a", "avalue");
-        assertEquals(1, original.size());
-        assertFalse("size=" + original.size(), original.isEmpty());
-
-        original.putValue("B", "Bvalue");
-        assertEquals(2, original.size());
-        assertFalse("size=" + original.size(), original.isEmpty());
-
-        original.putValue("3", "3value");
-        assertEquals(3, original.size());
-        assertFalse("size=" + original.size(), original.isEmpty());
-
-        original.remove("B");
-        assertEquals(2, original.size());
-        assertFalse("size=" + original.size(), original.isEmpty());
-
-        original.remove("3");
-        assertEquals(1, original.size());
-        assertFalse("size=" + original.size(), original.isEmpty());
-
-        original.remove("a");
-        assertEquals(0, original.size());
-        assertTrue("size=" + original.size(), original.isEmpty());
-    }
-
-    @Test
-    public void testForEachBiConsumer() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        original.forEach(new BiConsumer<String, String>() {
-            int count = 0;
-            @Override
-            public void accept(final String key, final String value) {
-                assertEquals("key", key, original.getKeyAt(count));
-                assertEquals("val", value, original.getValueAt(count));
-                count++;
-                assertTrue("count should not exceed size but was " + count, 
count <= original.size());
-            }
-        });
-    }
-
-    static class State {
-        SortedStringArrayMap data;
-        int count;
-    }
-    static TriConsumer<String, String, State> COUNTER = new 
TriConsumer<String, String, State>() {
-        @Override
-        public void accept(final String key, final String value, final State 
state) {
-            assertEquals("key", key, state.data.getKeyAt(state.count));
-            assertEquals("val", value, state.data.getValueAt(state.count));
-            state.count++;
-            assertTrue("count should not exceed size but was " + state.count,
-                    state.count <= state.data.size());
-        }
-    };
-
-    @Test
-    public void testForEachTriConsumer() throws Exception {
-        final SortedStringArrayMap original = new SortedStringArrayMap();
-        original.putValue("a", "avalue");
-        original.putValue("B", "Bvalue");
-        original.putValue("3", "3value");
-
-        final State state = new State();
-        state.data = original;
-        original.forEach(COUNTER, state);
-        assertEquals(state.count, original.size());
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
index 8577fa1..dddbc7f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/AbstractLogEvent.java
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.ThreadContext.ContextStack;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 
 /**
@@ -36,7 +36,7 @@ public abstract class AbstractLogEvent implements LogEvent {
     private static final long serialVersionUID = 1L;
 
     @Override
-    public ContextData getContextData() {
+    public ReadOnlyStringMap getContextData() {
         return null;
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/ContextDataInjector.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/ContextDataInjector.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/ContextDataInjector.java
index b17a5a0..584910c 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/ContextDataInjector.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/ContextDataInjector.java
@@ -21,11 +21,11 @@ import java.util.List;
 import org.apache.logging.log4j.core.config.Property;
 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
 import org.apache.logging.log4j.core.impl.ThreadContextDataInjector;
-import org.apache.logging.log4j.util.ContextData;
-import org.apache.logging.log4j.util.MutableContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
+import org.apache.logging.log4j.util.StringMap;
 
 /**
- * Responsible for initializing the ContextData of LogEvents. Context data is 
data that is set by the application to be
+ * Responsible for initializing the context data of LogEvents. Context data is 
data that is set by the application to be
  * included in all subsequent log events.
  * <p>
  * The source of the context data is implementation-specific. The default 
source for context data is the ThreadContext.
@@ -45,7 +45,7 @@ import org.apache.logging.log4j.util.MutableContextData;
  * guarantees to enable optimal performance.
  * </p>
  *
- * @see ContextData
+ * @see ReadOnlyStringMap
  * @see ContextDataInjectorFactory
  * @see org.apache.logging.log4j.ThreadContext
  * @see ThreadContextDataInjector
@@ -53,7 +53,7 @@ import org.apache.logging.log4j.util.MutableContextData;
  */
 public interface ContextDataInjector {
     /**
-     * Returns a {@code MutableContextData} object initialized with the 
specified properties and the appropriate
+     * Returns a {@code StringMap} object initialized with the specified 
properties and the appropriate
      * context data. The returned value may be the specified parameter or a 
different object.
      * <p>
      * This method will be called for each log event to initialize its context 
data and implementors should take
@@ -66,10 +66,10 @@ public interface ContextDataInjector {
      * Example implementation:
      * </p>
      * <pre>
-     * public MutableContextData injectContextData(List<Property> properties, 
MutableContextData reusable) {
+     * public StringMap injectContextData(List<Property> properties, StringMap 
reusable) {
      *     if (properties == null || properties.isEmpty()) {
      *         // assume context data is stored in a copy-on-write data 
structure that is safe to pass to another thread
-     *         return (MutableContextData) rawContextData();
+     *         return (StringMap) rawContextData();
      *     }
      *     // first copy configuration properties into the result
      *     ThreadContextDataInjector.copyProperties(properties, reusable);
@@ -80,17 +80,17 @@ public interface ContextDataInjector {
      * }
      * </pre>
      *
-     * @param properties Properties from the log4j configuration to be added 
to the resulting ContextData. May be
+     * @param properties Properties from the log4j configuration to be added 
to the resulting ReadOnlyStringMap. May be
      *          {@code null} or empty
-     * @param reusable a {@code MutableContextData} instance that may be 
reused to avoid creating temporary objects
-     * @return a {@code MutableContextData} instance initialized with the 
specified properties and the appropriate
+     * @param reusable a {@code StringMap} instance that may be reused to 
avoid creating temporary objects
+     * @return a {@code StringMap} instance initialized with the specified 
properties and the appropriate
      *          context data. The returned value may be the specified 
parameter or a different object.
-     * @see ThreadContextDataInjector#copyProperties(List, MutableContextData)
+     * @see ThreadContextDataInjector#copyProperties(List, StringMap)
      */
-    MutableContextData injectContextData(final List<Property> properties, 
final MutableContextData reusable);
+    StringMap injectContextData(final List<Property> properties, final 
StringMap reusable);
 
     /**
-     * Returns a {@code ContextData} object reflecting the current state of 
the context. Configuration properties
+     * Returns a {@code ReadOnlyStringMap} object reflecting the current state 
of the context. Configuration properties
      * are not included in the result.
      * <p>
      * This method may be called multiple times for each log event by Filters 
and Lookups and implementors should take
@@ -101,7 +101,7 @@ public interface ContextDataInjector {
      * underlying context may or may not be reflected in the returned object, 
depending on the context data source and
      * the implementation of this method. It is not safe to pass the returned 
object to another thread.
      * </p>
-     * @return a {@code ContextData} object reflecting the current state of 
the context
+     * @return a {@code ReadOnlyStringMap} object reflecting the current state 
of the context
      */
-    ContextData rawContextData();
+    ReadOnlyStringMap rawContextData();
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
index 892a692..77523ba 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
@@ -25,7 +25,7 @@ import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 /**
  * Provides contextual information about a logged message. A LogEvent must be 
{@link java.io.Serializable} so that it
@@ -58,11 +58,11 @@ public interface LogEvent extends Serializable {
     Map<String, String> getContextMap();
 
     /**
-     * Returns the {@code ContextData} object holding context key-value pairs.
-     * @return the {@code ContextData} object holding context key-value pairs
+     * Returns the {@code ReadOnlyStringMap} object holding context data 
key-value pairs.
+     * @return the {@code ReadOnlyStringMap} object holding context data 
key-value pairs
      * @since 2.7
      */
-    ContextData getContextData();
+    ReadOnlyStringMap getContextData();
 
     /**
      * Gets the context stack (also known as Nested Diagnostic Context or NDC).

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
index 5d40548..9485fdb 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/AbstractLogEventWrapperEntity.java
@@ -26,7 +26,7 @@ import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.AbstractLogEvent;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.core.LogEvent;
 import 
org.apache.logging.log4j.core.appender.db.jpa.converter.ContextDataAttributeConverter;
 import org.apache.logging.log4j.message.Message;
@@ -223,7 +223,7 @@ public abstract class AbstractLogEventWrapperEntity 
implements LogEvent {
      * @param contextData Ignored.
      */
     @SuppressWarnings("unused")
-    public void setContextData(final ContextData contextData) {
+    public void setContextData(final ReadOnlyStringMap contextData) {
         // this entity is write-only
     }
 
@@ -292,7 +292,7 @@ public abstract class AbstractLogEventWrapperEntity 
implements LogEvent {
     }
 
     /**
-     * Gets the context map. Transient, since the String version of the data 
is obtained via ContextMap.
+     * Gets the context map. Transient, since the String version of the data 
is obtained via ReadOnlyStringMap.
      *
      * @return the context data.
      * @see ContextDataAttributeConverter
@@ -301,7 +301,7 @@ public abstract class AbstractLogEventWrapperEntity 
implements LogEvent {
     @Override
     @Transient
     //@Convert(converter = ContextDataAttributeConverter.class)
-    public ContextData getContextData() {
+    public ReadOnlyStringMap getContextData() {
         return this.getWrappedEvent().getContextData();
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverter.java
index fdffe10..ede6706 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataAttributeConverter.java
@@ -19,19 +19,19 @@ package 
org.apache.logging.log4j.core.appender.db.jpa.converter;
 import javax.persistence.AttributeConverter;
 import javax.persistence.Converter;
 
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 /**
- * A JPA 2.1 attribute converter for {@link ContextData 
ContextData&lt;Object&gt;}s in
+ * A JPA 2.1 attribute converter for {@link ReadOnlyStringMap}s in
  * {@link org.apache.logging.log4j.core.LogEvent}s. This converter is only 
capable of converting to {@link String}s. The
  * {@link #convertToEntityAttribute(String)} method throws an {@link 
UnsupportedOperationException}. If you need to
  * support converting to an entity attribute, you should use the {@link 
ContextMapJsonAttributeConverter} for conversion
  * both ways.
  */
 @Converter(autoApply = false)
-public class ContextDataAttributeConverter implements 
AttributeConverter<ContextData, String> {
+public class ContextDataAttributeConverter implements 
AttributeConverter<ReadOnlyStringMap, String> {
     @Override
-    public String convertToDatabaseColumn(final ContextData contextData) {
+    public String convertToDatabaseColumn(final ReadOnlyStringMap contextData) 
{
         if (contextData == null) {
             return null;
         }
@@ -40,7 +40,7 @@ public class ContextDataAttributeConverter implements 
AttributeConverter<Context
     }
 
     @Override
-    public ContextData convertToEntityAttribute(final String s) {
+    public ReadOnlyStringMap convertToEntityAttribute(final String s) {
         throw new UnsupportedOperationException("Log events can only be 
persisted, not extracted.");
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverter.java
index 71ab47a..b6c57ed 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/db/jpa/converter/ContextDataJsonAttributeConverter.java
@@ -23,9 +23,9 @@ import javax.persistence.AttributeConverter;
 import javax.persistence.Converter;
 import javax.persistence.PersistenceException;
 
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.core.impl.ContextDataFactory;
-import org.apache.logging.log4j.util.MutableContextData;
+import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.util.BiConsumer;
 import org.apache.logging.log4j.util.Strings;
 
@@ -35,7 +35,7 @@ import com.fasterxml.jackson.databind.node.JsonNodeFactory;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
 /**
- * A JPA 2.1 attribute converter for {@link ContextData 
ContextData&lt;Object&gt;}s in
+ * A JPA 2.1 attribute converter for {@link ReadOnlyStringMap}s in
  * {@link org.apache.logging.log4j.core.LogEvent}s. This converter is capable 
of converting both to and from
  * {@link String}s.
  *
@@ -43,11 +43,11 @@ import com.fasterxml.jackson.databind.node.ObjectNode;
  * Processor.
  */
 @Converter(autoApply = false)
-public class ContextDataJsonAttributeConverter implements 
AttributeConverter<ContextData, String> {
+public class ContextDataJsonAttributeConverter implements 
AttributeConverter<ReadOnlyStringMap, String> {
     static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
 
     @Override
-    public String convertToDatabaseColumn(final ContextData contextData) {
+    public String convertToDatabaseColumn(final ReadOnlyStringMap contextData) 
{
         if (contextData == null) {
             return null;
         }
@@ -69,12 +69,12 @@ public class ContextDataJsonAttributeConverter implements 
AttributeConverter<Con
     }
 
     @Override
-    public ContextData convertToEntityAttribute(final String s) {
+    public ReadOnlyStringMap convertToEntityAttribute(final String s) {
         if (Strings.isEmpty(s)) {
             return null;
         }
         try {
-            final MutableContextData result = 
ContextDataFactory.createContextData();
+            final StringMap result = ContextDataFactory.createContextData();
             final ObjectNode root = (ObjectNode) OBJECT_MAPPER.readTree(s);
             final Iterator<Map.Entry<String, JsonNode>> entries = 
root.fields();
             while (entries.hasNext()) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
index b89b797..45fa666 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/AsyncLogger.java
@@ -38,7 +38,7 @@ import org.apache.logging.log4j.core.util.NanoClock;
 import org.apache.logging.log4j.message.Message;
 import org.apache.logging.log4j.message.MessageFactory;
 import org.apache.logging.log4j.message.ReusableMessage;
-import org.apache.logging.log4j.util.MutableContextData;
+import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.status.StatusLogger;
 
 import com.lmax.disruptor.EventTranslatorVararg;
@@ -275,7 +275,7 @@ public class AsyncLogger extends Logger implements 
EventTranslatorVararg<RingBuf
         event.setValues(asyncLogger, asyncLogger.getName(), marker, fqcn, 
level, message, thrown,
                 // config properties are taken care of in the EventHandler 
thread
                 // in the AsyncLogger#actualAsyncLog method
-                CONTEXT_DATA_INJECTOR.injectContextData(null, 
(MutableContextData) event.getContextData()),
+                CONTEXT_DATA_INJECTOR.injectContextData(null, (StringMap) 
event.getContextData()),
                 contextStack, currentThread.getId(), threadName, 
currentThread.getPriority(), location,
                 CLOCK.currentTimeMillis(), nanoClock.nanoTime());
     }
@@ -308,9 +308,9 @@ public class AsyncLogger extends Logger implements 
EventTranslatorVararg<RingBuf
         final List<Property> properties = 
privateConfig.loggerConfig.getPropertyList();
 
         if (properties != null) {
-            MutableContextData contextData = (MutableContextData) 
event.getContextData();
+            StringMap contextData = (StringMap) event.getContextData();
             if (contextData.isFrozen()) {
-                final MutableContextData temp = 
ContextDataFactory.createContextData();
+                final StringMap temp = ContextDataFactory.createContextData();
                 temp.putAll(contextData);
                 contextData = temp;
             }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
index 44bc766..48f89b3 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEvent.java
@@ -23,11 +23,11 @@ import java.util.Map;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext.ContextStack;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.impl.ContextDataFactory;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
-import org.apache.logging.log4j.util.MutableContextData;
+import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.core.util.Constants;
 import org.apache.logging.log4j.message.Message;
@@ -82,7 +82,7 @@ public class RingBufferLogEvent implements LogEvent, 
ReusableMessage, CharSequen
     private Object[] parameters;
     private transient Throwable thrown;
     private ThrowableProxy thrownProxy;
-    private MutableContextData contextData = 
ContextDataFactory.createContextData();
+    private StringMap contextData = ContextDataFactory.createContextData();
     private Marker marker;
     private String fqcn;
     private StackTraceElement location;
@@ -92,7 +92,7 @@ public class RingBufferLogEvent implements LogEvent, 
ReusableMessage, CharSequen
 
     public void setValues(final AsyncLogger anAsyncLogger, final String 
aLoggerName, final Marker aMarker,
             final String theFqcn, final Level aLevel, final Message msg, final 
Throwable aThrowable,
-            final MutableContextData mutableContextData, final ContextStack 
aContextStack, final long threadId,
+            final StringMap mutableContextData, final ContextStack 
aContextStack, final long threadId,
             final String threadName, final int threadPriority, final 
StackTraceElement aLocation,
             final long aCurrentTimeMillis, final long aNanoTime) {
         this.threadPriority = threadPriority;
@@ -324,11 +324,11 @@ public class RingBufferLogEvent implements LogEvent, 
ReusableMessage, CharSequen
 
     @SuppressWarnings("unchecked")
     @Override
-    public ContextData getContextData() {
+    public ReadOnlyStringMap getContextData() {
         return contextData;
     }
 
-    void setContextData(final MutableContextData contextData) {
+    void setContextData(final StringMap contextData) {
         this.contextData = contextData;
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
index d85b7c5..d612bb4 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/async/RingBufferLogEventTranslator.java
@@ -21,7 +21,7 @@ import org.apache.logging.log4j.Marker;
 import org.apache.logging.log4j.ThreadContext.ContextStack;
 import org.apache.logging.log4j.core.ContextDataInjector;
 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
-import org.apache.logging.log4j.util.MutableContextData;
+import org.apache.logging.log4j.util.StringMap;
 import org.apache.logging.log4j.message.Message;
 
 import com.lmax.disruptor.EventTranslator;
@@ -58,7 +58,7 @@ public class RingBufferLogEventTranslator implements
         event.setValues(asyncLogger, loggerName, marker, fqcn, level, message, 
thrown,
                 // config properties are taken care of in the EventHandler 
thread
                 // in the AsyncLogger#actualAsyncLog method
-                injector.injectContextData(null, (MutableContextData) 
event.getContextData()), contextStack,
+                injector.injectContextData(null, (StringMap) 
event.getContextData()), contextStack,
                 threadId, threadName, threadPriority, location, 
currentTimeMillis, nanoTime);
 
         clear(); // clear the translator

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
index aec0937..b3a3498 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/DynamicThresholdFilter.java
@@ -35,7 +35,7 @@ import org.apache.logging.log4j.core.ContextDataInjector;
 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 /**
  * Compares against a log level that is associated with a context value. By 
default the context is the
@@ -119,7 +119,7 @@ public final class DynamicThresholdFilter extends 
AbstractFilter {
         return true;
     }
 
-    private Result filter(final Level level, final ContextData contextMap) {
+    private Result filter(final Level level, final ReadOnlyStringMap 
contextMap) {
         final String value = contextMap.getValue(key);
         if (value != null) {
             Level ctxLevel = levelMap.get(value);
@@ -155,7 +155,7 @@ public final class DynamicThresholdFilter extends 
AbstractFilter {
         return filter(level, currentContextData());
     }
 
-    private ContextData currentContextData() {
+    private ReadOnlyStringMap currentContextData() {
         return injector.rawContextData();
     }
 

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
index d112327..d8b8f00 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/MapFilter.java
@@ -35,7 +35,7 @@ import 
org.apache.logging.log4j.core.config.plugins.PluginFactory;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.MapMessage;
 import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 /**
  * A Filter that operates on a Map.
@@ -85,7 +85,7 @@ public class MapFilter extends AbstractFilter {
         return match;
     }
 
-    protected boolean filter(final ContextData data) {
+    protected boolean filter(final ReadOnlyStringMap data) {
         boolean match = false;
         for (final Map.Entry<String, List<String>> entry : map.entrySet()) {
             final String toMatch = data.getValue(entry.getKey());

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/800db9c7/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
index 0a9d862..a5e5cf8 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
@@ -37,7 +37,7 @@ import org.apache.logging.log4j.core.ContextDataInjector;
 import org.apache.logging.log4j.core.impl.ContextDataInjectorFactory;
 import org.apache.logging.log4j.core.util.KeyValuePair;
 import org.apache.logging.log4j.message.Message;
-import org.apache.logging.log4j.util.ContextData;
+import org.apache.logging.log4j.util.ReadOnlyStringMap;
 
 /**
  * Filter based on a value in the Thread Context Map (MDC).
@@ -95,7 +95,7 @@ public class ThreadContextMapFilter extends MapFilter {
     private Result filter() {
         boolean match = false;
         if (useMap) {
-            ContextData currentContextData = null;
+            ReadOnlyStringMap currentContextData = null;
             for (final Map.Entry<String, List<String>> entry : 
getMap().entrySet()) {
                 if (currentContextData == null) {
                     currentContextData = currentContextData();
@@ -112,7 +112,7 @@ public class ThreadContextMapFilter extends MapFilter {
         return match ? onMatch : onMismatch;
     }
 
-    private ContextData currentContextData() {
+    private ReadOnlyStringMap currentContextData() {
         return injector.rawContextData();
     }
 

Reply via email to