Skip to content

Commit 7c29474

Browse files
committed
add support for finding the console's charset, LOGBACK-1642
Signed-off-by: Ceki Gulcu <ceki@qos.ch>
1 parent 44fbe63 commit 7c29474

File tree

8 files changed

+131
-10
lines changed

8 files changed

+131
-10
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?xml version="1.0" encoding="UTF-8" ?>
2+
<!--
3+
~ Logback: the reliable, generic, fast and flexible logging framework.
4+
~ Copyright (C) 1999-2024, QOS.ch. All rights reserved.
5+
~
6+
~ This program and the accompanying materials are dual-licensed under
7+
~ either the terms of the Eclipse Public License v1.0 as published by
8+
~ the Eclipse Foundation
9+
~
10+
~ or (per the licensee's choosing)
11+
~
12+
~ under the terms of the GNU Lesser General Public License version 2.1
13+
~ as published by the Free Software Foundation.
14+
-->
15+
16+
<!DOCTYPE configuration>
17+
18+
<configuration>
19+
<import class="ch.qos.logback.core.status.OnConsoleStatusListener"/>
20+
<import class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"/>
21+
<import class="ch.qos.logback.core.ConsoleAppender"/>
22+
<import class="ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner"/>
23+
24+
<define name="consoleCharset" class="ConsoleCharsetPropertyDefiner"/>
25+
26+
<appender name="CON" class="ConsoleAppender">
27+
<encoder class="PatternLayoutEncoder">
28+
<charset>${consoleCharset}</charset>
29+
<pattern>TEST %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</pattern>
30+
</encoder>
31+
</appender>
32+
33+
<root>
34+
<level value="DEBUG"/>
35+
<appender-ref ref="CON"/>
36+
</root>
37+
<statusListener class="OnConsoleStatusListener"/>
38+
</configuration>

logback-classic/src/test/java/ch/qos/logback/classic/joran/JoranConfiguratorTest.java

+13
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import ch.qos.logback.core.testUtil.RandomUtil;
4747
import ch.qos.logback.core.testUtil.StringListAppender;
4848
import ch.qos.logback.core.util.CachingDateFormatter;
49+
import ch.qos.logback.core.util.EnvUtil;
4950
import ch.qos.logback.core.util.StatusPrinter;
5051
import ch.qos.logback.core.util.StatusPrinter2;
5152
import org.junit.jupiter.api.Disabled;
@@ -740,6 +741,18 @@ public void dateConverterWithLocale() throws JoranException {
740741
//StatusPrinter.print(loggerContext);
741742
}
742743

744+
@Test
745+
public void consoleCharsetTest() throws JoranException {
746+
if(EnvUtil.isJDK21OrHigher()) {
747+
configure(ClassicTestConstants.JORAN_INPUT_PREFIX + "consoleCharset.xml");
748+
checker.assertContainsMatch(Status.INFO, "About to instantiate property definer of type \\[ch.qos.logback.core.property.ConsoleCharsetPropertyDefiner\\]");
749+
checker.assertContainsMatch(Status.WARN, "System.console\\(\\) returned null. Cannot compute console's charset, returning");
750+
checker.assertContainsMatch("Setting property consoleCharset=null in scope LOCAL" );
751+
checker.assertContainsMatch("Converting the string \\\"null. as Charset.defaultCharset\\(\\)");
752+
//StatusPrinter.print(loggerContext);
753+
}
754+
}
755+
743756
@Test
744757
public void modelSerialization() throws JoranException, IOException, ClassNotFoundException {
745758
String outputPath = OUTPUT_DIR_PREFIX+"minimal_"+diff+ MODEL_CONFIG_FILE_EXTENSION;

logback-core/pom.xml

+10
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,16 @@
102102
<multiReleaseOutput>true</multiReleaseOutput>
103103
</configuration>
104104
</execution>
105+
106+
<execution>
107+
<id>default-testCompile</id>
108+
<phase>test-compile</phase>
109+
<configuration>
110+
<testExcludes>
111+
<exclude>**/COWArrayListConcurrencyTest.java</exclude>
112+
</testExcludes>
113+
</configuration>
114+
</execution>
105115
</executions>
106116
</plugin>
107117
<plugin>

logback-core/src/main/java/ch/qos/logback/core/encoder/LayoutWrappingEncoder.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ public class LayoutWrappingEncoder<E> extends EncoderBase<E> {
2727
/**
2828
* The charset to use when converting a String into bytes.
2929
* <p>
30-
* By default this property has the value {@code null} which corresponds to the
30+
* By default, this property has the value {@code null} which corresponds to the
3131
* system's default charset.
3232
*/
3333
private Charset charset;
@@ -51,7 +51,7 @@ public Charset getCharset() {
5151
* Set the charset to use when converting the string returned by the layout into
5252
* bytes.
5353
* <p>
54-
* By default this property has the value {@code null} which corresponds to the
54+
* By default, this property has the value {@code null} which corresponds to the
5555
* system's default charset.
5656
*
5757
* @param charset

logback-core/src/main/java/ch/qos/logback/core/joran/JoranConstants.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
*/
1414
package ch.qos.logback.core.joran;
1515

16+
import ch.qos.logback.core.CoreConstants;
17+
1618
/**
1719
*
1820
* This class contains constants used by Joran components.
@@ -37,7 +39,8 @@ public abstract class JoranConstants {
3739
public static final String ACTION_CLASS_ATTRIBUTE = "actionClass";
3840

3941
public static final String INHERITED = "INHERITED";
40-
public static final String NULL = "NULL";
42+
// all usages in the project are case-insensitive. Elsewhere this might not be the case hence the toUpperCase call
43+
public static final String NULL = CoreConstants.NULL_STR.toUpperCase();
4144
static final Class<?>[] ONE_STRING_PARAM = new Class[] { String.class };
4245

4346
public static final String APPENDER_BAG = "APPENDER_BAG";

logback-core/src/main/java/ch/qos/logback/core/joran/util/PropertySetter.java

+1-5
Original file line numberDiff line numberDiff line change
@@ -285,8 +285,4 @@ public Class<?> getClassNameViaImplicitRules(String name, AggregationType aggreg
285285
return aggregationAssessor.getClassNameViaImplicitRules(name, aggregationType, registry);
286286
}
287287

288-
289-
290-
291-
292-
}
288+
}

logback-core/src/main/java/ch/qos/logback/core/joran/util/StringToObjectConverter.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,27 @@
1313
*/
1414
package ch.qos.logback.core.joran.util;
1515

16+
import java.io.Console;
1617
import java.lang.reflect.Method;
1718
import java.lang.reflect.Modifier;
1819
import java.nio.charset.Charset;
1920
import java.nio.charset.UnsupportedCharsetException;
2021

22+
import ch.qos.logback.core.Context;
2123
import ch.qos.logback.core.CoreConstants;
2224
import ch.qos.logback.core.spi.ContextAware;
25+
import ch.qos.logback.core.spi.ContextAwareBase;
26+
27+
import static ch.qos.logback.core.CoreConstants.CONSOLE;
28+
import static ch.qos.logback.core.CoreConstants.NULL_STR;
2329

2430
/**
2531
* Utility class which can convert string into objects.
2632
*
2733
* @author Ceki G&uuml;lc&uuml;
2834
*
2935
*/
30-
public class StringToObjectConverter {
36+
public class StringToObjectConverter {
3137

3238
private static final Class<?>[] STRING_CLASS_PARAMETER = new Class[] { String.class };
3339

@@ -51,7 +57,7 @@ static public boolean canBeBuiltFromSimpleString(Class<?> parameterClass) {
5157
* Convert <code>val</code> a String parameter to an object of a given type.
5258
*/
5359
@SuppressWarnings("unchecked")
54-
public static Object convertArg(ContextAware ca, String val, Class<?> type) {
60+
static public Object convertArg(ContextAware ca, String val, Class<?> type) {
5561
if (val == null) {
5662
return null;
5763
}
@@ -88,6 +94,12 @@ static private boolean isOfTypeCharset(Class<?> type) {
8894
}
8995

9096
static private Charset convertToCharset(ContextAware ca, String val) {
97+
98+
if (NULL_STR.equalsIgnoreCase(val)) {
99+
ca.addInfo("Converting the string \"null\" as Charset.defaultCharset()");
100+
return Charset.defaultCharset();
101+
}
102+
91103
try {
92104
return Charset.forName(val);
93105
} catch (UnsupportedCharsetException e) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*
2+
* Logback: the reliable, generic, fast and flexible logging framework.
3+
* Copyright (C) 1999-2024, QOS.ch. All rights reserved.
4+
*
5+
* This program and the accompanying materials are dual-licensed under
6+
* either the terms of the Eclipse Public License v1.0 as published by
7+
* the Eclipse Foundation
8+
*
9+
* or (per the licensee's choosing)
10+
*
11+
* under the terms of the GNU Lesser General Public License version 2.1
12+
* as published by the Free Software Foundation.
13+
*/
14+
15+
package ch.qos.logback.core.property;
16+
17+
import ch.qos.logback.core.PropertyDefinerBase;
18+
import static ch.qos.logback.core.CoreConstants.NULL_STR;
19+
20+
import java.io.Console;
21+
import java.nio.charset.Charset;
22+
23+
/**
24+
* Compute the console's charset.
25+
*
26+
* @since 1.5.7
27+
*/
28+
public class ConsoleCharsetPropertyDefiner extends PropertyDefinerBase {
29+
@Override
30+
public String getPropertyValue() {
31+
// System.console().charset() requires Java 17
32+
Console console = System.console();
33+
if (console != null) {
34+
Charset charset = console.charset();
35+
if (charset != null) {
36+
String charsetName = charset.name();
37+
addInfo("Found value '" + charsetName + "' as returned by System.console().");
38+
return charsetName;
39+
} else {
40+
addInfo("System.console() returned null charset. Returning \"NULL\" string as defined value.");
41+
return NULL_STR;
42+
}
43+
} else {
44+
addWarn("System.console() returned null. Cannot compute console's charset, returning the \"NULL\" string, i.e. the default JVM charset");
45+
return NULL_STR;
46+
}
47+
}
48+
49+
}

0 commit comments

Comments
 (0)