From 1022112c9438ed4567838668aa5f37a6e26c598f Mon Sep 17 00:00:00 2001 From: Daniel Meier Date: Sat, 28 Jun 2025 22:01:15 +0200 Subject: [PATCH] Don't use URLDecoder to decode file URLs in ConfigurationWatchList Java's `File#toURI` method does not encode all reserved URI characters like the `+` character, because they only need to be encoded in other parts of the URI. The `java.net.URLDecoder` on the other hand expects the `x-www-form-urlencode` encoding and therefore replaces these characters. Automatic reloading of logback configuration files in directories with the `+` did therefore not work. Fixes #950 Signed-off-by: Daniel Meier --- logback-core/pom.xml | 7 ++++++ .../joran/spi/ConfigurationWatchList.java | 13 ++++++---- .../joran/spi/ConfigurationWatchListTest.java | 25 ++++++++++++++----- 3 files changed, 34 insertions(+), 11 deletions(-) diff --git a/logback-core/pom.xml b/logback-core/pom.xml index 85d2e49105..5d36af35fd 100755 --- a/logback-core/pom.xml +++ b/logback-core/pom.xml @@ -69,6 +69,13 @@ + + org.junit.jupiter + junit-jupiter-params + ${junit-jupiter-params.version} + test + + org.mockito mockito-core diff --git a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java index 9c11b1eb4b..77b639faaa 100755 --- a/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java +++ b/logback-core/src/main/java/ch/qos/logback/core/joran/spi/ConfigurationWatchList.java @@ -19,7 +19,6 @@ import java.io.File; import java.net.HttpURLConnection; import java.net.URL; -import java.net.URLDecoder; import java.security.NoSuchAlgorithmException; import java.util.ArrayList; import java.util.Arrays; @@ -236,15 +235,19 @@ private byte[] computeHash(String response) { } } - @SuppressWarnings("deprecation") File convertToFile(URL url) { String protocol = url.getProtocol(); - if ("file".equals(protocol)) { - return new File(URLDecoder.decode(url.getFile())); - } else { + if (!"file".equals(protocol)) { addInfo("URL [" + url + "] is not of type file"); return null; } + + try { + return new File(url.toURI()); + } catch (Exception e) { + addWarn("URL [" + url + "] can not be converted to a file", e); + return null; + } } /** diff --git a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java index 60050fe7d3..91f5ba6fce 100644 --- a/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java +++ b/logback-core/src/test/java/ch/qos/logback/core/joran/spi/ConfigurationWatchListTest.java @@ -13,26 +13,39 @@ */ package ch.qos.logback.core.joran.spi; -import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; import java.io.File; import java.net.MalformedURLException; import java.net.URL; +import java.util.stream.Stream; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Named.named; +import static org.junit.jupiter.params.provider.Arguments.arguments; /** * @author Ceki Gülcü */ -public class ConfigurationWatchListTest { +class ConfigurationWatchListTest { - @Test - // See http://jira.qos.ch/browse/LBCORE-119 - public void fileToURLAndBack() throws MalformedURLException { - File file = new File("a b.xml"); + @ParameterizedTest(name = "{index}: {0}") + @MethodSource("relativeFilePaths") + void fileToURLAndBack(String relativePath) throws MalformedURLException { + File file = new File(relativePath); URL url = file.toURI().toURL(); ConfigurationWatchList cwl = new ConfigurationWatchList(); File back = cwl.convertToFile(url); assertEquals(file.getName(), back.getName()); } + + static Stream relativeFilePaths() { + return Stream.of( + arguments(named("path with space", "a b.xml")), + arguments(named("path with plus sign", "a+b.xml")) + ); + } + }