You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@logging.apache.org by gg...@apache.org on 2016/10/10 18:20:39 UTC

[2/2] logging-log4j2 git commit: [LOG4J2-1636] Console Appender does not pick up Oracle Java 8's sun.stdout.encoding and sun.stderr.encoding. This is a partial fix. See discussion in Jira.

[LOG4J2-1636] Console Appender does not pick up Oracle Java 8's
sun.stdout.encoding and sun.stderr.encoding. This is a partial fix. See
discussion in Jira.

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

Branch: refs/heads/master
Commit: d65bf73c02adbf7e82bd2dc66649bad512b944f2
Parents: eed7c07
Author: Gary Gregory <gg...@apache.org>
Authored: Mon Oct 10 11:20:32 2016 -0700
Committer: Gary Gregory <gg...@apache.org>
Committed: Mon Oct 10 11:20:32 2016 -0700

----------------------------------------------------------------------
 .../logging/log4j/util/PropertiesUtil.java      |  597 +-
 .../log4j/core/appender/AbstractAppender.java   |    8 +
 .../log4j/core/appender/ConsoleAppender.java    |   23 +-
 .../appender/ConsoleAppenderBuilderTest.java    |   80 +-
 src/changes/changes.xml                         | 6175 +++++++++---------
 5 files changed, 3477 insertions(+), 3406 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d65bf73c/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
----------------------------------------------------------------------
diff --git a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
index 1bc4e43..af0b29e 100644
--- a/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
+++ b/log4j-api/src/main/java/org/apache/logging/log4j/util/PropertiesUtil.java
@@ -1,287 +1,310 @@
-/*
- * 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.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.ConcurrentHashMap;
-
-/**
- * <em>Consider this class private.</em>
- * <p>
- * Helps access properties. This utility provides a method to override system properties by specifying properties in a
- * properties file.
- * </p>
- */
-public final class PropertiesUtil {
-
-    private static final PropertiesUtil LOG4J_PROPERTIES = new PropertiesUtil("log4j2.component.properties");
-
-    private final Properties props;
-
-    /**
-     * Constructs a PropertiesUtil using a given Properties object as its source of defined properties.
-     *
-     * @param props the Properties to use by default
-     */
-    public PropertiesUtil(final Properties props) {
-        this.props = props;
-    }
-
-    /**
-     * Constructs a PropertiesUtil for a given properties file name on the classpath. The properties specified in this
-     * file are used by default. If a property is not defined in this file, then the equivalent system property is used.
-     *
-     * @param propertiesFileName the location of properties file to load
-     */
-    public PropertiesUtil(final String propertiesFileName) {
-        final Properties properties = new Properties();
-        for (final URL url : LoaderUtil.findResources(propertiesFileName)) {
-            try (final InputStream in = url.openStream()) {
-                properties.load(in);
-            } catch (final IOException ioe) {
-                LowLevelLogUtil.logException("Unable to read " + url.toString(), ioe);
-            }
-        }
-        this.props = properties;
-    }
-
-    /**
-     * Loads and closes the given property input stream. If an error occurs, log to the status logger.
-     *
-     * @param in a property input stream.
-     * @param source a source object describing the source, like a resource string or a URL.
-     * @return a new Properties object
-     */
-    static Properties loadClose(final InputStream in, final Object source) {
-        final Properties props = new Properties();
-        if (null != in) {
-            try {
-                props.load(in);
-            } catch (final IOException e) {
-                LowLevelLogUtil.logException("Unable to read " + source, e);
-            } finally {
-                try {
-                    in.close();
-                } catch (final IOException e) {
-                    LowLevelLogUtil.logException("Unable to close " + source, e);
-                }
-            }
-        }
-        return props;
-    }
-
-    /**
-     * Returns the PropertiesUtil used by Log4j.
-     *
-     * @return the main Log4j PropertiesUtil instance.
-     */
-    public static PropertiesUtil getProperties() {
-        return LOG4J_PROPERTIES;
-    }
-
-    /**
-     * Gets the named property as a boolean value. If the property matches the string {@code "true"} (case-insensitive),
-     * then it is returned as the boolean value {@code true}. Any other non-{@code null} text in the property is
-     * considered {@code false}.
-     *
-     * @param name the name of the property to look up
-     * @return the boolean value of the property or {@code false} if undefined.
-     */
-    public boolean getBooleanProperty(final String name) {
-        return getBooleanProperty(name, false);
-    }
-
-    /**
-     * Gets the named property as a boolean value.
-     *
-     * @param name the name of the property to look up
-     * @param defaultValue the default value to use if the property is undefined
-     * @return the boolean value of the property or {@code defaultValue} if undefined.
-     */
-    public boolean getBooleanProperty(final String name, final boolean defaultValue) {
-        final String prop = getStringProperty(name);
-        return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
-    }
-
-    /**
-     * Gets the named property as a double.
-     *
-     * @param name the name of the property to look up
-     * @param defaultValue the default value to use if the property is undefined
-     * @return the parsed double value of the property or {@code defaultValue} if it was undefined or could not be parsed.
-     */
-    public double getDoubleProperty(final String name, final double defaultValue) {
-        final String prop = getStringProperty(name);
-        if (prop != null) {
-            try {
-                return Double.parseDouble(prop);
-            } catch (final Exception ignored) {
-                return defaultValue;
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Gets the named property as an integer.
-     *
-     * @param name the name of the property to look up
-     * @param defaultValue the default value to use if the property is undefined
-     * @return the parsed integer value of the property or {@code defaultValue} if it was undefined or could not be
-     *         parsed.
-     */
-    public int getIntegerProperty(final String name, final int defaultValue) {
-        final String prop = getStringProperty(name);
-        if (prop != null) {
-            try {
-                return Integer.parseInt(prop);
-            } catch (final Exception ignored) {
-                return defaultValue;
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Gets the named property as a long.
-     *
-     * @param name the name of the property to look up
-     * @param defaultValue the default value to use if the property is undefined
-     * @return the parsed long value of the property or {@code defaultValue} if it was undefined or could not be parsed.
-     */
-    public long getLongProperty(final String name, final long defaultValue) {
-        final String prop = getStringProperty(name);
-        if (prop != null) {
-            try {
-                return Long.parseLong(prop);
-            } catch (final Exception ignored) {
-                return defaultValue;
-            }
-        }
-        return defaultValue;
-    }
-
-    /**
-     * Gets the named property as a String.
-     *
-     * @param name the name of the property to look up
-     * @return the String value of the property or {@code null} if undefined.
-     */
-    public String getStringProperty(final String name) {
-        String prop = null;
-        try {
-            prop = System.getProperty(name);
-        } catch (final SecurityException ignored) {
-            // Ignore
-        }
-        return prop == null ? props.getProperty(name) : prop;
-    }
-
-    /**
-     * Gets the named property as a String.
-     *
-     * @param name the name of the property to look up
-     * @param defaultValue the default value to use if the property is undefined
-     * @return the String value of the property or {@code defaultValue} if undefined.
-     */
-    public String getStringProperty(final String name, final String defaultValue) {
-        final String prop = getStringProperty(name);
-        return (prop == null) ? defaultValue : prop;
-    }
-
-    /**
-     * Return the system properties or an empty Properties object if an error occurs.
-     *
-     * @return The system properties.
-     */
-    public static Properties getSystemProperties() {
-        try {
-            return new Properties(System.getProperties());
-        } catch (final SecurityException ex) {
-            LowLevelLogUtil.logException("Unable to access system properties.", ex);
-            // Sandboxed - can't read System Properties
-            return new Properties();
-        }
-    }
-
-    /**
-     * Extracts properties that start with or are equals to the specific prefix and returns them in a new Properties
-     * object with the prefix removed.
-     *
-     * @param properties The Properties to evaluate.
-     * @param prefix The prefix to extract.
-     * @return The subset of properties.
-     */
-    public static Properties extractSubset(final Properties properties, final String prefix) {
-        final Properties subset = new Properties();
-
-        if (prefix == null || prefix.length() == 0) {
-            return subset;
-        }
-
-        final String prefixToMatch = prefix.charAt(prefix.length() - 1) != '.' ? prefix + '.' : prefix;
-
-        final List<String> keys = new ArrayList<>();
-
-        for (final String key : properties.stringPropertyNames()) {
-            if (key.startsWith(prefixToMatch)) {
-                subset.setProperty(key.substring(prefixToMatch.length()), properties.getProperty(key));
-                keys.add(key);
-            }
-        }
-        for (final String key : keys) {
-            properties.remove(key);
-        }
-
-        return subset;
-    }
-
-    /**
-     * Partitions a properties map based on common key prefixes up to the first period.
-     *
-     * @param properties properties to partition
-     * @return the partitioned properties where each key is the common prefix (minus the period) and the values are
-     * new property maps without the prefix and period in the key
-     * @since 2.6
-     */
-    public static Map<String, Properties> partitionOnCommonPrefixes(final Properties properties) {
-        final Map<String, Properties> parts = new ConcurrentHashMap<>();
-        for (final String key : properties.stringPropertyNames()) {
-            final String prefix = key.substring(0, key.indexOf('.'));
-            if (!parts.containsKey(prefix)) {
-                parts.put(prefix, new Properties());
-            }
-            parts.get(prefix).setProperty(key.substring(key.indexOf('.') + 1), properties.getProperty(key));
-        }
-        return parts;
-    }
-
-    /**
-     * Returns true if system properties tell us we are running on Windows.
-     * @return true if system properties tell us we are running on Windows.
-     */
-    public boolean isOsWindows() {
-        return getStringProperty("os.name").startsWith("Windows");
-    }
-
-}
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * <em>Consider this class private.</em>
+ * <p>
+ * Helps access properties. This utility provides a method to override system properties by specifying properties in a
+ * properties file.
+ * </p>
+ */
+public final class PropertiesUtil {
+
+    private static final PropertiesUtil LOG4J_PROPERTIES = new PropertiesUtil("log4j2.component.properties");
+
+    private final Properties props;
+
+    /**
+     * Constructs a PropertiesUtil using a given Properties object as its source of defined properties.
+     *
+     * @param props the Properties to use by default
+     */
+    public PropertiesUtil(final Properties props) {
+        this.props = props;
+    }
+
+    /**
+     * Constructs a PropertiesUtil for a given properties file name on the classpath. The properties specified in this
+     * file are used by default. If a property is not defined in this file, then the equivalent system property is used.
+     *
+     * @param propertiesFileName the location of properties file to load
+     */
+    public PropertiesUtil(final String propertiesFileName) {
+        final Properties properties = new Properties();
+        for (final URL url : LoaderUtil.findResources(propertiesFileName)) {
+            try (final InputStream in = url.openStream()) {
+                properties.load(in);
+            } catch (final IOException ioe) {
+                LowLevelLogUtil.logException("Unable to read " + url.toString(), ioe);
+            }
+        }
+        this.props = properties;
+    }
+
+    /**
+     * Loads and closes the given property input stream. If an error occurs, log to the status logger.
+     *
+     * @param in a property input stream.
+     * @param source a source object describing the source, like a resource string or a URL.
+     * @return a new Properties object
+     */
+    static Properties loadClose(final InputStream in, final Object source) {
+        final Properties props = new Properties();
+        if (null != in) {
+            try {
+                props.load(in);
+            } catch (final IOException e) {
+                LowLevelLogUtil.logException("Unable to read " + source, e);
+            } finally {
+                try {
+                    in.close();
+                } catch (final IOException e) {
+                    LowLevelLogUtil.logException("Unable to close " + source, e);
+                }
+            }
+        }
+        return props;
+    }
+
+    /**
+     * Returns the PropertiesUtil used by Log4j.
+     *
+     * @return the main Log4j PropertiesUtil instance.
+     */
+    public static PropertiesUtil getProperties() {
+        return LOG4J_PROPERTIES;
+    }
+
+    /**
+     * Gets the named property as a boolean value. If the property matches the string {@code "true"} (case-insensitive),
+     * then it is returned as the boolean value {@code true}. Any other non-{@code null} text in the property is
+     * considered {@code false}.
+     *
+     * @param name the name of the property to look up
+     * @return the boolean value of the property or {@code false} if undefined.
+     */
+    public boolean getBooleanProperty(final String name) {
+        return getBooleanProperty(name, false);
+    }
+
+    /**
+     * Gets the named property as a boolean value.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the boolean value of the property or {@code defaultValue} if undefined.
+     */
+    public boolean getBooleanProperty(final String name, final boolean defaultValue) {
+        final String prop = getStringProperty(name);
+        return (prop == null) ? defaultValue : "true".equalsIgnoreCase(prop);
+    }
+
+    /**
+     * Gets the named property as a Charset value.
+     *
+     * @param name the name of the property to look up
+     * @return the Charset value of the property or {@link Charset#defaultCharset()} if undefined.
+     */
+    public Charset getCharsetProperty(final String name) {
+        return getCharsetProperty(name, Charset.defaultCharset());
+    }
+
+    /**
+     * Gets the named property as a Charset value.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the Charset value of the property or {@code defaultValue} if undefined.
+     */
+    public Charset getCharsetProperty(String name, Charset defaultValue) {
+        final String prop = getStringProperty(name);
+        return prop == null ? defaultValue : Charset.forName(name);
+    }
+
+    /**
+     * Gets the named property as a double.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the parsed double value of the property or {@code defaultValue} if it was undefined or could not be parsed.
+     */
+    public double getDoubleProperty(final String name, final double defaultValue) {
+        final String prop = getStringProperty(name);
+        if (prop != null) {
+            try {
+                return Double.parseDouble(prop);
+            } catch (final Exception ignored) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the named property as an integer.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the parsed integer value of the property or {@code defaultValue} if it was undefined or could not be
+     *         parsed.
+     */
+    public int getIntegerProperty(final String name, final int defaultValue) {
+        final String prop = getStringProperty(name);
+        if (prop != null) {
+            try {
+                return Integer.parseInt(prop);
+            } catch (final Exception ignored) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the named property as a long.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the parsed long value of the property or {@code defaultValue} if it was undefined or could not be parsed.
+     */
+    public long getLongProperty(final String name, final long defaultValue) {
+        final String prop = getStringProperty(name);
+        if (prop != null) {
+            try {
+                return Long.parseLong(prop);
+            } catch (final Exception ignored) {
+                return defaultValue;
+            }
+        }
+        return defaultValue;
+    }
+
+    /**
+     * Gets the named property as a String.
+     *
+     * @param name the name of the property to look up
+     * @return the String value of the property or {@code null} if undefined.
+     */
+    public String getStringProperty(final String name) {
+        String prop = null;
+        try {
+            prop = System.getProperty(name);
+        } catch (final SecurityException ignored) {
+            // Ignore
+        }
+        return prop == null ? props.getProperty(name) : prop;
+    }
+
+    /**
+     * Gets the named property as a String.
+     *
+     * @param name the name of the property to look up
+     * @param defaultValue the default value to use if the property is undefined
+     * @return the String value of the property or {@code defaultValue} if undefined.
+     */
+    public String getStringProperty(final String name, final String defaultValue) {
+        final String prop = getStringProperty(name);
+        return (prop == null) ? defaultValue : prop;
+    }
+
+    /**
+     * Return the system properties or an empty Properties object if an error occurs.
+     *
+     * @return The system properties.
+     */
+    public static Properties getSystemProperties() {
+        try {
+            return new Properties(System.getProperties());
+        } catch (final SecurityException ex) {
+            LowLevelLogUtil.logException("Unable to access system properties.", ex);
+            // Sandboxed - can't read System Properties
+            return new Properties();
+        }
+    }
+
+    /**
+     * Extracts properties that start with or are equals to the specific prefix and returns them in a new Properties
+     * object with the prefix removed.
+     *
+     * @param properties The Properties to evaluate.
+     * @param prefix The prefix to extract.
+     * @return The subset of properties.
+     */
+    public static Properties extractSubset(final Properties properties, final String prefix) {
+        final Properties subset = new Properties();
+
+        if (prefix == null || prefix.length() == 0) {
+            return subset;
+        }
+
+        final String prefixToMatch = prefix.charAt(prefix.length() - 1) != '.' ? prefix + '.' : prefix;
+
+        final List<String> keys = new ArrayList<>();
+
+        for (final String key : properties.stringPropertyNames()) {
+            if (key.startsWith(prefixToMatch)) {
+                subset.setProperty(key.substring(prefixToMatch.length()), properties.getProperty(key));
+                keys.add(key);
+            }
+        }
+        for (final String key : keys) {
+            properties.remove(key);
+        }
+
+        return subset;
+    }
+
+    /**
+     * Partitions a properties map based on common key prefixes up to the first period.
+     *
+     * @param properties properties to partition
+     * @return the partitioned properties where each key is the common prefix (minus the period) and the values are
+     * new property maps without the prefix and period in the key
+     * @since 2.6
+     */
+    public static Map<String, Properties> partitionOnCommonPrefixes(final Properties properties) {
+        final Map<String, Properties> parts = new ConcurrentHashMap<>();
+        for (final String key : properties.stringPropertyNames()) {
+            final String prefix = key.substring(0, key.indexOf('.'));
+            if (!parts.containsKey(prefix)) {
+                parts.put(prefix, new Properties());
+            }
+            parts.get(prefix).setProperty(key.substring(key.indexOf('.') + 1), properties.getProperty(key));
+        }
+        return parts;
+    }
+
+    /**
+     * Returns true if system properties tell us we are running on Windows.
+     * @return true if system properties tell us we are running on Windows.
+     */
+    public boolean isOsWindows() {
+        return getStringProperty("os.name").startsWith("Windows");
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d65bf73c/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractAppender.java
index 71af242..94f2fec 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/AbstractAppender.java
@@ -17,6 +17,7 @@
 package org.apache.logging.log4j.core.appender;
 
 import java.io.Serializable;
+import java.nio.charset.Charset;
 
 import org.apache.logging.log4j.core.Appender;
 import org.apache.logging.log4j.core.ErrorHandler;
@@ -87,6 +88,13 @@ public abstract class AbstractAppender extends AbstractFilterable implements App
             return layout;
         }
         
+        public Layout<? extends Serializable> getOrCreateLayout(Charset charset) {
+            if (layout == null) {
+                return PatternLayout.newBuilder().withCharset(charset).build();
+            }
+            return layout;
+        }
+        
     }
     
     private final String name;

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d65bf73c/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
index fec5997..b865caf 100644
--- a/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
+++ b/log4j-core/src/main/java/org/apache/logging/log4j/core/appender/ConsoleAppender.java
@@ -64,9 +64,26 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt
      */
     public enum Target {
         /** Standard output. */
-        SYSTEM_OUT,
+        SYSTEM_OUT {
+            @Override
+            public Charset getDefaultCharset() {
+                return getCharset("sun.stdout.encoding");
+            }
+        },
         /** Standard error output. */
-        SYSTEM_ERR
+        SYSTEM_ERR {
+            @Override
+            public Charset getDefaultCharset() {
+                return getCharset("sun.stderr.encoding");
+            }
+        };
+        
+        public abstract Charset getDefaultCharset();
+        
+        protected Charset getCharset(String property) {
+            return new PropertiesUtil(PropertiesUtil.getSystemProperties()).getCharsetProperty(property);
+        }
+
     }
 
     private ConsoleAppender(final String name, final Layout<? extends Serializable> layout, final Filter filter,
@@ -197,7 +214,7 @@ public final class ConsoleAppender extends AbstractOutputStreamAppender<OutputSt
             if (follow && direct) {
                 throw new IllegalArgumentException("Cannot use both follow and direct on ConsoleAppender '" + getName() + "'");
             }
-            final Layout<? extends Serializable> layout = getOrCreateLayout();
+            final Layout<? extends Serializable> layout = getOrCreateLayout(target.getDefaultCharset());
             return new ConsoleAppender(getName(), layout, getFilter(), getManager(target, follow, direct, layout),
                     isIgnoreExceptions(), target);
         }

http://git-wip-us.apache.org/repos/asf/logging-log4j2/blob/d65bf73c/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderBuilderTest.java
----------------------------------------------------------------------
diff --git a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderBuilderTest.java b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderBuilderTest.java
index 2531a31..157b8c0 100644
--- a/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderBuilderTest.java
+++ b/log4j-core/src/test/java/org/apache/logging/log4j/core/appender/ConsoleAppenderBuilderTest.java
@@ -1,31 +1,49 @@
-/*
- * 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.appender;
-
-import org.junit.Assert;
-import org.junit.Test;
-
-public class ConsoleAppenderBuilderTest {
-
-    /**
-     * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
-     */
-    @Test
-    public void testDefaultImmediateFlush() {
-        Assert.assertTrue(ConsoleAppender.newBuilder().isImmediateFlush());
-    }
-}
+/*
+ * 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.appender;
+
+import java.nio.charset.Charset;
+
+import org.apache.logging.log4j.core.layout.PatternLayout;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ConsoleAppenderBuilderTest {
+
+    /**
+     * Tests https://issues.apache.org/jira/browse/LOG4J2-1620
+     */
+    @Test
+    public void testDefaultImmediateFlush() {
+        Assert.assertTrue(ConsoleAppender.newBuilder().isImmediateFlush());
+    }
+
+    /**
+     * Tests https://issues.apache.org/jira/browse/LOG4J2-1636
+     * 
+     * Tested with Oracle 7 and 8 and IBM Java 8.
+     */
+    @Test
+    public void testDefaultLayoutDefaultCharset() {
+        final ConsoleAppender appender = ConsoleAppender.newBuilder().build();
+        final PatternLayout layout = (PatternLayout) appender.getLayout();
+        final String charsetName = System.getProperty("sun.stdout.encoding");
+        final String expectedName = charsetName != null ? charsetName : Charset.defaultCharset().name();
+        Assert.assertEquals(expectedName, layout.getCharset().name());
+    }
+
+}