From a250bbb7e4e61c27339ab2ced004ef694b75f8bd Mon Sep 17 00:00:00 2001 From: Dmytro Nosan Date: Wed, 19 Feb 2025 12:12:21 +0200 Subject: [PATCH] Use Console charset for console logging when available Prior to this commit, LogbackLoggingSystemProperties doesn't respect Console.charset(). It used Charset.getDefaultCharset() for logback and UTF-8 for log42j as defaults. This commit changes the behaviour of LogbackLoggingSystemProperties to use Console.charset() when available. If no console is present, the default charset is used instead. These changes bring consistency across logging implementations. See gh-43118 Signed-off-by: Dmytro Nosan --- .../boot/logging/LoggingSystemProperties.java | 18 +++++++++---- .../LogbackLoggingSystemProperties.java | 8 +++--- .../logging/LoggingSystemPropertiesTests.java | 27 ++++++++++++++++--- .../LogbackLoggingSystemPropertiesTests.java | 27 +++++++++++++++++-- 4 files changed, 65 insertions(+), 15 deletions(-) diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystemProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystemProperties.java index 89092d9c8a9..385573a43a6 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystemProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/LoggingSystemProperties.java @@ -16,8 +16,8 @@ package org.springframework.boot.logging; +import java.io.Console; import java.nio.charset.Charset; -import java.nio.charset.StandardCharsets; import java.util.function.BiConsumer; import java.util.function.Function; @@ -91,8 +91,12 @@ public class LoggingSystemProperties { this.setter = (setter != null) ? setter : systemPropertySetter; } + protected Console getConsole() { + return System.console(); + } + protected Charset getDefaultCharset() { - return StandardCharsets.UTF_8; + return Charset.defaultCharset(); } public final void apply() { @@ -116,12 +120,11 @@ public class LoggingSystemProperties { } protected void apply(LogFile logFile, PropertyResolver resolver) { - String defaultCharsetName = getDefaultCharset().name(); setSystemProperty(LoggingSystemProperty.APPLICATION_NAME, resolver); setSystemProperty(LoggingSystemProperty.APPLICATION_GROUP, resolver); setSystemProperty(LoggingSystemProperty.PID, new ApplicationPid().toString()); - setSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET, resolver, defaultCharsetName); - setSystemProperty(LoggingSystemProperty.FILE_CHARSET, resolver, defaultCharsetName); + setSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET, resolver, getConsoleCharset().name()); + setSystemProperty(LoggingSystemProperty.FILE_CHARSET, resolver, getDefaultCharset().name()); setSystemProperty(LoggingSystemProperty.CONSOLE_THRESHOLD, resolver, this::thresholdMapper); setSystemProperty(LoggingSystemProperty.FILE_THRESHOLD, resolver, this::thresholdMapper); setSystemProperty(LoggingSystemProperty.EXCEPTION_CONVERSION_WORD, resolver); @@ -137,6 +140,11 @@ public class LoggingSystemProperties { } } + private Charset getConsoleCharset() { + Console console = getConsole(); + return (console != null) ? console.charset() : getDefaultCharset(); + } + private void setSystemProperty(LoggingSystemProperty property, PropertyResolver resolver) { setSystemProperty(property, resolver, Function.identity()); } diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java index 75ab70a9d2b..dad314206a2 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/logging/logback/LogbackLoggingSystemProperties.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,7 @@ package org.springframework.boot.logging.logback; -import java.nio.charset.Charset; +import java.io.Console; import java.util.function.BiConsumer; import java.util.function.Function; @@ -71,8 +71,8 @@ public class LogbackLoggingSystemProperties extends LoggingSystemProperties { } @Override - protected Charset getDefaultCharset() { - return Charset.defaultCharset(); + protected Console getConsole() { + return super.getConsole(); } @Override diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/LoggingSystemPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/LoggingSystemPropertiesTests.java index 72308c2f98f..e61866887a3 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/LoggingSystemPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/LoggingSystemPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2024 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,6 +16,9 @@ package org.springframework.boot.logging; +import java.io.Console; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -31,6 +34,9 @@ import org.springframework.core.env.StandardEnvironment; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; /** * Tests for {@link LoggingSystemProperties}. @@ -72,9 +78,22 @@ class LoggingSystemPropertiesTests { } @Test - void consoleCharsetWhenNoPropertyUsesUtf8() { - new LoggingSystemProperties(new MockEnvironment()).apply(null); - assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET)).isEqualTo("UTF-8"); + void consoleCharsetWhenNoPropertyUsesCharsetDefault() { + LoggingSystemProperties loggingSystemProperties = spy(new LoggingSystemProperties(new MockEnvironment())); + given(loggingSystemProperties.getConsole()).willReturn(null); + loggingSystemProperties.apply(null); + assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET)).isEqualTo(Charset.defaultCharset().name()); + } + + @Test + void consoleCharsetWhenNoPropertyUsesSystemConsoleCharsetWhenAvailable() { + LoggingSystemProperties loggingSystemProperties = spy(new LoggingSystemProperties(new MockEnvironment())); + Console console = mock(Console.class); + given(console.charset()).willReturn(StandardCharsets.UTF_16BE); + given(loggingSystemProperties.getConsole()).willReturn(console); + loggingSystemProperties.apply(null); + assertThat(getSystemProperty(LoggingSystemProperty.CONSOLE_CHARSET)) + .isEqualTo(StandardCharsets.UTF_16BE.name()); } @Test diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java index 45c82c533de..41d7c768c72 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/logging/logback/LogbackLoggingSystemPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2023 the original author or authors. + * Copyright 2012-2025 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,7 +16,9 @@ package org.springframework.boot.logging.logback; +import java.io.Console; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; import java.util.HashSet; import java.util.Set; @@ -31,6 +33,9 @@ import org.springframework.core.convert.support.ConfigurableConversionService; import org.springframework.mock.env.MockEnvironment; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; /** * Tests for {@link LogbackLoggingSystemProperties}. @@ -102,11 +107,29 @@ class LogbackLoggingSystemPropertiesTests { @Test void consoleCharsetWhenNoPropertyUsesDefault() { - new LoggingSystemProperties(new MockEnvironment()).apply(null); + LogbackLoggingSystemProperties logbackLoggingSystemProperties = spy( + new LogbackLoggingSystemProperties(new MockEnvironment(), null, null)); + given(logbackLoggingSystemProperties.getConsole()).willReturn(null); + + logbackLoggingSystemProperties.apply(null); assertThat(System.getProperty(LoggingSystemProperty.CONSOLE_CHARSET.getEnvironmentVariableName())) .isEqualTo(Charset.defaultCharset().name()); } + @Test + void consoleCharsetWhenNoPropertyUsesSystemConsoleCharsetWhenAvailable() { + LogbackLoggingSystemProperties logbackLoggingSystemProperties = spy( + new LogbackLoggingSystemProperties(new MockEnvironment(), null, null)); + + Console console = mock(Console.class); + given(console.charset()).willReturn(StandardCharsets.UTF_16BE); + given(logbackLoggingSystemProperties.getConsole()).willReturn(console); + + logbackLoggingSystemProperties.apply(null); + assertThat(System.getProperty(LoggingSystemProperty.CONSOLE_CHARSET.getEnvironmentVariableName())) + .isEqualTo(StandardCharsets.UTF_16BE.name()); + } + @Test void fileCharsetWhenNoPropertyUsesDefault() { new LoggingSystemProperties(new MockEnvironment()).apply(null);