From 7c29474416f4e2273f5049699155374fd2c4eaef Mon Sep 17 00:00:00 2001 From: Ceki Gulcu Date: Mon, 12 Aug 2024 19:07:04 +0200 Subject: [PATCH] add support for finding the console's charset, LOGBACK-1642 Signed-off-by: Ceki Gulcu --- .../src/test/input/joran/consoleCharset.xml | 38 ++++++++++++++ .../classic/joran/JoranConfiguratorTest.java | 13 +++++ logback-core/pom.xml | 10 ++++ .../core/encoder/LayoutWrappingEncoder.java | 4 +- .../logback/core/joran/JoranConstants.java | 5 +- .../core/joran/util/PropertySetter.java | 6 +-- .../joran/util/StringToObjectConverter.java | 16 +++++- .../ConsoleCharsetPropertyDefiner.java | 49 +++++++++++++++++++ 8 files changed, 131 insertions(+), 10 deletions(-) create mode 100644 logback-classic/src/test/input/joran/consoleCharset.xml create mode 100644 logback-core/src/main/java21/ch/qos/logback/core/property/ConsoleCharsetPropertyDefiner.java diff --git a/logback-classic/src/test/input/joran/consoleCharset.xml b/logback-classic/src/test/input/joran/consoleCharset.xml new file mode 100644 index 0000000000..3dca617016 --- /dev/null +++ b/logback-classic/src/test/input/joran/consoleCharset.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + ${consoleCharset} + TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + \ No newline at end of file diff --git a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java index ae13b581d4..18d7ade3c4 100644 --- a/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java +++ b/logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java @@ -46,6 +46,7 @@ import ch.qos.logback.core.testUtil.RandomUtil; import ch.qos.logback.core.testUtil.StringListAppender; import ch.qos.logback.core.util.CachingDateFormatter; +import ch.qos.logback.core.util.EnvUtil; import ch.qos.logback.core.util.StatusPrinter; import ch.qos.logback.core.util.StatusPrinter2; import org.junit.jupiter.api.Disabled; @@ -740,6 +741,18 @@ public void dateConverterWithLocale() throws JoranException { //StatusPrinter.print(loggerContext); } + @Test + public void consoleCharsetTest() throws JoranException { + if(EnvUtil.isJDK21OrHigher()) { + configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "consoleCharset.xml"); + checker.assertContainsMatch(Status.INFO, "About to instantiate property definer of type \\[ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner\\]"); + checker.assertContainsMatch(Status.WARN, "System.console\\(\\) returned null. Cannot compute console's charset, returning"); + checker.assertContainsMatch("Setting property consoleCharset=null in scope LOCAL" ); + checker.assertContainsMatch("Converting the string \\\"null. as Charset.defaultCharset\\(\\)"); + //StatusPrinter.print(loggerContext); + } + } + @Test public void modelSerialization() throws JoranException, IOException, ClassNotFoundException { String outputPath = OUTPUT_DIR_PREFIX+"minimal_"+diff+ MODEL_CONFIG_FILE_EXTENSION; diff --git a/logback-core/pom.xml b/logback-core/pom.xml index cbc2f1128e..e1e75ff338 100755 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -102,6 +102,16 @@ true + + + default-testCompile + test-compile + + + **/COWArrayListConcurrencyTest.java + + + diff --git a/logback-core/src/main/java/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java b/logback-core/src/main/java/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java index 15fa41f139..642cb37b60 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java +++ b/logback-core/src/main/java/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java @@ -27,7 +27,7 @@ public class LayoutWrappingEncoder extends EncoderBase { /** * The charset to use when converting a String into bytes. *

- * By default this property has the value {@code null} which corresponds to the + * By default, this property has the value {@code null} which corresponds to the * system's default charset. */ private Charset charset; @@ -51,7 +51,7 @@ public Charset getCharset() { * Set the charset to use when converting the string returned by the layout into * bytes. *

- * By default this property has the value {@code null} which corresponds to the + * By default, this property has the value {@code null} which corresponds to the * system's default charset. * * @param charset diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConstants.java b/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConstants.java index f0b53c08a3..7ee9422775 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConstants.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/JoranConstants.java @@ -13,6 +13,8 @@ */ package ch.qos.logback.core.joran; +import ch.qos.logback.core.CoreConstants; + /** * * This class contains constants used by Joran components. @@ -37,7 +39,8 @@ public abstract class JoranConstants { public static final String ACTION_CLASS_ATTRIBUTE = "actionClass"; public static final String INHERITED = "INHERITED"; - public static final String NULL = "NULL"; + // all usages in the project are case-insensitive. Elsewhere this might not be the case hence the toUpperCase call + public static final String NULL = CoreConstants.NULL_STR.toUpperCase(); static final Class[] ONE_STRING_PARAM = new Class[] { String.class }; public static final String APPENDER_BAG = "APPENDER_BAG"; diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java index ad048b9af7..367a5b08cd 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java @@ -285,8 +285,4 @@ public Class getClassNameViaImplicitRules(String name, AggregationType aggreg return aggregationAssessor.getClassNameViaImplicitRules(name, aggregationType, registry); } - - - - - } +} diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java b/logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java index b670143bb6..08fd9cb6ad 100644 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java @@ -13,13 +13,19 @@ */ package ch.qos.logback.core.joran.util; +import java.io.Console; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.nio.charset.Charset; import java.nio.charset.UnsupportedCharsetException; +import ch.qos.logback.core.Context; import ch.qos.logback.core.CoreConstants; import ch.qos.logback.core.spi.ContextAware; +import ch.qos.logback.core.spi.ContextAwareBase; + +import static ch.qos.logback.core.CoreConstants.CONSOLE; +import static ch.qos.logback.core.CoreConstants.NULL_STR; /** * Utility class which can convert string into objects. @@ -27,7 +33,7 @@ * @author Ceki Gülcü * */ -public class StringToObjectConverter { +public class StringToObjectConverter { private static final Class[] STRING_CLASS_PARAMETER = new Class[] { String.class }; @@ -51,7 +57,7 @@ static public boolean canBeBuiltFromSimpleString(Class parameterClass) { * Convert val a String parameter to an object of a given type. */ @SuppressWarnings("unchecked") - public static Object convertArg(ContextAware ca, String val, Class type) { + static public Object convertArg(ContextAware ca, String val, Class type) { if (val == null) { return null; } @@ -88,6 +94,12 @@ static private boolean isOfTypeCharset(Class type) { } static private Charset convertToCharset(ContextAware ca, String val) { + + if (NULL_STR.equalsIgnoreCase(val)) { + ca.addInfo("Converting the string \"null\" as Charset.defaultCharset()"); + return Charset.defaultCharset(); + } + try { return Charset.forName(val); } catch (UnsupportedCharsetException e) { diff --git a/logback-core/src/main/java21/ch/qos/logback/core/property/ConsoleCharsetPropertyDefiner.java b/logback-core/src/main/java21/ch/qos/logback/core/property/ConsoleCharsetPropertyDefiner.java new file mode 100644 index 0000000000..da8bd4e85f --- /dev/null +++ b/logback-core/src/main/java21/ch/qos/logback/core/property/ConsoleCharsetPropertyDefiner.java @@ -0,0 +1,49 @@ +/* + * Logback: the reliable, generic, fast and flexible logging framework. + * Copyright (C) 1999-2024, QOS.ch. All rights reserved. + * + * This program and the accompanying materials are dual-licensed under + * either the terms of the Eclipse Public License v1.0 as published by + * the Eclipse Foundation + * + * or (per the licensee's choosing) + * + * under the terms of the GNU Lesser General Public License version 2.1 + * as published by the Free Software Foundation. + */ + +package ch.qos.logback.core.property; + +import ch.qos.logback.core.PropertyDefinerBase; +import static ch.qos.logback.core.CoreConstants.NULL_STR; + +import java.io.Console; +import java.nio.charset.Charset; + +/** + * Compute the console's charset. + * + * @since 1.5.7 + */ +public class ConsoleCharsetPropertyDefiner extends PropertyDefinerBase { + @Override + public String getPropertyValue() { + // System.console().charset() requires Java 17 + Console console = System.console(); + if (console != null) { + Charset charset = console.charset(); + if (charset != null) { + String charsetName = charset.name(); + addInfo("Found value '" + charsetName + "' as returned by System.console()."); + return charsetName; + } else { + addInfo("System.console() returned null charset. Returning \"NULL\" string as defined value."); + return NULL_STR; + } + } else { + addWarn("System.console() returned null. Cannot compute console's charset, returning the \"NULL\" string, i.e. the default JVM charset"); + return NULL_STR; + } + } + +}