You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by rg...@apache.org on 2012/09/25 04:44:49 UTC

svn commit: r1389690 - in /logging/log4j/log4j2/trunk: api/src/main/java/org/apache/logging/log4j/ api/src/main/java/org/apache/logging/log4j/message/ core/src/main/java/org/apache/logging/log4j/core/ core/src/main/java/org/apache/logging/log4j/core/im...

Author: rgoers
Date: Tue Sep 25 02:44:48 2012
New Revision: 1389690

URL: http://svn.apache.org/viewvc?rev=1389690&view=rev
Log:
Log4J2-83 and Log4J2-84 - Set the Context Map and Context Stack to null in the LogEvent if they are empty.

Modified:
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java
    logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
    logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
    logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java
    logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java
    logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/NDC.java
    logging/log4j/log4j2/trunk/src/changes/changes.xml

Modified: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/ThreadContext.java Tue Sep 25 02:44:48 2012
@@ -17,10 +17,13 @@
 
 package org.apache.logging.log4j;
 
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
-import java.util.Stack;
-
+import java.util.NoSuchElementException;
 
 /**
  * The ThreadContext allows applications to store information either in a Map
@@ -31,6 +34,16 @@ import java.util.Stack;
  */
 public final class ThreadContext {
 
+    /**
+     * Empty, immutable Map.
+     */
+    public static final Map<String, String> EMPTY_MAP = new ImmutableMap();
+
+    /**
+     * Empty, immutable ContextStack.
+     */
+    public static final ContextStack EMPTY_STACK = new ImmutableStack();
+
     private static ThreadLocal<Map<String, String>> localMap =
         new InheritableThreadLocal<Map<String, String>>() {
             protected Map<String, String> childValue(Map<String, String> parentValue) {
@@ -38,14 +51,7 @@ public final class ThreadContext {
             }
         };
 
-    private static ThreadLocal<Stack<String>> localStack =
-        new InheritableThreadLocal<Stack<String>>() {
-            protected Stack<String> childValue(Stack<String> parentValue) {
-                return parentValue == null ? null : (Stack<String>) parentValue.clone();
-            }
-        };
-
-
+    private static ThreadLocal<ContextStack> localStack = new ThreadLocal<ContextStack>();
 
     private ThreadContext() {
 
@@ -112,13 +118,30 @@ public final class ThreadContext {
     }
 
     /**
-     * Get the current thread's MDC as a hashtable. This method is
-     * intended to be used internally.
+     * Get a copy of current thread's context Map.
      * @return a copy of the context.
      */
     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());
+        return map == null ? new HashMap<String, String>() : new HashMap<String, String>(map);
+    }
+
+    /**
+     * Get an immutable copy of the current thread's context Map.
+     * @return An immutable copy of the ThreadContext Map.
+     */
+    public static Map<String, String> getImmutableContext() {
+        Map<String, String> map = localMap.get();
+        return map == null ? new ImmutableMap() : new ImmutableMap(map);
+    }
+
+    /**
+     * Return true if the Map is empty.
+     * @return true if the Map is empty, false otherwise.
+     */
+    public static boolean isEmpty() {
+        Map<String, String> map = localMap.get();
+        return map == null || map.size() == 0;
     }
 
     /**
@@ -132,28 +155,40 @@ public final class ThreadContext {
      * Return a copy of this thread's stack.
      * @return A copy of this thread's stack.
      */
-    public static Stack<String> cloneStack() {
-        Stack<String> stack = localStack.get();
-        return stack == null ? new Stack<String>() : (Stack<String>) stack.clone();
+    public static ContextStack cloneStack() {
+        ContextStack stack = localStack.get();
+        return stack == null ? new ThreadContextStack() : new ThreadContextStack(stack.asList());
+    }
+
+    /**
+     * Get an immutable copy of this current thread's context stack.
+     * @return an immutable copy of the ThreadContext stack.
+     */
+    public static ContextStack getImmutableStack() {
+        ContextStack stack = localStack.get();
+        return stack == null ? EMPTY_STACK : new ImmutableStack(stack.asList());
     }
 
     /**
      * Set this thread's stack.
      * @param stack The stack to use.
      */
-    public static void setStack(Stack<String> stack) {
-        localStack.set(stack);
+    public static void setStack(Collection<String> stack) {
+        if (stack.size() == 0) {
+            return;
+        }
+        localStack.set(new ThreadContextStack(stack));
     }
 
     /**
      * Get the current nesting depth of this thread's stack.
      * @return the number of items in the stack.
      *
-     * @see #setMaxDepth
+     * @see #trim
      */
     public static int getDepth() {
-        Stack<String> stack = localStack.get();
-        return stack == null ? 0 : stack.size();
+        ContextStack stack = localStack.get();
+        return stack == null ? 0 : stack.getDepth();
     }
 
     /**
@@ -165,8 +200,8 @@ public final class ThreadContext {
      * @return String The innermost diagnostic context.
      */
     public static String pop() {
-        Stack<String> s = localStack.get();
-        if (s == null || s.isEmpty()) {
+        ContextStack s = localStack.get();
+        if (s == null || s.getDepth() == 0) {
             return "";
         }
         return s.pop();
@@ -182,8 +217,8 @@ public final class ThreadContext {
      * @return String The innermost diagnostic context.
      */
     public static String peek() {
-        Stack<String> s = localStack.get();
-        if (s == null || s.isEmpty()) {
+        ContextStack s = localStack.get();
+        if (s == null || s.getDepth() == 0) {
             return "";
         }
         return s.peek();
@@ -198,9 +233,10 @@ public final class ThreadContext {
      * @param message The new diagnostic context information.
      */
     public static void push(String message) {
-        Stack<String> stack = localStack.get();
+        ContextStack stack = localStack.get();
         if (stack == null) {
-            stack = new Stack<String>();
+            stack = new ThreadContextStack();
+            localStack.set(stack);
         }
         stack.push(message);
     }
@@ -228,24 +264,25 @@ public final class ThreadContext {
     }
 
     /**
-     * Set maximum depth of this diagnostic context. If the current
+     * Trims elements from this diagnostic context. If the current
      * depth is smaller or equal to <code>maxDepth</code>, then no
-     * action is taken.
+     * action is taken. If the current depth is larger than newDepth
+     * then all elements at maxDepth or higher are discarded.
      * <p/>
      * <p>This method is a convenient alternative to multiple {@link
      * #pop} calls. Moreover, it is often the case that at the end of
-     * complex call sequences, the depth of the NDC is
-     * unpredictable. The <code>setMaxDepth</code> method circumvents
+     * complex call sequences, the depth of the ThreadContext is
+     * unpredictable. The <code>trim</code> method circumvents
      * this problem.
      * <p/>
      * <p>For example, the combination
      * <pre>
      * void foo() {
-     * &nbsp;  int depth = NDC.getDepth();
+     * &nbsp;  int depth = ThreadContext.getDepth();
      * <p/>
      * &nbsp;  ... complex sequence of calls
      * <p/>
-     * &nbsp;  NDC.setMaxDepth(depth);
+     * &nbsp;  ThreadContext.trim(depth);
      * }
      * </pre>
      * <p/>
@@ -253,9 +290,190 @@ public final class ThreadContext {
      * diagnostic stack is conserved.
      *
      * @see #getDepth
-     * @param maxDepth The maximum depth of the stack.
+     * @param depth The number of elements to keep.
+     */
+    public static void trim(int depth) {
+        ContextStack stack = localStack.get();
+        if (stack != null) {
+            stack.trim(depth);
+        }
+    }
+
+    /**
+     * The ThreadContext Stack interface.
+     */
+    public interface ContextStack extends Serializable {
+
+        /**
+         * Clears all elements from the stack.
+         */
+        void clear();
+
+        /**
+         * Return the element at the top of the stack.
+         * @return The element at the top of the stack.
+         * @throws java.util.NoSuchElementException if the stack is empty.
+         */
+        String pop();
+
+        /**
+         * Return the element at the top of the stack without removing it or null if the stack is empty.
+         * @return the element at the top of the stack or null if the stack is empty.
+         */
+        String peek();
+
+        /**
+         * Add an element to the stack.
+         * @param message The element to add.
+         */
+        void push(String message);
+
+        /**
+         * Return the number of elements in the stack.
+         * @return the number of elements in the stack.
+         */
+        int getDepth();
+
+        /**
+         * Returns all the elements in the stack in a List.
+         * @return all the elements in the stack in a List.
+         */
+        List<String> asList();
+
+        /**
+         * Trims elements from the end of the stack.
+         * @param depth The maximum number of items in the stack to keep.
+         */
+        void trim(int depth);
+
+        /**
+         * Returns a copy of the ContextStack.
+         * @return a copy of the ContextStack.
+         */
+        ContextStack copy();
+    }
+
+    /**
+     * The ContextStack implementation.
+     */
+    private static class ThreadContextStack extends ArrayList<String> implements ContextStack {
+
+        private static final long serialVersionUID = 5050501L;
+
+        public ThreadContextStack() {
+            super();
+        }
+
+        public ThreadContextStack(Collection<String> collection) {
+            super(collection);
+        }
+
+        public String pop() {
+            int index = size() - 1;
+            if (index >= 0) {
+                String result = get(index);
+                remove(index);
+                return result;
+            }
+            throw new NoSuchElementException("The ThreadContext stack is empty");
+        }
+
+        public String peek() {
+            int index = size() - 1;
+            if (index >= 0) {
+                return get(index);
+            }
+            return null;
+        }
+
+        public void push(String message) {
+            add(message);
+        }
+
+        public int getDepth() {
+            return size();
+        }
+
+        public List<String> asList() {
+            return this;
+        }
+
+        public void trim(int depth) {
+            if (depth < 0) {
+                throw new IllegalArgumentException("Maximum stack depth cannot be negative");
+            }
+            while (size() > depth) {
+                remove(size() - 1);
+            }
+
+        }
+
+        public ContextStack copy() {
+            return new ThreadContextStack(this);
+        }
+    }
+
+    /**
+     * An immutable ContextStack.
      */
-    public static void setMaxDepth(int maxDepth) {
+    private static class ImmutableStack extends ThreadContextStack {
+
+        private static final long serialVersionUID = 5050502L;
 
+        public ImmutableStack() {
+        }
+
+        public ImmutableStack(Collection<String> collection) {
+            super(collection);
+        }
+
+        public ImmutableStack(ThreadContextStack stack) {
+            super(stack);
+        }
+
+        @Override
+        public void push(String message) {
+            throw new UnsupportedOperationException("Stack cannot be modified");
+        }
+
+        @Override
+        public void trim(int depth) {
+            throw new UnsupportedOperationException("Stack cannot be modified");
+        }
+    }
+
+    /**
+     * An immutable Context Map.
+     */
+    private static class ImmutableMap extends HashMap<String, String> {
+        private static final long serialVersionUID = 5050503L;
+
+        public ImmutableMap() {
+            super();
+        }
+
+        public ImmutableMap(Map<String, String> map) {
+            super(map);
+        }
+
+        @Override
+        public String put(String s, String s1) {
+            throw new UnsupportedOperationException("Map cannot be modified");
+        }
+
+        @Override
+        public void putAll(Map<? extends String, ? extends String> map) {
+            throw new UnsupportedOperationException("Map cannot be modified");
+        }
+
+        @Override
+        public String remove(Object o) {
+            throw new UnsupportedOperationException("Map cannot be modified");
+        }
+
+        @Override
+        public void clear() {
+            throw new UnsupportedOperationException("Map cannot be modified");
+        }
     }
 }

Modified: logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java (original)
+++ logging/log4j/log4j2/trunk/api/src/main/java/org/apache/logging/log4j/message/StructuredDataMessage.java Tue Sep 25 02:44:48 2012
@@ -34,6 +34,9 @@ public class StructuredDataMessage exten
 
     private String type;
 
+    /**
+     * Supported formats.
+     */
     public enum Format {
         /** The map should be formatted as XML. */
         XML,

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/LogEvent.java Tue Sep 25 02:44:48 2012
@@ -19,11 +19,11 @@ package org.apache.logging.log4j.core;
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.message.Message;
 
 import java.io.Serializable;
 import java.util.Map;
-import java.util.Stack;
 
 /**
  *
@@ -94,9 +94,9 @@ public interface LogEvent extends Serial
     /**
      * Get the NDC data.
      *
-     * @return A copy of the Nested Diagnostic Context of null;
+     * @return A copy of the Nested Diagnostic Context or null;
      */
-    Stack<String> getContextStack();
+    ThreadContext.ContextStack getContextStack();
 
     /**
      * Returns the fully qualified class name of the caller of the logging api.

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/impl/Log4jLogEvent.java Tue Sep 25 02:44:48 2012
@@ -27,9 +27,7 @@ import org.apache.logging.log4j.message.
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.Serializable;
-import java.util.HashMap;
 import java.util.Map;
-import java.util.Stack;
 
 /**
  * Implementation of a LogEvent.
@@ -46,7 +44,7 @@ public class Log4jLogEvent implements Lo
     private final long timestamp;
     private final ThrowableProxy throwable;
     private final Map<String, String> mdc;
-    private final Stack<String> ndc;
+    private ThreadContext.ContextStack ndc;
     private String threadName = null;
     private StackTraceElement location;
 
@@ -60,8 +58,10 @@ public class Log4jLogEvent implements Lo
      * @param t A Throwable or null.
      */
     public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, Throwable t) {
-        this(loggerName, marker, fqcn, level, message, t, ThreadContext.getContext(), ThreadContext.cloneStack(), null,
-             null, System.currentTimeMillis());
+        this(loggerName, marker, fqcn, level, message, t,
+            ThreadContext.getContext().size() == 0 ? null : ThreadContext.getImmutableContext(),
+            ThreadContext.getDepth() == 0 ? null : ThreadContext.cloneStack(), null,
+            null, System.currentTimeMillis());
     }
 
     /**
@@ -79,8 +79,8 @@ public class Log4jLogEvent implements Lo
      * @param timestamp The timestamp of the event.
      */
     public Log4jLogEvent(String loggerName, Marker marker, String fqcn, Level level, Message message, Throwable t,
-                         Map<String, String> mdc, Stack<String> ndc, String threadName, StackTraceElement location,
-                         long timestamp) {
+                         Map<String, String> mdc, ThreadContext.ContextStack ndc, String threadName,
+                         StackTraceElement location, long timestamp) {
         name = loggerName;
         this.marker = marker;
         this.fqcnOfLogger = fqcn;
@@ -165,21 +165,19 @@ public class Log4jLogEvent implements Lo
     }
 
     /**
-     * @doubt Allows direct access to the map passed into the constructor, would allow appender
-     * or layout to manipulate event as seen by other appenders.
+     * Returns the immutable copy of the ThreadContext Map.
      * @return The context Map.
      */
     public Map<String, String> getContextMap() {
-        return mdc;
+        return mdc == null ? ThreadContext.EMPTY_MAP : mdc;
     }
 
     /**
-     * @doubt Allows direct access to the map passed into the constructor, would allow appender
-     * or layout to manipulate event as seen by other appenders.
+     * Returns an immutable copy of the ThreadContext stack.
      * @return The context Stack.
      */
-    public Stack<String> getContextStack() {
-        return ndc;
+    public ThreadContext.ContextStack getContextStack() {
+        return ndc == null ? ThreadContext.EMPTY_STACK : ndc;
     }
 
     /**
@@ -266,8 +264,8 @@ public class Log4jLogEvent implements Lo
         private final Message message;
         private final long timestamp;
         private final Throwable throwable;
-        private final HashMap<String, String> mdc;
-        private final Stack<String> ndc;
+        private final Map<String, String> mdc;
+        private ThreadContext.ContextStack ndc;
         private String threadName;
         private StackTraceElement location;
 
@@ -279,7 +277,7 @@ public class Log4jLogEvent implements Lo
             this.message = event.message;
             this.timestamp = event.timestamp;
             this.throwable = event.throwable;
-            this.mdc = new HashMap<String, String>(event.mdc);
+            this.mdc = event.mdc;
             this.ndc = event.ndc;
             this.location = event.getSource();
             this.threadName = event.getThreadName();

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/HTMLLayout.java Tue Sep 25 02:44:48 2012
@@ -123,7 +123,7 @@ public final class HTMLLayout extends Ab
         sbuf.append("</td>").append(LINE_SEP);
         sbuf.append("</tr>").append(LINE_SEP);
 
-        if (event.getContextStack().size() > 0) {
+        if (event.getContextStack().getDepth() > 0) {
             sbuf.append("<tr><td bgcolor=\"#EEEEEE\" style=\"font-size : xx-small;\" colspan=\"6\" ");
             sbuf.append("title=\"Nested Diagnostic Context\">");
             sbuf.append("NDC: ").append(Transform.escapeTags(event.getContextStack().toString()));

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/layout/XMLLayout.java Tue Sep 25 02:44:48 2012
@@ -75,12 +75,12 @@ public class XMLLayout extends AbstractS
 
     private static final int DEFAULT_SIZE = 256;
 
+    private static final String[] FORMATS = new String[] {"xml"};
+
     private final boolean locationInfo;
     private final boolean properties;
     private final boolean complete;
 
-    private static final String[] FORMATS = new String[] {"xml"};
-
     protected XMLLayout(boolean locationInfo, boolean properties, boolean complete, Charset charset) {
         super(charset);
         this.locationInfo = locationInfo;
@@ -136,7 +136,7 @@ public class XMLLayout extends AbstractS
             }
         }
 
-        if (event.getContextStack() != null && event.getContextStack().size() > 0) {
+        if (event.getContextStack().getDepth() > 0) {
             buf.append("<log4j:NDC><![CDATA[");
             Transform.appendEscapingCDATA(buf, event.getContextStack().toString());
             buf.append("]]></log4j:NDC>\r\n");

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/MessagePatternConverter.java Tue Sep 25 02:44:48 2012
@@ -46,6 +46,7 @@ public final class MessagePatternConvert
     /**
      * Obtains an instance of pattern converter.
      *
+     * @param config The Configuration.
      * @param options options, may be null.
      * @return instance of pattern converter.
      */

Modified: logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java (original)
+++ logging/log4j/log4j2/trunk/core/src/main/java/org/apache/logging/log4j/core/pattern/PatternParser.java Tue Sep 25 02:44:48 2012
@@ -269,7 +269,8 @@ public final class PatternParser {
                             default:
 
                                 if (currentLiteral.length() != 0) {
-                                    patternConverters.add(new LiteralPatternConverter(config, currentLiteral.toString()));
+                                    patternConverters.add(new LiteralPatternConverter(config,
+                                        currentLiteral.toString()));
                                     formattingInfos.add(FormattingInfo.getDefault());
                                 }
 
@@ -292,12 +293,10 @@ public final class PatternParser {
                             formattingInfo =
                                 new FormattingInfo(true, formattingInfo.getMinLength(),
                                     formattingInfo.getMaxLength());
-
                             break;
 
                         case '.':
                             state = ParserState.DOT_STATE;
-
                             break;
 
                         default:

Modified: logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java (original)
+++ logging/log4j/log4j2/trunk/core/src/test/java/org/apache/logging/log4j/core/lookup/DateLookupTest.java Tue Sep 25 02:44:48 2012
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.lo
 
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.message.Message;
 import org.junit.Test;
@@ -84,7 +85,7 @@ public class DateLookupTest {
             return null;
         }
 
-        public Stack<String> getContextStack() {
+        public ThreadContext.ContextStack getContextStack() {
             return null;
         }
 

Modified: logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java (original)
+++ logging/log4j/log4j2/trunk/flume-ng/src/main/java/org/apache/logging/log4j/flume/appender/FlumeEvent.java Tue Sep 25 02:44:48 2012
@@ -20,6 +20,7 @@ import org.apache.flume.event.SimpleEven
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.LoggingException;
 import org.apache.logging.log4j.Marker;
+import org.apache.logging.log4j.ThreadContext;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.helpers.UUIDUtil;
 import org.apache.logging.log4j.message.MapMessage;
@@ -259,7 +260,7 @@ public class FlumeEvent extends SimpleEv
      * Return a copy of the context stack.
      * @return a copy of the context stack.
      */
-    public Stack<String> getContextStack() {
+    public ThreadContext.ContextStack getContextStack() {
         return event.getContextStack();
     }
 }

Modified: logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/NDC.java
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/NDC.java?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/NDC.java (original)
+++ logging/log4j/log4j2/trunk/log4j12-api/src/main/java/org/apache/log4j/NDC.java Tue Sep 25 02:44:48 2012
@@ -53,7 +53,11 @@ public final class NDC {
      * @return Stack A clone of the current thread's  diagnostic context.
      */
     public static Stack cloneStack() {
-        return org.apache.logging.log4j.ThreadContext.cloneStack();
+        Stack<String> stack = new Stack<String>();
+        for (String element : org.apache.logging.log4j.ThreadContext.cloneStack().asList()) {
+            stack.push(element);
+        }
+        return stack;
     }
 
 
@@ -187,6 +191,6 @@ public final class NDC {
      * @param maxDepth The maximum depth of the stack.
      */
     public static void setMaxDepth(int maxDepth) {
-        org.apache.logging.log4j.ThreadContext.setMaxDepth(maxDepth);
+        org.apache.logging.log4j.ThreadContext.trim(maxDepth);
     }
 }

Modified: logging/log4j/log4j2/trunk/src/changes/changes.xml
URL: http://svn.apache.org/viewvc/logging/log4j/log4j2/trunk/src/changes/changes.xml?rev=1389690&r1=1389689&r2=1389690&view=diff
==============================================================================
--- logging/log4j/log4j2/trunk/src/changes/changes.xml (original)
+++ logging/log4j/log4j2/trunk/src/changes/changes.xml Tue Sep 25 02:44:48 2012
@@ -23,6 +23,16 @@
 
   <body>
     <release version="2.0-beta2" date="TBD" description="Bug fixes and enhancements">
+      <action issue="LOG4J2-84" dev="rgoers" type="fix">
+        If the ThreadContext stack is empty the LogEvent will contain a null value to reduce the overhead of
+        creating log events and in the size of the serialized object. Changed the ThreadContext stack to use
+        a custom stack interface instead of java.util.Stack as that class is overly heavy. This change will
+        cause an API incompatibility.
+      </action>
+      <action issue="LOG4J2-83" dev="rgoers" type="fix">
+        If the ThreadContext map is empty the LogEvent will contain a null value to reduce the overhead of creating
+        log events and in the size of the serialized object.
+      </action>
       <action dev="rgoers" type="add">
         Add getFormats to MultiformatMessage and allow StructuredDataMessage to format as XML.
       </action>