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);