http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AbstractStyleNameConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AbstractStyleNameConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AbstractStyleNameConverter.java
index c15c9fc..5a86560 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AbstractStyleNameConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/AbstractStyleNameConverter.java
@@ -18,6 +18,7 @@ package org.apache.logging.log4j.core.pattern;
 
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
+import java.nio.charset.Charset;
 import java.util.Arrays;
 import java.util.List;
 
@@ -29,7 +30,7 @@ import org.apache.logging.log4j.core.layout.PatternLayout;
 /**
  * Style pattern converter. Adds ANSI color styling to the result of the 
enclosed pattern.
  */
-public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverter /*TODO: implements AnsiConverter*/ {
+public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverter /* TODO: implements AnsiConverter */{
 
     private final List<PatternFormatter> formatters;
 
@@ -42,8 +43,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
      * @param styling The styling that should encapsulate the pattern.
      */
     protected AbstractStyleNameConverter(final String name, final 
List<PatternFormatter> formatters,
-                                         final String styling) {
-        super(name, "style");
+            final String styling, final FormattingInfo formattingInfo) {
+        super(name, "style", formattingInfo);
         this.formatters = formatters;
         this.style = styling;
     }
@@ -64,8 +65,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Black(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Black(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -76,8 +77,9 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Black newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Black.class, NAME, config, options);
+        public static Black newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Black.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -97,8 +99,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Blue(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Blue(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -106,11 +108,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Blue newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Blue.class, NAME, config, options);
+        public static Blue newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Blue.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -130,8 +133,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Cyan(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Cyan(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -139,11 +142,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Cyan newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Cyan.class, NAME, config, options);
+        public static Cyan newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Cyan.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -163,8 +167,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Green(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Green(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -172,11 +176,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Green newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Green.class, NAME, config, options);
+        public static Green newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Green.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -196,8 +201,9 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Magenta(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Magenta(final List<PatternFormatter> formatters, final String 
styling,
+                final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -205,11 +211,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Magenta newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Magenta.class, NAME, config, options);
+        public static Magenta newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Magenta.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -229,8 +236,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Red(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Red(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -238,11 +245,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Red newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Red.class, NAME, config, options);
+        public static Red newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Red.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -262,8 +270,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public White(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public White(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -271,11 +279,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static White newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(White.class, NAME, config, options);
+        public static White newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(White.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -295,8 +304,8 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          * @param formatters The PatternFormatters to generate the text to 
manipulate.
          * @param styling The styling that should encapsulate the pattern.
          */
-        public Yellow(final List<PatternFormatter> formatters, final String 
styling) {
-            super(NAME, formatters, styling);
+        public Yellow(final List<PatternFormatter> formatters, final String 
styling, final FormattingInfo formattingInfo) {
+            super(NAME, formatters, styling, formattingInfo);
         }
 
         /**
@@ -304,11 +313,12 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
          *
          * @param config The current Configuration.
          * @param options The pattern options, may be null. If the first 
element is "short", only the first line of the
-         *                throwable will be formatted.
+         *            throwable will be formatted.
          * @return new instance of class or null
          */
-        public static Yellow newInstance(final Configuration config, final 
String[] options) {
-            return newInstance(Yellow.class, NAME, config, options);
+        public static Yellow newInstance(final Configuration config, final 
String[] options,
+                final FormattingInfo formattingInfo) {
+            return newInstance(Yellow.class, NAME, config, options, 
formattingInfo);
         }
     }
 
@@ -317,19 +327,18 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
      *
      * @param config The current Configuration.
      * @param options The pattern options, may be null. If the first element 
is "short", only the first line of the
-     *                throwable will be formatted.
+     *            throwable will be formatted.
      * @return new instance of class or null
      */
     protected static <T extends AbstractStyleNameConverter> T 
newInstance(final Class<T> asnConverterClass,
-                                                                          
final String name, final Configuration config,
-                                                                          
final String[] options) {
+            final String name, final Configuration config, final String[] 
options, final FormattingInfo formattingInfo) {
         final List<PatternFormatter> formatters = 
toPatternFormatterList(config, options);
         if (formatters == null) {
             return null;
         }
         try {
             final Constructor<T> constructor = 
asnConverterClass.getConstructor(List.class, String.class);
-            return constructor.newInstance(formatters, 
AnsiEscape.createSequence(name));
+            return constructor.newInstance(formatters, 
AnsiEscape.createSequence(name), formattingInfo);
         } catch (final SecurityException e) {
             LOGGER.error(e.toString(), e);
         } catch (final NoSuchMethodException e) {
@@ -370,13 +379,27 @@ public abstract class AbstractStyleNameConverter extends 
LogEventPatternConverte
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        final StringBuilder buf = new StringBuilder();
-        for (final PatternFormatter formatter : formatters) {
-            formatter.format(event, buf);
-        }
-        if (buf.length() > 0) {
-            
toAppendTo.append(style).append(buf.toString()).append(AnsiEscape.getDefaultStyle());
+    public void format(final LogEvent event, final TextBuffer toAppendTo) {
+        format0(event, toAppendTo, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        format0(event, toAppendTo, charset);
+    }
+
+    private void format0(final LogEvent event, final Buffer toAppendTo, final 
Charset charset) {
+        StyleConverter.formatNested(event, toAppendTo, charset, false, 
formatters, style, AnsiEscape.getDefaultStyle());
+    }
+    
+    @Override
+    public void setCharset(final Charset charset) {
+        super.setCharset(charset);
+        for (PatternFormatter paf : formatters) {
+            paf.getConverter().setCharset(charset);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ArrayPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ArrayPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ArrayPatternConverter.java
index c571b45..b731390 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ArrayPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ArrayPatternConverter.java
@@ -23,8 +23,8 @@ public interface ArrayPatternConverter extends 
PatternConverter {
 
     /**
      * Formats an array of Objects.
-     * @param toAppendTo The StringBuilder to add the content to.
+     * @param toAppendTo The Buffer to add the content to.
      * @param objects The Object array.
      */
-    void format(final StringBuilder toAppendTo, Object... objects);
+    void format(final Buffer toAppendTo, Object... objects);
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassNamePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassNamePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassNamePatternConverter.java
index a2e0f2a..1d17139 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassNamePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ClassNamePatternConverter.java
@@ -16,10 +16,11 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
+
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
-
 /**
  * Formats the class name of the site of the logging request.
  */
@@ -27,16 +28,15 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 @ConverterKeys({ "C", "class" })
 public final class ClassNamePatternConverter extends NamePatternConverter {
 
-    private static final String NA = "?";
+    private static final char NA = '?';
 
     /**
      * Private constructor.
      *
      * @param options options, may be null.
      */
-    private ClassNamePatternConverter(
-        final String[] options) {
-        super("Class Name", "class name", options);
+    private ClassNamePatternConverter(final String[] options, final 
FormattingInfo formattingInfo) {
+        super("Class Name", "class name", options, formattingInfo);
     }
 
     /**
@@ -45,18 +45,18 @@ public final class ClassNamePatternConverter extends 
NamePatternConverter {
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static ClassNamePatternConverter newInstance(final String[] 
options) {
-        return new ClassNamePatternConverter(options);
+    public static ClassNamePatternConverter newInstance(final String[] 
options, final FormattingInfo formattingInfo) {
+        return new ClassNamePatternConverter(options, formattingInfo);
     }
 
     /**
      * Format a logging event.
      *
-     * @param event      event to format.
-     * @param toAppendTo string buffer to which class name will be appended.
+     * @param event event to format.
+     * @param toAppendTo buffer to which class name will be appended.
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+    public void format(final LogEvent event, final TextBuffer toAppendTo) {
         final StackTraceElement element = event.getSource();
         if (element == null) {
             toAppendTo.append(NA);
@@ -64,4 +64,20 @@ public final class ClassNamePatternConverter extends 
NamePatternConverter {
             toAppendTo.append(abbreviate(element.getClassName()));
         }
     }
+
+    /**
+     * Format a logging event.
+     *
+     * @param event event to format.
+     * @param toAppendTo buffer to which class name will be appended.
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        final StackTraceElement element = event.getSource();
+        if (element == null) {
+            toAppendTo.append((byte) NA);
+        } else {
+            toAppendTo.append(abbreviateToBinary(element.getClassName(), 
charset));
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java
index 4e34d50..6415abd 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/DatePatternConverter.java
@@ -16,12 +16,14 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 import java.util.TimeZone;
 
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.util.Assert;
 
 /**
  * Convert and format the event's date in a StringBuilder.
@@ -30,48 +32,112 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 @ConverterKeys({ "d", "date" })
 public final class DatePatternConverter extends LogEventPatternConverter 
implements ArrayPatternConverter {
 
-    private abstract static class Formatter {
-        abstract String format(long time);
+    /**
+     * ADT for formatter helpers.
+     */
+    public abstract static interface Formatter {
+        void format(long time, Buffer buffer);
 
-        public String toPattern() {
-            return null;
-        }
+        void format(Date time, Buffer buffer);
+
+        void format(long timestamp, BinaryBuffer output, Charset charset);
+
+        String toPattern();
     }
 
-    private static class PatternFormatter extends Formatter {
-        private final SimpleDateFormat simpleDateFormat;
+    private static class PatternFormatter implements Formatter {
+        private ThreadLocal<SimpleDateFormat> simpleDateFormat = new 
ThreadLocal<SimpleDateFormat>() {
+            @Override
+            protected SimpleDateFormat initialValue() {
+                final SimpleDateFormat result = new SimpleDateFormat(pattern);
+                if (timeZone != null) {
+                    result.setTimeZone(timeZone);
+                }
+                return result;
+            }
+        };
+        private final String pattern;
+        private final TimeZone timeZone;
+        private final boolean useFastFormat;
+
+        PatternFormatter(final String pattern, final TimeZone timeZone) {
+            this.pattern = Assert.requireNonNull(pattern, "pattern is null");
+            this.timeZone = timeZone;
+            this.useFastFormat = ABSOLUTE_TIME_PATTERN.equals(pattern);
+        }
 
-        PatternFormatter(final SimpleDateFormat simpleDateFormat) {
-            this.simpleDateFormat = simpleDateFormat;
+        @Override
+        public void format(final long time, final Buffer buffer) {
+            format(new Date(time), buffer);
         }
 
         @Override
-        String format(final long time) {
-            return simpleDateFormat.format(Long.valueOf(time));
+        public void format(final Date time, final Buffer buffer) {
+            if (useFastFormat) {
+
+            } else {
+                final String formatted = simpleDateFormat.get().format(time);
+                buffer.append(formatted);
+            }
+        }
+
+        @Override
+        public void format(final long timestamp, final BinaryBuffer output, 
final Charset charset) {
+            if (useFastFormat) {
+
+            } else {
+                format(new Date(timestamp), output); // use SimpleDateFormat
+            }
         }
 
         @Override
         public String toPattern() {
-            return simpleDateFormat.toPattern();
+            return pattern;
         }
     }
 
-    private static class UnixFormatter extends Formatter {
+    private static class UnixFormatter implements Formatter {
+        @Override
+        public void format(final long time, final Buffer buffer) {
+            buffer.append(time / 1000);
+        }
 
         @Override
-        String format(final long time) {
-            return Long.toString(time / 1000);
+        public void format(final Date time, final Buffer buffer) {
+            format(time.getTime(), buffer);
         }
 
+        @Override
+        public void format(final long timestamp, final BinaryBuffer output, 
final Charset charset) {
+            output.append(timestamp / 1000);
+        }
+
+        @Override
+        public String toPattern() {
+            return null;
+        }
     }
 
-    private static class UnixMillisFormatter extends Formatter {
+    private static class UnixMillisFormatter implements Formatter {
+        @Override
+        public void format(final long time, final Buffer buffer) {
+            buffer.append(time);
+        }
+
+        @Override
+        public void format(final Date time, final Buffer buffer) {
+            format(time.getTime(), buffer);
+        }
 
         @Override
-        String format(final long time) {
-            return Long.toString(time);
+        public void format(final long timestamp, final BinaryBuffer output, 
final Charset charset) {
+            output.append(timestamp);
         }
 
+        @Override
+        public String toPattern() {
+            return null;
+        }
     }
 
     /**
@@ -82,7 +148,7 @@ public final class DatePatternConverter extends 
LogEventPatternConverter impleme
     /**
      * SimpleTimePattern for ABSOLUTE.
      */
-    private static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
+    static final String ABSOLUTE_TIME_PATTERN = "HH:mm:ss,SSS";
 
     /**
      * COMPACT string literal.
@@ -150,31 +216,22 @@ public final class DatePatternConverter extends 
LogEventPatternConverter impleme
     /**
      * Obtains an instance of pattern converter.
      *
-     * @param options
-     *            options, may be null.
+     * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static DatePatternConverter newInstance(final String[] options) {
-        return new DatePatternConverter(options);
+    public static DatePatternConverter newInstance(final String[] options, 
final FormattingInfo formattingInfo) {
+        return new DatePatternConverter(options, formattingInfo);
     }
 
-    /**
-     * Date format.
-     */
-    private String cachedDateString;
-
-    private final Formatter formatter;
-
-    private long lastTimestamp;
+    private Formatter formatter;
 
     /**
      * Private constructor.
      *
-     * @param options
-     *            options, may be null.
+     * @param options options, may be null.
      */
-    private DatePatternConverter(final String[] options) {
-        super("Date", "date");
+    private DatePatternConverter(final String[] options, final FormattingInfo 
formattingInfo) {
+        super("Date", "date", formattingInfo);
 
         // null patternOption is OK.
         final String patternOption = options != null && options.length > 0 ? 
options[0] : null;
@@ -203,62 +260,66 @@ public final class DatePatternConverter extends 
LogEventPatternConverter impleme
         }
 
         if (pattern != null) {
-            SimpleDateFormat tempFormat;
-
             try {
-                tempFormat = new SimpleDateFormat(pattern);
+                new SimpleDateFormat(pattern);
             } catch (final IllegalArgumentException e) {
                 LOGGER.warn("Could not instantiate SimpleDateFormat with 
pattern " + patternOption, e);
 
                 // default to the DEFAULT format
-                tempFormat = new SimpleDateFormat(DEFAULT_PATTERN);
+                pattern = DEFAULT_PATTERN;
             }
 
             // if the option list contains a TZ option, then set it.
-            if (options != null && options.length > 1) {
-                final TimeZone tz = TimeZone.getTimeZone(options[1]);
-                tempFormat.setTimeZone(tz);
-            }
-            tempFormatter = new PatternFormatter(tempFormat);
+            final TimeZone tz = (options != null && options.length > 1) ? 
TimeZone.getTimeZone(options[1]) : null;
+            tempFormatter = new PatternFormatter(pattern, tz);
         }
         formatter = tempFormatter;
     }
 
+    @Override
+    public void setCharset(Charset charset) {
+        super.setCharset(charset);
+        if (formatter instanceof PatternFormatter) {
+            PatternFormatter paf = (PatternFormatter) formatter;
+            
+            // FastTimeFormat does not support time zones
+            if (paf.timeZone == null && 
paf.pattern.endsWith(ABSOLUTE_TIME_PATTERN)) {
+                formatter = new FastTimeFormatter(paf.pattern, charset);
+            }
+        }
+    }
+
     /**
      * Append formatted date to string buffer.
      *
-     * @param date
-     *            date
-     * @param toAppendTo
-     *            buffer to which formatted date is appended.
+     * @param date date
+     * @param toAppendTo buffer to which formatted date is appended.
      */
-    public void format(final Date date, final StringBuilder toAppendTo) {
-        synchronized (this) {
-            toAppendTo.append(formatter.format(date.getTime()));
-        }
+    public void format(final Date date, final Buffer toAppendTo) {
+        formatter.format(date, toAppendTo);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder output) {
-        final long timestamp = event.getTimeMillis();
+    public void format(final LogEvent event, final TextBuffer output) {
+        formatter.format(event.getTimeMillis(), output);
+    }
 
-        synchronized (this) {
-            if (timestamp != lastTimestamp) {
-                lastTimestamp = timestamp;
-                cachedDateString = formatter.format(timestamp);
-            }
-        }
-        output.append(cachedDateString);
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer output, final 
Charset charset) {
+        formatter.format(event.getTimeMillis(), output, charset);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final Object obj, final StringBuilder output) {
+    public void format(final Object obj, final Buffer output) {
         if (obj instanceof Date) {
             format((Date) obj, output);
         }
@@ -266,7 +327,7 @@ public final class DatePatternConverter extends 
LogEventPatternConverter impleme
     }
 
     @Override
-    public void format(final StringBuilder toAppendTo, final Object... 
objects) {
+    public void format(final Buffer toAppendTo, final Object... objects) {
         for (final Object obj : objects) {
             if (obj instanceof Date) {
                 format(obj, toAppendTo);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/EncodingPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/EncodingPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/EncodingPatternConverter.java
index b437309..64ecf9f 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/EncodingPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/EncodingPatternConverter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
 import java.util.List;
 
 import org.apache.logging.log4j.core.LogEvent;
@@ -37,8 +38,8 @@ public final class EncodingPatternConverter extends 
LogEventPatternConverter {
      *
      * @param formatters The PatternFormatters to generate the text to 
manipulate.
      */
-    private EncodingPatternConverter(final List<PatternFormatter> formatters) {
-        super("encode", "encode");
+    private EncodingPatternConverter(final List<PatternFormatter> formatters, 
final FormattingInfo formattingInfo) {
+        super("encode", "encode", formattingInfo);
         this.formatters = formatters;
     }
 
@@ -49,7 +50,7 @@ public final class EncodingPatternConverter extends 
LogEventPatternConverter {
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static EncodingPatternConverter newInstance(final Configuration 
config, final String[] options) {
+    public static EncodingPatternConverter newInstance(final Configuration 
config, final String[] options, final FormattingInfo formattingInfo) {
         if (options.length != 1) {
             LOGGER.error("Incorrect number of options on escape. Expected 1, 
received " + options.length);
             return null;
@@ -60,49 +61,73 @@ public final class EncodingPatternConverter extends 
LogEventPatternConverter {
         }
         final PatternParser parser = PatternLayout.createPatternParser(config);
         final List<PatternFormatter> formatters = parser.parse(options[0]);
-        return new EncodingPatternConverter(formatters);
+        return new EncodingPatternConverter(formatters, formattingInfo);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        final StringBuilder buf = new StringBuilder();
+    public void format(final LogEvent event, final TextBuffer toAppendTo) {
+        replaceAndAppend(event, toAppendTo);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        replaceAndAppend(event, toAppendTo);
+    }
+
+    private void replaceAndAppend(final LogEvent event, final Buffer 
toAppendTo) {
+        final TextBuffer buf = new TextBuffer();
         for (final PatternFormatter formatter : formatters) {
             formatter.format(event, buf);
         }
         for (int i = 0; i < buf.length(); i++) {
             final char c = buf.charAt(i);
-            switch (c) {
-                case '\r':
-                    toAppendTo.append("\\r");
-                    break;
-                case '\n':
-                    toAppendTo.append("\\n");
-                    break;
-                case '&':
-                    toAppendTo.append("&amp;");
-                    break;
-                case '<':
-                    toAppendTo.append("&lt;");
-                    break;
-                case '>':
-                    toAppendTo.append("&gt;");
-                    break;
-                case '"':
-                    toAppendTo.append("&quot;");
-                    break;
-                case '\'':
-                    toAppendTo.append("&apos;");
-                    break;
-                case '/':
-                    toAppendTo.append("&#x2F;");
-                    break;
-                default:
-                    toAppendTo.append(c);
-                    break;
-            }
+            replace(c, toAppendTo);
+        }
+    }
+
+    private void replace(final char c, final Buffer toAppendTo) {
+        switch (c) {
+            case '\r':
+                toAppendTo.append("\\r");
+                break;
+            case '\n':
+                toAppendTo.append("\\n");
+                break;
+            case '&':
+                toAppendTo.append("&amp;");
+                break;
+            case '<':
+                toAppendTo.append("&lt;");
+                break;
+            case '>':
+                toAppendTo.append("&gt;");
+                break;
+            case '"':
+                toAppendTo.append("&quot;");
+                break;
+            case '\'':
+                toAppendTo.append("&apos;");
+                break;
+            case '/':
+                toAppendTo.append("&#x2F;");
+                break;
+            default:
+                toAppendTo.append(c);
+                break;
+        }
+    }
+    
+    @Override
+    public void setCharset(final Charset charset) {
+        super.setCharset(charset);
+        for (PatternFormatter paf : formatters) {
+            paf.getConverter().setCharset(charset);
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
index cf6f764..5224042 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/ExtendedThrowablePatternConverter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
+
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 import org.apache.logging.log4j.core.impl.Log4jLogEvent;
@@ -23,12 +25,11 @@ import org.apache.logging.log4j.core.impl.ThrowableProxy;
 import org.apache.logging.log4j.core.util.Constants;
 
 /**
- * Outputs the Throwable portion of the LoggingEvent as a full stacktrace
- * unless this converter's option is 'short', where it just outputs the first 
line of the trace, or if
- * the number of lines to print is explicitly specified.
+ * Outputs the Throwable portion of the LoggingEvent as a full stacktrace 
unless this converter's option is 'short',
+ * where it just outputs the first line of the trace, or if the number of 
lines to print is explicitly specified.
  * <p>
- * The extended stack trace will also include the location of where the class 
was loaded from and the
- * version of the jar if available.
+ * The extended stack trace will also include the location of where the class 
was loaded from and the version of the jar
+ * if available.
  */
 @Plugin(name = "ExtendedThrowablePatternConverter", category = 
PatternConverter.CATEGORY)
 @ConverterKeys({ "xEx", "xThrowable", "xException" })
@@ -39,26 +40,40 @@ public final class ExtendedThrowablePatternConverter 
extends ThrowablePatternCon
      *
      * @param options options, may be null.
      */
-    private ExtendedThrowablePatternConverter(final String[] options) {
-        super("ExtendedThrowable", "throwable", options);
+    private ExtendedThrowablePatternConverter(final String[] options, final 
FormattingInfo formattingInfo) {
+        super("ExtendedThrowable", "throwable", options, formattingInfo);
     }
 
     /**
      * Gets an instance of the class.
      *
-     * @param options pattern options, may be null.  If first element is 
"short",
-     *                only the first line of the throwable will be formatted.
+     * @param options pattern options, may be null. If first element is 
"short", only the first line of the throwable
+     *            will be formatted.
      * @return instance of class.
      */
-    public static ExtendedThrowablePatternConverter newInstance(final String[] 
options) {
-        return new ExtendedThrowablePatternConverter(options);
+    public static ExtendedThrowablePatternConverter newInstance(final String[] 
options,
+            final FormattingInfo formattingInfo) {
+        return new ExtendedThrowablePatternConverter(options, formattingInfo);
+    }
+
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final TextBuffer toAppendTo) {
+        handle(event, toAppendTo);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        handle(event, toAppendTo);
+    }
+
+    private void handle(final LogEvent event, final Buffer toAppendTo) {
         ThrowableProxy proxy = null;
         if (event instanceof Log4jLogEvent) {
             proxy = ((Log4jLogEvent) event).getThrownProxy();
@@ -70,13 +85,12 @@ public final class ExtendedThrowablePatternConverter 
extends ThrowablePatternCon
                 return;
             }
             final String trace = 
proxy.getExtendedStackTraceAsString(options.getPackages());
-            final int len = toAppendTo.length();
-            if (len > 0 && !Character.isWhitespace(toAppendTo.charAt(len - 
1))) {
+            if (!toAppendTo.hasTrailingWhitespace()) {
                 toAppendTo.append(' ');
             }
             if (!options.allLines() || 
!Constants.LINE_SEPARATOR.equals(options.getSeparator())) {
-                final StringBuilder sb = new StringBuilder();
                 final String[] array = trace.split(Constants.LINE_SEPARATOR);
+                final StringBuilder sb = new StringBuilder(array.length << 7); 
// *128: estimate 128 chars per line
                 final int limit = options.minLines(array.length) - 1;
                 for (int i = 0; i <= limit; ++i) {
                     sb.append(array[i]);

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileDatePatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileDatePatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileDatePatternConverter.java
index 7a83d78..a6fb361 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileDatePatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileDatePatternConverter.java
@@ -19,9 +19,8 @@ package org.apache.logging.log4j.core.pattern;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
 /**
- * Formats a date by delegating to {@link DatePatternConverter}.  The default
- * date pattern for a %d specifier in a file name is different than
- * the %d pattern in pattern layout.
+ * Formats a date by delegating to {@link DatePatternConverter}. The default 
date pattern for a %d specifier in a file
+ * name is different than the %d pattern in pattern layout.
  */
 @Plugin(name = "FileDatePatternConverter", category = "FileConverter")
 @ConverterKeys({ "d", "date" })
@@ -38,14 +37,11 @@ public final class FileDatePatternConverter {
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static PatternConverter newInstance(final String[] options) {
+    public static PatternConverter newInstance(final String[] options, final 
FormattingInfo formattingInfo) {
         if (options == null || options.length == 0) {
-            return DatePatternConverter.newInstance(
-                new String[]{
-                    "yyyy-MM-dd"
-                });
+            return DatePatternConverter.newInstance(new String[] { 
"yyyy-MM-dd" }, formattingInfo);
         }
 
-        return DatePatternConverter.newInstance(options);
+        return DatePatternConverter.newInstance(options, formattingInfo);
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileLocationPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileLocationPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileLocationPatternConverter.java
index 7fcd33d..5a7a9af 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileLocationPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FileLocationPatternConverter.java
@@ -16,27 +16,23 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
+
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
-
 /**
  * Returns the event's line location information in a StringBuilder.
  */
 @Plugin(name = "FileLocationPatternConverter", category = 
PatternConverter.CATEGORY)
 @ConverterKeys({ "F", "file" })
 public final class FileLocationPatternConverter extends 
LogEventPatternConverter {
-    /**
-     * Singleton.
-     */
-    private static final FileLocationPatternConverter INSTANCE =
-        new FileLocationPatternConverter();
 
     /**
      * Private constructor.
      */
-    private FileLocationPatternConverter() {
-        super("File Location", "file");
+    private FileLocationPatternConverter(final FormattingInfo formattingInfo) {
+        super("File Location", "file", formattingInfo);
     }
 
     /**
@@ -45,19 +41,29 @@ public final class FileLocationPatternConverter extends 
LogEventPatternConverter
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static FileLocationPatternConverter newInstance(final String[] 
options) {
-        return INSTANCE;
+    public static FileLocationPatternConverter newInstance(final String[] 
options, final FormattingInfo formattingInfo) {
+        return new FileLocationPatternConverter(formattingInfo);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder output) {
+    public void format(final LogEvent event, final TextBuffer output) {
         final StackTraceElement element = event.getSource();
+        if (element != null) {
+            output.append(getCachedFormattedString(element.getFileName()));
+        }
+    }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        final StackTraceElement element = event.getSource();
         if (element != null) {
-            output.append(element.getFileName());
+            toAppendTo.append(getCachedFormattedBytes(element.getFileName(), 
charset));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
index 950a7d5..a02c2fc 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FormattingInfo.java
@@ -17,6 +17,9 @@
 
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.ByteBuffer;
+import java.util.Arrays;
+
 /**
  * Modifies the output of a pattern converter for a specified minimum and 
maximum width and alignment.
  */
@@ -24,7 +27,14 @@ public final class FormattingInfo {
     /**
      * Array of spaces.
      */
-    private static final char[] SPACES = new char[] { ' ', ' ', ' ', ' ', ' ', 
' ', ' ', ' ' };
+    private static final char[] SPACES = new char[128];
+    static {
+        Arrays.fill(SPACES, ' ');
+    }
+    private static final byte[] SPACEBYTES = new byte[128];
+    static {
+        Arrays.fill(SPACEBYTES, (byte) ' ');
+    }
 
     /**
      * Default instance.
@@ -49,14 +59,22 @@ public final class FormattingInfo {
     /**
      * Creates new instance.
      *
-     * @param leftAlign
-     *            left align if true.
-     * @param minLength
-     *            minimum length.
-     * @param maxLength
-     *            maximum length.
+     * @param leftAlign left align if true.
+     * @param minLength minimum length (must be non-negative and not exceed 
maxLength).
+     * @param maxLength maximum length (must be non-negative).
      */
     public FormattingInfo(final boolean leftAlign, final int minLength, final 
int maxLength) {
+        if (minLength < 0) {
+            throw new IllegalArgumentException("MinLength must be at least 0 
but was " + minLength);
+        }
+        if (maxLength < 0) {
+            throw new IllegalArgumentException("MaxLength must be at least 0 
but was " + maxLength);
+        }
+        // Note: I'd like to assert that min <= max, but this breaks the 
PatternParser unit tests (and perhaps user
+        // code)
+        // if (minLength > maxLength) {
+        // throw new IllegalArgumentException("MinLength " + minLength + " 
exceeds MaxLength " + maxLength);
+        // }
         this.leftAlign = leftAlign;
         this.minLength = minLength;
         this.maxLength = maxLength;
@@ -101,12 +119,13 @@ public final class FormattingInfo {
     /**
      * Adjust the content of the buffer based on the specified lengths and 
alignment.
      *
-     * @param fieldStart
-     *            start of field in buffer.
-     * @param buffer
-     *            buffer to be modified.
+     * @param fieldStart start of field in buffer.
+     * @param buffer buffer to be modified.
      */
     public void format(final int fieldStart, final StringBuilder buffer) {
+        if (this == DEFAULT) {
+            return; // no formatting
+        }
         final int rawLength = buffer.length() - fieldStart;
 
         if (rawLength > maxLength) {
@@ -150,4 +169,49 @@ public final class FormattingInfo {
         return sb.toString();
     }
 
+    /**
+     * Adjust the content of the buffer based on the specified lengths and 
alignment.
+     *
+     * @param fieldStart start of field in buffer.
+     * @param buffer buffer to be modified.
+     */
+    public void format(int fieldStart, ByteBuffer buffer) {
+        if (this == DEFAULT) {
+            return; // no formatting
+        }
+        final int rawLength = buffer.position() - fieldStart;
+
+        if (rawLength > maxLength) {
+            buffer.position(buffer.position() - maxLength);
+            final ByteBuffer src = buffer.slice();
+            src.limit(maxLength);
+            buffer.position(fieldStart);
+            buffer.put(src);
+        } else if (rawLength < minLength) {
+            if (leftAlign) {
+                final int fieldEnd = buffer.position();
+                buffer.position(fieldStart + minLength);
+
+                for (int i = fieldEnd; i < buffer.position(); i++) {
+                    buffer.put(i, (byte) ' ');
+                }
+            } else {
+                int old = buffer.position();
+                int padLength = minLength - rawLength;
+
+                buffer.position(fieldStart);
+                final ByteBuffer src = buffer.slice();
+                src.limit(old - fieldStart);
+                buffer.position(fieldStart + padLength);
+                buffer.put(src);
+
+                buffer.position(fieldStart);
+                for (; padLength > SPACES.length; padLength -= SPACES.length) {
+                    buffer.put(SPACEBYTES, 0, padLength);
+                }
+                buffer.put(SPACEBYTES, 0, padLength);
+                buffer.position(minLength + fieldStart);
+            }
+        }
+    }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FullLocationPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FullLocationPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FullLocationPatternConverter.java
index 120a671..e6c43ef 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FullLocationPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/FullLocationPatternConverter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
+
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
@@ -26,17 +28,12 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 @Plugin(name = "FullLocationPatternConverter", category = 
PatternConverter.CATEGORY)
 @ConverterKeys({ "l", "location" })
 public final class FullLocationPatternConverter extends 
LogEventPatternConverter {
-    /**
-     * Singleton.
-     */
-    private static final FullLocationPatternConverter INSTANCE =
-        new FullLocationPatternConverter();
 
     /**
      * Private constructor.
      */
-    private FullLocationPatternConverter() {
-        super("Full Location", "fullLocation");
+    private FullLocationPatternConverter(final FormattingInfo formattingInfo) {
+        super("Full Location", "fullLocation", formattingInfo);
     }
 
     /**
@@ -45,19 +42,29 @@ public final class FullLocationPatternConverter extends 
LogEventPatternConverter
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static FullLocationPatternConverter newInstance(final String[] 
options) {
-        return INSTANCE;
+    public static FullLocationPatternConverter newInstance(final String[] 
options, final FormattingInfo formattingInfo) {
+        return new FullLocationPatternConverter(formattingInfo);
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder output) {
+    public void format(final LogEvent event, final TextBuffer output) {
         final StackTraceElement element = event.getSource();
+        if (element != null) {
+            output.append(getCachedFormattedString(element));
+        }
+    }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        final StackTraceElement element = event.getSource();
         if (element != null) {
-            output.append(element.toString());
+            toAppendTo.append(getCachedFormattedBytes(element, charset));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
index 3fc0ef0..473f8d2 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/HighlightConverter.java
@@ -1,229 +1,243 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache license, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the license for the specific language governing permissions and
- * limitations under the license.
- */
-package org.apache.logging.log4j.core.pattern;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-
-import org.apache.logging.log4j.Level;
-import org.apache.logging.log4j.core.LogEvent;
-import org.apache.logging.log4j.core.config.Configuration;
-import org.apache.logging.log4j.core.config.plugins.Plugin;
-import org.apache.logging.log4j.core.layout.PatternLayout;
-import org.apache.logging.log4j.util.Strings;
-
-/**
- * Highlight pattern converter. Formats the result of a pattern using a color 
appropriate for the Level in the LogEvent.
- * <p>
- * For example:
- * </p>
- * 
- * <pre>
- * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}
- * </pre>
- * <p>
- * You can define custom colors for each Level:
- * </p>
- * 
- * <pre>
- * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=red, 
ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan,
- * TRACE=black}
- * </pre>
- * <p>
- * You can use a predefined style:
- * </p>
- * 
- * <pre>
- * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=Log4j}
- * </pre>
- * <p>
- * The available predefined styles are:
- * </p>
- * <ul>
- * <li>{@code Default}</li>
- * <li>{@code Log4j} - The same as {@code Default}</li>
- * <li>{@code Logback}</li>
- * </ul>
- * <p>
- * You can use whitespace around the comma and equal sign. The names in values 
MUST come from the
- * {@linkplain AnsiEscape} enum, case is normalized to upper-case internally.
- * </p>
- */
-@Plugin(name = "highlight", category = PatternConverter.CATEGORY)
-@ConverterKeys({ "highlight" })
-public final class HighlightConverter extends LogEventPatternConverter 
implements AnsiConverter {
-
-    private static final Map<Level, String> DEFAULT_STYLES = new 
HashMap<Level, String>();
-
-    private static final Map<Level, String> LOGBACK_STYLES = new 
HashMap<Level, String>();
-
-    private static final String STYLE_KEY = "STYLE";
-
-    private static final String STYLE_KEY_DEFAULT = "DEFAULT";
-
-    private static final String STYLE_KEY_LOGBACK = "LOGBACK";
-
-    private static final Map<String, Map<Level, String>> STYLES = new 
HashMap<String, Map<Level, String>>();
-
-    static {
-        // Default styles:
-        DEFAULT_STYLES.put(Level.FATAL, AnsiEscape.createSequence("BRIGHT", 
"RED"));
-        DEFAULT_STYLES.put(Level.ERROR, AnsiEscape.createSequence("BRIGHT", 
"RED"));
-        DEFAULT_STYLES.put(Level.WARN, AnsiEscape.createSequence("YELLOW"));
-        DEFAULT_STYLES.put(Level.INFO, AnsiEscape.createSequence("GREEN"));
-        DEFAULT_STYLES.put(Level.DEBUG, AnsiEscape.createSequence("CYAN"));
-        DEFAULT_STYLES.put(Level.TRACE, AnsiEscape.createSequence("BLACK"));
-        // Logback styles:
-        LOGBACK_STYLES.put(Level.FATAL, AnsiEscape.createSequence("BLINK", 
"BRIGHT", "RED"));
-        LOGBACK_STYLES.put(Level.ERROR, AnsiEscape.createSequence("BRIGHT", 
"RED"));
-        LOGBACK_STYLES.put(Level.WARN, AnsiEscape.createSequence("RED"));
-        LOGBACK_STYLES.put(Level.INFO, AnsiEscape.createSequence("BLUE"));
-        LOGBACK_STYLES.put(Level.DEBUG, AnsiEscape.createSequence((String[]) 
null));
-        LOGBACK_STYLES.put(Level.TRACE, AnsiEscape.createSequence((String[]) 
null));
-        // Style map:
-        STYLES.put(STYLE_KEY_DEFAULT, DEFAULT_STYLES);
-        STYLES.put(STYLE_KEY_LOGBACK, LOGBACK_STYLES);
-    }
-
-    /**
-     * Creates a level style map where values are ANSI escape sequences given 
configuration options in {@code option[1]}
-     * .
-     * <p>
-     * The format of the option string in {@code option[1]} is:
-     * </p>
-     * 
-     * <pre>
-     * Level1=Value, Level2=Value, ...
-     * </pre>
-     *
-     * <p>
-     * For example:
-     * </p>
-     *
-     * <pre>
-     * ERROR=red bold, WARN=yellow bold, INFO=green, ...
-     * </pre>
-     *
-     * <p>
-     * You can use whitespace around the comma and equal sign. The names in 
values MUST come from the
-     * {@linkplain AnsiEscape} enum, case is normalized to upper-case 
internally.
-     * </p>
-     *
-     * @param options
-     *        The second slot can optionally contain the style map.
-     * @return a new map
-     */
-    private static Map<Level, String> createLevelStyleMap(final String[] 
options) {
-        if (options.length < 2) {
-            return DEFAULT_STYLES;
-        }
-        // Feels like a hack. Should String[] options change to a 
Map<String,String>?
-        final String string = 
options[1].replaceAll(PatternParser.NO_CONSOLE_NO_ANSI + "=(true|false)", 
Strings.EMPTY);
-        //
-        final Map<String, String> styles = AnsiEscape.createMap(string, new 
String[] {STYLE_KEY});
-        final Map<Level, String> levelStyles = new HashMap<Level, 
String>(DEFAULT_STYLES);
-        for (final Map.Entry<String, String> entry : styles.entrySet()) {
-            final String key = entry.getKey().toUpperCase(Locale.ENGLISH);
-            final String value = entry.getValue();
-            if (STYLE_KEY.equalsIgnoreCase(key)) {
-                final Map<Level, String> enumMap = 
STYLES.get(value.toUpperCase(Locale.ENGLISH));
-                if (enumMap == null) {
-                    LOGGER.error("Unknown level style: " + value + ". Use one 
of " +
-                        Arrays.toString(STYLES.keySet().toArray()));
-                } else {
-                    levelStyles.putAll(enumMap);
-                }
-            } else {
-                final Level level = Level.toLevel(key);
-                if (level == null) {
-                    LOGGER.error("Unknown level name: " + key + ". Use one of 
" +
-                        Arrays.toString(DEFAULT_STYLES.keySet().toArray()));
-                } else {
-                    levelStyles.put(level, value);
-                }
-            }
-        }
-        return levelStyles;
-    }
-
-    /**
-     * Gets an instance of the class.
-     *
-     * @param config The current Configuration.
-     * @param options pattern options, may be null. If first element is 
"short", only the first line of the
-     *                throwable will be formatted.
-     * @return instance of class.
-     */
-    public static HighlightConverter newInstance(final Configuration config, 
final String[] options) {
-        if (options.length < 1) {
-            LOGGER.error("Incorrect number of options on style. Expected at 
least 1, received " + options.length);
-            return null;
-        }
-        if (options[0] == null) {
-            LOGGER.error("No pattern supplied on style");
-            return null;
-        }
-        final PatternParser parser = PatternLayout.createPatternParser(config);
-        final List<PatternFormatter> formatters = parser.parse(options[0]);
-        return new HighlightConverter(formatters, 
createLevelStyleMap(options));
-    }
-
-    private final Map<Level, String> levelStyles;
-
-    private final List<PatternFormatter> patternFormatters;
-
-    /**
-     * Construct the converter.
-     *
-     * @param patternFormatters
-     *            The PatternFormatters to generate the text to manipulate.
-     */
-    private HighlightConverter(final List<PatternFormatter> patternFormatters, 
final Map<Level, String> levelStyles) {
-        super("style", "style");
-        this.patternFormatters = patternFormatters;
-        this.levelStyles = levelStyles;
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void format(final LogEvent event, final StringBuilder toAppendTo) {
-        final StringBuilder buf = new StringBuilder();
-        for (final PatternFormatter formatter : patternFormatters) {
-            formatter.format(event, buf);
-        }
-
-        if (buf.length() > 0) {
-            
toAppendTo.append(levelStyles.get(event.getLevel())).append(buf.toString()).
-                append(AnsiEscape.getDefaultStyle());
-        }
-    }
-
-    @Override
-    public boolean handlesThrowable() {
-        for (final PatternFormatter formatter : patternFormatters) {
-            if (formatter .handlesThrowable()) {
-                return true;
-            }
-        }
-        return false;
-    }
-}
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache license, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the license for the specific language governing permissions and
+ * limitations under the license.
+ */
+package org.apache.logging.log4j.core.pattern;
+
+import java.nio.charset.Charset;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+
+import org.apache.logging.log4j.Level;
+import org.apache.logging.log4j.core.LogEvent;
+import org.apache.logging.log4j.core.config.Configuration;
+import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.apache.logging.log4j.util.Strings;
+
+/**
+ * Highlight pattern converter. Formats the result of a pattern using a color 
appropriate for the Level in the LogEvent.
+ * <p>
+ * For example:
+ * </p>
+ * 
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}
+ * </pre>
+ * <p>
+ * You can define custom colors for each Level:
+ * </p>
+ * 
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{FATAL=red, 
ERROR=red, WARN=yellow, INFO=green, DEBUG=cyan,
+ * TRACE=black}
+ * </pre>
+ * <p>
+ * You can use a predefined style:
+ * </p>
+ * 
+ * <pre>
+ * %highlight{%d{ ISO8601 } [%t] %-5level: %msg%n%throwable}{STYLE=Log4j}
+ * </pre>
+ * <p>
+ * The available predefined styles are:
+ * </p>
+ * <ul>
+ * <li>{@code Default}</li>
+ * <li>{@code Log4j} - The same as {@code Default}</li>
+ * <li>{@code Logback}</li>
+ * </ul>
+ * <p>
+ * You can use whitespace around the comma and equal sign. The names in values 
MUST come from the
+ * {@linkplain AnsiEscape} enum, case is normalized to upper-case internally.
+ * </p>
+ */
+@Plugin(name = "highlight", category = PatternConverter.CATEGORY)
+@ConverterKeys({ "highlight" })
+public final class HighlightConverter extends LogEventPatternConverter 
implements AnsiConverter {
+
+    private static final Map<Level, String> DEFAULT_STYLES = new 
HashMap<Level, String>();
+
+    private static final Map<Level, String> LOGBACK_STYLES = new 
HashMap<Level, String>();
+
+    private static final String STYLE_KEY = "STYLE";
+
+    private static final String STYLE_KEY_DEFAULT = "DEFAULT";
+
+    private static final String STYLE_KEY_LOGBACK = "LOGBACK";
+
+    private static final Map<String, Map<Level, String>> STYLES = new 
HashMap<String, Map<Level, String>>();
+
+    static {
+        // Default styles:
+        DEFAULT_STYLES.put(Level.FATAL, AnsiEscape.createSequence("BRIGHT", 
"RED"));
+        DEFAULT_STYLES.put(Level.ERROR, AnsiEscape.createSequence("BRIGHT", 
"RED"));
+        DEFAULT_STYLES.put(Level.WARN, AnsiEscape.createSequence("YELLOW"));
+        DEFAULT_STYLES.put(Level.INFO, AnsiEscape.createSequence("GREEN"));
+        DEFAULT_STYLES.put(Level.DEBUG, AnsiEscape.createSequence("CYAN"));
+        DEFAULT_STYLES.put(Level.TRACE, AnsiEscape.createSequence("BLACK"));
+        // Logback styles:
+        LOGBACK_STYLES.put(Level.FATAL, AnsiEscape.createSequence("BLINK", 
"BRIGHT", "RED"));
+        LOGBACK_STYLES.put(Level.ERROR, AnsiEscape.createSequence("BRIGHT", 
"RED"));
+        LOGBACK_STYLES.put(Level.WARN, AnsiEscape.createSequence("RED"));
+        LOGBACK_STYLES.put(Level.INFO, AnsiEscape.createSequence("BLUE"));
+        LOGBACK_STYLES.put(Level.DEBUG, AnsiEscape.createSequence((String[]) 
null));
+        LOGBACK_STYLES.put(Level.TRACE, AnsiEscape.createSequence((String[]) 
null));
+        // Style map:
+        STYLES.put(STYLE_KEY_DEFAULT, DEFAULT_STYLES);
+        STYLES.put(STYLE_KEY_LOGBACK, LOGBACK_STYLES);
+    }
+
+    /**
+     * Creates a level style map where values are ANSI escape sequences given 
configuration options in {@code option[1]}
+     * .
+     * <p>
+     * The format of the option string in {@code option[1]} is:
+     * </p>
+     * 
+     * <pre>
+     * Level1=Value, Level2=Value, ...
+     * </pre>
+     *
+     * <p>
+     * For example:
+     * </p>
+     *
+     * <pre>
+     * ERROR=red bold, WARN=yellow bold, INFO=green, ...
+     * </pre>
+     *
+     * <p>
+     * You can use whitespace around the comma and equal sign. The names in 
values MUST come from the
+     * {@linkplain AnsiEscape} enum, case is normalized to upper-case 
internally.
+     * </p>
+     *
+     * @param options The second slot can optionally contain the style map.
+     * @return a new map
+     */
+    private static Map<Level, String> createLevelStyleMap(final String[] 
options) {
+        if (options.length < 2) {
+            return DEFAULT_STYLES;
+        }
+        // Feels like a hack. Should String[] options change to a 
Map<String,String>?
+        final String string = 
options[1].replaceAll(PatternParser.NO_CONSOLE_NO_ANSI + "=(true|false)", 
Strings.EMPTY);
+        //
+        final Map<String, String> styles = AnsiEscape.createMap(string, new 
String[] { STYLE_KEY });
+        final Map<Level, String> levelStyles = new HashMap<Level, 
String>(DEFAULT_STYLES);
+        for (final Map.Entry<String, String> entry : styles.entrySet()) {
+            final String key = entry.getKey().toUpperCase(Locale.ENGLISH);
+            final String value = entry.getValue();
+            if (STYLE_KEY.equalsIgnoreCase(key)) {
+                final Map<Level, String> enumMap = 
STYLES.get(value.toUpperCase(Locale.ENGLISH));
+                if (enumMap == null) {
+                    LOGGER.error("Unknown level style: " + value + ". Use one 
of "
+                            + Arrays.toString(STYLES.keySet().toArray()));
+                } else {
+                    levelStyles.putAll(enumMap);
+                }
+            } else {
+                final Level level = Level.toLevel(key);
+                if (level == null) {
+                    LOGGER.error("Unknown level name: " + key + ". Use one of "
+                            + 
Arrays.toString(DEFAULT_STYLES.keySet().toArray()));
+                } else {
+                    levelStyles.put(level, value);
+                }
+            }
+        }
+        return levelStyles;
+    }
+
+    /**
+     * Gets an instance of the class.
+     *
+     * @param config The current Configuration.
+     * @param options pattern options, may be null. If first element is 
"short", only the first line of the throwable
+     *            will be formatted.
+     * @return instance of class.
+     */
+    public static HighlightConverter newInstance(final Configuration config, 
final String[] options,
+            final FormattingInfo formattingInfo) {
+        if (options.length < 1) {
+            LOGGER.error("Incorrect number of options on style. Expected at 
least 1, received " + options.length);
+            return null;
+        }
+        if (options[0] == null) {
+            LOGGER.error("No pattern supplied on style");
+            return null;
+        }
+        final PatternParser parser = PatternLayout.createPatternParser(config);
+        final List<PatternFormatter> formatters = parser.parse(options[0]);
+        return new HighlightConverter(formatters, 
createLevelStyleMap(options), formattingInfo);
+    }
+
+    private final Map<Level, String> levelStyles;
+
+    private final List<PatternFormatter> patternFormatters;
+
+    /**
+     * Construct the converter.
+     *
+     * @param patternFormatters The PatternFormatters to generate the text to 
manipulate.
+     */
+    private HighlightConverter(final List<PatternFormatter> patternFormatters, 
final Map<Level, String> levelStyles,
+            final FormattingInfo formattingInfo) {
+        super("style", "style", formattingInfo);
+        this.patternFormatters = patternFormatters;
+        this.levelStyles = levelStyles;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final TextBuffer toAppendTo) {
+        format0(event, toAppendTo, null);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        format0(event, toAppendTo, charset);
+    }
+
+    private void format0(final LogEvent event, final Buffer toAppendTo, final 
Charset charset) {
+        StyleConverter.formatNested(event, toAppendTo, charset, false, 
patternFormatters,
+                levelStyles.get(event.getLevel()), 
AnsiEscape.getDefaultStyle());
+    }
+
+    @Override
+    public boolean handlesThrowable() {
+        for (final PatternFormatter formatter : patternFormatters) {
+            if (formatter.handlesThrowable()) {
+                return true;
+            }
+        }
+        return false;
+    }
+    
+    @Override
+    public void setCharset(final Charset charset) {
+        super.setCharset(charset);
+        for (PatternFormatter paf : patternFormatters) {
+            paf.getConverter().setCharset(charset);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/IntegerPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/IntegerPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/IntegerPatternConverter.java
index 5380d45..c352cac 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/IntegerPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/IntegerPatternConverter.java
@@ -20,24 +20,18 @@ import java.util.Date;
 
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
-
 /**
  * Formats an integer.
  */
 @Plugin(name = "IntegerPatternConverter", category = "FileConverter")
 @ConverterKeys({ "i", "index" })
 public final class IntegerPatternConverter extends AbstractPatternConverter 
implements ArrayPatternConverter {
-    
-    /**
-     * Singleton.
-     */
-    private static final IntegerPatternConverter INSTANCE = new 
IntegerPatternConverter();
 
     /**
      * Private constructor.
      */
-    private IntegerPatternConverter() {
-        super("Integer", "integer");
+    private IntegerPatternConverter(final FormattingInfo formattingInfo) {
+        super("Integer", "integer", formattingInfo);
     }
 
     /**
@@ -46,13 +40,12 @@ public final class IntegerPatternConverter extends 
AbstractPatternConverter impl
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static IntegerPatternConverter newInstance(
-        final String[] options) {
-        return INSTANCE;
+    public static IntegerPatternConverter newInstance(final String[] options, 
final FormattingInfo formattingInfo) {
+        return new IntegerPatternConverter(formattingInfo);
     }
 
     @Override
-    public void format(final StringBuilder toAppendTo, final Object... 
objects) {
+    public void format(final Buffer toAppendTo, final Object... objects) {
         for (final Object obj : objects) {
             if (obj instanceof Integer) {
                 format(obj, toAppendTo);
@@ -65,7 +58,7 @@ public final class IntegerPatternConverter extends 
AbstractPatternConverter impl
      * {@inheritDoc}
      */
     @Override
-    public void format(final Object obj, final StringBuilder toAppendTo) {
+    public void format(final Object obj, final Buffer toAppendTo) {
         if (obj instanceof Integer) {
             toAppendTo.append(obj.toString());
         } else if (obj instanceof Date) {

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LevelPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LevelPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LevelPatternConverter.java
index 1975fcf..7d31fc8 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LevelPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LevelPatternConverter.java
@@ -16,6 +16,7 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
 import java.util.HashMap;
 import java.util.Locale;
 import java.util.Map;
@@ -23,6 +24,7 @@ import java.util.Map;
 import org.apache.logging.log4j.Level;
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
+import org.apache.logging.log4j.core.util.Charsets;
 import org.apache.logging.log4j.core.util.Patterns;
 
 /**
@@ -34,33 +36,29 @@ public final class LevelPatternConverter extends 
LogEventPatternConverter {
     private static final String OPTION_LENGTH = "length";
     private static final String OPTION_LOWER = "lowerCase";
 
-    /**
-     * Singleton.
-     */
-    private static final LevelPatternConverter INSTANCE = new 
LevelPatternConverter(null);
-
-    private final Map<Level, String> levelMap;
+    private final Map<Level, String> levelTextMap;
+    private final Map<Level, byte[]> levelBinaryMap = new HashMap<Level, 
byte[]>();
 
     /**
      * Private constructor.
      */
-    private LevelPatternConverter(final Map<Level, String> map) {
-        super("Level", "level");
-        this.levelMap = map;
+    private LevelPatternConverter(final Map<Level, String> map, final 
FormattingInfo formattingInfo) {
+        super("Level", "level", formattingInfo);
+        this.levelTextMap = map;
     }
 
     /**
      * Obtains an instance of pattern converter.
      *
-     * @param options
-     *            options, may be null. May contain a list of level names and 
The value that should be displayed for the
-     *            Level.
+     * @param options options, may be null. May contain a list of level names 
and The value that should be displayed for
+     *            the Level.
      * @return instance of pattern converter.
      */
-    public static LevelPatternConverter newInstance(final String[] options) {
+    public static LevelPatternConverter newInstance(final String[] options, 
final FormattingInfo formattingInfo) {
         if (options == null || options.length == 0) {
-            return INSTANCE;
+            return createDefaultLevelPatternConverter(formattingInfo);
         }
+        final StringBuilder sb = new StringBuilder(64);
         final Map<Level, String> levelMap = new HashMap<Level, String>();
         int length = Integer.MAX_VALUE; // More than the longest level name.
         boolean lowerCase = false;
@@ -82,29 +80,63 @@ public final class LevelPatternConverter extends 
LogEventPatternConverter {
                 if (level == null) {
                     LOGGER.error("Invalid Level {}", key);
                 } else {
-                    levelMap.put(level, value);
+                    levelMap.put(level, format(formattingInfo, sb, value));
                 }
             }
         }
         if (levelMap.isEmpty() && length == Integer.MAX_VALUE && !lowerCase) {
-            return INSTANCE;
+            return createDefaultLevelPatternConverter(formattingInfo);
         }
         for (final Level level : Level.values()) {
             if (!levelMap.containsKey(level)) {
                 final String left = left(level, length);
-                levelMap.put(level, lowerCase ? left.toLowerCase(Locale.US) : 
left);
+                final String value = lowerCase ? left.toLowerCase(Locale.US) : 
left;
+                levelMap.put(level, format(formattingInfo, sb, value));
             }
         }
-        return new LevelPatternConverter(levelMap);
+        return new LevelPatternConverter(levelMap, formattingInfo);
+    }
+
+    private static LevelPatternConverter 
createDefaultLevelPatternConverter(final FormattingInfo formattingInfo) {
+        final FormattingInfo fi = formattingInfo;
+        return new LevelPatternConverter(createTextLevelMap(fi), fi);
+    }
+
+    private static Map<Level, String> createTextLevelMap(final FormattingInfo 
formattingInfo) {
+        if (formattingInfo == null || formattingInfo == 
FormattingInfo.getDefault()) {
+            return null; // indicates no formatting
+        }
+        final Map<Level, String> result = new HashMap<Level, String>();
+        final StringBuilder sb = new StringBuilder(64);
+        for (final Level level : Level.values()) {
+            final String formatted = format(formattingInfo, sb, level.name());
+            result.put(level, formatted);
+        }
+        return result;
+    }    
+
+    private static Map<Level, byte[]> createBinaryLevelMap(final 
FormattingInfo formattingInfo, final Charset charset) {
+        final Map<Level, byte[]> result = new HashMap<Level, byte[]>();
+        final StringBuilder sb = new StringBuilder(64);
+        for (final Level level : Level.values()) {
+            final String formatted = format(formattingInfo, sb, level.name());
+            result.put(level, Charsets.getBytes(formatted, charset));
+        }
+        return result;
+    }
+
+    private static String format(final FormattingInfo formattingInfo, final 
StringBuilder sb, final String raw) {
+        sb.setLength(0);
+        sb.append(raw);
+        formattingInfo.format(0, sb);
+        return sb.toString();
     }
 
     /**
      * Returns the leftmost chars of the level name for the given level.
      *
-     * @param level
-     *            The level
-     * @param length
-     *            How many chars to return
+     * @param level The level
+     * @param length How many chars to return
      * @return The abbreviated level name, or the whole level name if the 
{@code length} is greater than the level name
      *         length,
      */
@@ -115,13 +147,34 @@ public final class LevelPatternConverter extends 
LogEventPatternConverter {
         }
         return string.substring(0, length);
     }
+    
+    @Override
+    public void setCharset(final Charset charset) {
+        super.setCharset(charset);
+        if (this.levelTextMap == null) {
+            
this.levelBinaryMap.putAll(createBinaryLevelMap(getFormattingInfo(), charset));
+        } else {
+            for (final Level level : levelTextMap.keySet()) {
+                final String value = levelTextMap.get(level);
+                levelBinaryMap.put(level, Charsets.getBytes(value, charset));
+            }
+        }
+    }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder output) {
-        output.append(levelMap == null ? event.getLevel().toString() : 
levelMap.get(event.getLevel()));
+    public void format(final LogEvent event, final TextBuffer output) {
+        output.append(levelTextMap == null ? event.getLevel().toString() : 
levelTextMap.get(event.getLevel()));
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer output, final 
Charset charset) {
+        output.append(levelBinaryMap.get(event.getLevel()));
     }
 
     /**
@@ -132,7 +185,6 @@ public final class LevelPatternConverter extends 
LogEventPatternConverter {
         if (e instanceof LogEvent) {
             return "level " + ((LogEvent) 
e).getLevel().name().toLowerCase(Locale.ENGLISH);
         }
-
         return "level";
     }
 }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/08386d0e/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LineLocationPatternConverter.java
----------------------------------------------------------------------
diff --git 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LineLocationPatternConverter.java
 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LineLocationPatternConverter.java
index 2b912d7..64ac2c9 100644
--- 
a/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LineLocationPatternConverter.java
+++ 
b/log4j-core/src/main/java/org/apache/logging/log4j/core/pattern/LineLocationPatternConverter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.logging.log4j.core.pattern;
 
+import java.nio.charset.Charset;
+
 import org.apache.logging.log4j.core.LogEvent;
 import org.apache.logging.log4j.core.config.plugins.Plugin;
 
@@ -25,17 +27,12 @@ import org.apache.logging.log4j.core.config.plugins.Plugin;
 @Plugin(name = "LineLocationPatternConverter", category = 
PatternConverter.CATEGORY)
 @ConverterKeys({ "L", "line" })
 public final class LineLocationPatternConverter extends 
LogEventPatternConverter {
-    /**
-     * Singleton.
-     */
-    private static final LineLocationPatternConverter INSTANCE =
-        new LineLocationPatternConverter();
 
     /**
      * Private constructor.
      */
-    private LineLocationPatternConverter() {
-        super("Line", "line");
+    private LineLocationPatternConverter(final FormattingInfo formattingInfo) {
+        super("Line", "line", formattingInfo);
     }
 
     /**
@@ -44,20 +41,42 @@ public final class LineLocationPatternConverter extends 
LogEventPatternConverter
      * @param options options, may be null.
      * @return instance of pattern converter.
      */
-    public static LineLocationPatternConverter newInstance(
-        final String[] options) {
-        return INSTANCE;
+    public static LineLocationPatternConverter newInstance(final String[] 
options, final FormattingInfo formattingInfo) {
+        return new LineLocationPatternConverter(formattingInfo);
+    }
+
+    @Override
+    public String convert(final Object element) {
+        return String.valueOf(((StackTraceElement) element).getLineNumber());
     }
 
     /**
      * {@inheritDoc}
      */
     @Override
-    public void format(final LogEvent event, final StringBuilder output) {
+    public void format(final LogEvent event, final TextBuffer output) {
         final StackTraceElement element = event.getSource();
+        if (element != null) {
+            if (hasFormattingInfo) {
+                output.append(getCachedFormattedString(element));
+            } else {
+                output.append(element.getLineNumber());
+            }
+        }
+    }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void format(final LogEvent event, final BinaryBuffer toAppendTo, 
final Charset charset) {
+        final StackTraceElement element = event.getSource();
         if (element != null) {
-            output.append(element.getLineNumber());
+            if (hasFormattingInfo) {
+                toAppendTo.append(getCachedFormattedBytes(element, charset));
+            } else {
+                toAppendTo.append(element.getLineNumber());
+            }
         }
     }
 }

Reply via email to