ThreadContext Map and Stack can be removed. Correct places where MDC was returning an Object

git-svn-id: https://svn.apache.org/repos/asf/logging/log4j/branches/BRANCH_2_0_EXPERIMENTAL/rgoers@1178468 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/log4j2-api/src/main/java/org/apache/logging/log4j/ThreadContext.java b/log4j2-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
index 163144e..add7efe 100644
--- a/log4j2-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
+++ b/log4j2-api/src/main/java/org/apache/logging/log4j/ThreadContext.java
@@ -33,21 +33,13 @@
 
     private static ThreadLocal<Map<String, String>> localMap =
         new InheritableThreadLocal<Map<String, String>>() {
-            protected Map<String, String> initialValue() {
-                return new HashMap<String, String>();
-            }
-
             protected Map<String, String> childValue(Map<String, String> parentValue) {
-                return parentValue == null ? new HashMap<String, String>() : new HashMap<String, String>(parentValue);
+                return parentValue == null ? null : new HashMap<String, String>(parentValue);
             }
         };
 
     private static ThreadLocal<Stack<String>> localStack =
         new InheritableThreadLocal<Stack<String>>() {
-            protected Stack<String> initialValue() {
-                return new Stack<String>();
-            }
-
             protected Stack<String> childValue(Stack<String> parentValue) {
                 return parentValue == null ? null : (Stack<String>) parentValue.clone();
             }
@@ -70,7 +62,12 @@
      * @param value The key value.
      */
     public static void put(String key, String value) {
-        localMap.get().put(key, value);
+        Map<String, String> map = localMap.get();
+        if (map == null) {
+            map = new HashMap<String, String>();
+            localMap.set(map);
+        }
+        map.put(key, value);
     }
 
     /**
@@ -81,7 +78,8 @@
      * @return The value associated with the key or null.
      */
     public static String get(String key) {
-        return localMap.get().get(key);
+        Map<String, String> map = localMap.get();
+        return map == null ? null : map.get(key);
     }
 
     /**
@@ -90,14 +88,17 @@
      * @param key The key to remove.
      */
     public static void remove(String key) {
-        localMap.get().remove(key);
+        Map<String, String> map = localMap.get();
+        if (map != null) {
+            map.remove(key);
+        }
     }
 
     /**
      * Clear the context.
      */
     public static void clear() {
-        localMap.get().clear();
+        localMap.remove();
     }
 
     /**
@@ -106,7 +107,8 @@
      * @return True if the key is in the context, false otherwise.
      */
     public static boolean containsKey(String key) {
-        return localMap.get().containsKey(key);
+        Map<String, String> map = localMap.get();
+        return map == null ? false : map.containsKey(key);
     }
 
     /**
@@ -114,15 +116,16 @@
      * intended to be used internally.
      * @return a copy of the context.
      */
-    public static Map<String, Object> getContext() {
-        return new HashMap<String, Object>(localMap.get());
+    public static Map<String, String> getContext() {
+        Map<String, String> map = localMap.get();
+        return map == null ? new HashMap<String, String>() : new HashMap<String, String>(localMap.get());
     }
 
     /**
      * Clear the stack for this thread.
      */
     public static void clearStack() {
-        localStack.get().clear();
+        localStack.remove();
     }
 
     /**
@@ -130,7 +133,8 @@
      * @return A copy of this thread's stack.
      */
     public static Stack<String> cloneStack() {
-        return (Stack<String>) localStack.get().clone();
+        Stack<String> stack = localStack.get();
+        return stack == null ? new Stack<String>() : (Stack<String>) stack.clone();
     }
 
     /**
@@ -148,7 +152,8 @@
      * @see #setMaxDepth
      */
     public static int getDepth() {
-        return localStack.get().size();
+        Stack<String> stack = localStack.get();
+        return stack == null ? 0 : stack.size();
     }
 
     /**
@@ -161,7 +166,7 @@
      */
     public static String pop() {
         Stack<String> s = localStack.get();
-        if (s.isEmpty()) {
+        if (s == null || s.isEmpty()) {
             return "";
         }
         return s.pop();
@@ -177,8 +182,8 @@
      * @return String The innermost diagnostic context.
      */
     public static String peek() {
-         Stack<String> s = localStack.get();
-        if (s.isEmpty()) {
+        Stack<String> s = localStack.get();
+        if (s == null || s.isEmpty()) {
             return "";
         }
         return s.peek();
@@ -193,7 +198,11 @@
      * @param message The new diagnostic context information.
      */
     public static void push(String message) {
-        localStack.get().push(message);
+        Stack<String> stack = localStack.get();
+        if (stack == null) {
+            stack = new Stack<String>();
+        }
+        stack.push(message);
     }
 
     /**
diff --git a/log4j2-api/src/test/java/org/apache/logging/log4j/SimpleLogger.java b/log4j2-api/src/test/java/org/apache/logging/log4j/SimpleLogger.java
index a7266d6..8c54d45 100644
--- a/log4j2-api/src/test/java/org/apache/logging/log4j/SimpleLogger.java
+++ b/log4j2-api/src/test/java/org/apache/logging/log4j/SimpleLogger.java
@@ -42,7 +42,7 @@
         sb.append(level.toString());
         sb.append(" ");
         sb.append(msg.getFormattedMessage());
-        Map<String, Object> mdc = ThreadContext.getContext();
+        Map<String, String> mdc = ThreadContext.getContext();
         if (mdc.size() > 0) {
             sb.append(" ");
             sb.append(mdc.toString());
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
index e18bca1..e5edf0d 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
@@ -91,7 +91,7 @@
      * @doubt as mentioned elsewhere, think MDC and NDC should be combined into a thread context object.
      * (RG) Still to do.
      */
-    Map<String, Object> getContextMap();
+    Map<String, String> getContextMap();
 
     /**
      * Get the NDC data.
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/appender/flume/FlumeEvent.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/appender/flume/FlumeEvent.java
index 97c8a7a..f51ecf7 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/appender/flume/FlumeEvent.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/appender/flume/FlumeEvent.java
@@ -45,7 +45,7 @@
 
     private final String hostname;
 
-    private final Map<String, Object> ctx = new HashMap<String, Object>();
+    private final Map<String, String> ctx = new HashMap<String, String>();
 
     private static final String DEFAULT_MDC_PREFIX = "mdc:";
 
@@ -71,7 +71,7 @@
             eventPrefix = DEFAULT_EVENT_PREFIX;
         }
         this.fields = new HashMap<String, byte[]>();
-        Map<String, Object> mdc = event.getContextMap();
+        Map<String, String> mdc = event.getContextMap();
         if (includes != null) {
             String[] array = includes.split(",");
             if (array.length > 0) {
@@ -85,7 +85,7 @@
             String[] array = excludes.split(",");
             if (array.length > 0) {
                 List<String> list = Arrays.asList(array);
-                for (Map.Entry<String, Object> entry : mdc.entrySet()) {
+                for (Map.Entry<String, String> entry : mdc.entrySet()) {
                     if (!list.contains(entry.getKey())) {
                         ctx.put(entry.getKey(), entry.getValue());
                     }
@@ -114,7 +114,7 @@
             }
         }
 
-        for (Map.Entry<String, Object> entry : ctx.entrySet()) {
+        for (Map.Entry<String, String> entry : ctx.entrySet()) {
             fields.put(mdcPrefix + entry.getKey(), entry.getValue().toString().getBytes());
         }
 
@@ -212,7 +212,7 @@
         return event.getThrown();
     }
 
-    public Map<String, Object> getContextMap() {
+    public Map<String, String> getContextMap() {
         return ctx;
     }
 
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
index c7ab503..83ae7ba 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/filter/ThreadContextMapFilter.java
@@ -73,7 +73,7 @@
 
     @Override
     public Result filter(LogEvent event) {
-        Map<String, Object> ctx = event.getContextMap();
+        Map<String, String> ctx = event.getContextMap();
         boolean match = false;
         for (String key : map.keySet()) {
             match = map.get(key).equals(ctx.get(key));
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
index d3e8425..3f72f00 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
@@ -44,7 +44,7 @@
     private final Message message;
     private final long timestamp;
     private final ThrowableProxy throwable;
-    private final Map<String, Object> mdc;
+    private final Map<String, String> mdc;
     private final Stack<String> ndc;
     private String threadName = null;
     private StackTraceElement location;
@@ -78,7 +78,7 @@
      * @param timestamp The timestamp of the event.
      */
     public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, Throwable t,
-                         Map<String, Object> mdc, Stack<String> ndc, String threadName, StackTraceElement location,
+                         Map<String, String> mdc, Stack<String> ndc, String threadName, StackTraceElement location,
                          long timestamp) {
         name = loggerName;
         this.marker = marker;
@@ -131,7 +131,7 @@
      * @doubt Allows direct access to the map passed into the constructor, would allow appender
      * or layout to manipulate event as seen by other appenders.
      */
-    public Map<String, Object> getContextMap() {
+    public Map<String, String> getContextMap() {
         return mdc;
     }
 
@@ -210,7 +210,7 @@
         private final Message message;
         private final long timestamp;
         private final Throwable throwable;
-        private final HashMap<String, Object> mdc;
+        private final HashMap<String, String> mdc;
         private final Stack<String> ndc;
         private String threadName;
         private StackTraceElement location;
@@ -223,7 +223,7 @@
             this.message = event.message;
             this.timestamp = event.timestamp;
             this.throwable = event.throwable;
-            this.mdc = new HashMap<String, Object>(event.mdc);
+            this.mdc = new HashMap<String, String>(event.mdc);
             this.ndc = event.ndc;
             this.location = event.getSource();
             this.threadName = event.getThreadName();
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
index 73d9749..e0395fd 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/RFC5424Layout.java
@@ -300,7 +300,7 @@
         buf.append(Integer.toString(val));
     }
 
-    private void formatStructuredElement(StructuredDataId id, Map<String, Object> data, StringBuilder sb,
+    private void formatStructuredElement(StructuredDataId id, Map<String, String> data, StringBuilder sb,
                                          ListChecker checker)
     {
         if (id == null && defaultId == null)
@@ -330,19 +330,19 @@
         return sb.toString();
     }
 
-    private void checkRequired(Map<String, Object> map) {
+    private void checkRequired(Map<String, String> map) {
         for (String key : mdcRequired) {
-            Object value = map.get(key);
+            String value = map.get(key);
             if (value == null) {
                 throw new LoggingException("Required key " + key + " is missing from the " + mdcId);
             }
         }
     }
 
-    private void appendMap(Map<String, Object> map, StringBuilder sb, ListChecker checker)
+    private void appendMap(Map<String, String> map, StringBuilder sb, ListChecker checker)
     {
-        SortedMap<String, Object> sorted = new TreeMap<String, Object>(map);
-        for (Map.Entry<String, Object> entry : sorted.entrySet())
+        SortedMap<String, String> sorted = new TreeMap<String, String>(map);
+        for (Map.Entry<String, String> entry : sorted.entrySet())
         {
             if (checker.check(entry.getKey())) {
                 sb.append(" ");
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
index 2a04a13..5fe77b1 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
@@ -144,7 +144,7 @@
 
         if (properties && event.getContextMap().size() > 0) {
             buf.append("<log4j:properties>\r\n");
-            for (Map.Entry<String, Object> entry : event.getContextMap().entrySet()) {
+            for (Map.Entry<String, String> entry : event.getContextMap().entrySet()) {
                 buf.append("<log4j:data name=\"");
                 buf.append(Transform.escapeTags(entry.getKey()));
                 buf.append("\" value=\"");
diff --git a/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/MDCPatternConverter.java b/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/MDCPatternConverter.java
index 93c8c80..e7b2b41 100644
--- a/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/MDCPatternConverter.java
+++ b/log4j2-core/src/main/java/org/apache/logging/log4j/core/pattern/MDCPatternConverter.java
@@ -63,7 +63,7 @@
      * {@inheritDoc}
      */
     public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        Map<String, Object> contextMap = event.getContextMap();
+        Map<String, String> contextMap = event.getContextMap();
         // if there is no additional options, we output every single
         // Key/Value pair for the MDC in a similar format to Hashtable.toString()
         if (key == null) {
diff --git a/slf4j-impl/src/main/java/org/slf4j/helpers/Log4JMDCAdapter.java b/slf4j-impl/src/main/java/org/slf4j/helpers/Log4JMDCAdapter.java
index bb2a4eb..7389efd 100644
--- a/slf4j-impl/src/main/java/org/slf4j/helpers/Log4JMDCAdapter.java
+++ b/slf4j-impl/src/main/java/org/slf4j/helpers/Log4JMDCAdapter.java
@@ -44,13 +44,7 @@
     }
 
     public Map getCopyOfContextMap() {
-        Map<String, Object> ctx = ThreadContext.getContext();
-        Map<String, String> map = new HashMap<String, String>();
-
-        for (Map.Entry<String, Object> entry : ctx.entrySet()) {
-            map.put(entry.getKey(), entry.getValue().toString());
-        }
-        return map;
+        return ThreadContext.getContext();
     }
 
     public void setContextMap(Map map) {