This is an automated email from the ASF dual-hosted git repository. rmaucher pushed a commit to branch 9.0.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
commit 24b41f711db8729c8c35f96e97a1cdb8a2fc2f22 Author: opencode <[email protected]> AuthorDate: Wed Oct 14 17:41:22 2026 +0200 Return a URI from ConfigurationSource.DEFAULT.getURI for invalid URI names getURI() is documented to return URIs even for locations where no resource exists. For a relative name of a file that does not exist, the DEFAULT implementation ended by resolving the name against the user directory URI. URI.resolve() parses the reference strictly, so a name containing characters that are illegal in a URI but valid in a file name, such as a space, threw an unchecked IllegalArgumentException instead, contradicting the contract and inconsistent with getResource(), which wraps the same resolve() call and reports FileNotFoundException. Catch the IllegalArgumentException in the missing file case and fall back to the file based URI, which is valid whether or not the file exists and percent-encodes the name correctly. Resolvable names keep their existing resolve() result unchanged, including scheme based names such as classpath: and jar: that UriUtil does not classify as absolute URIs and which resolve() returns intact. Adds TestConfigurationSource covering the missing file with a space, the unchanged results for a missing URI-safe name, an existing file, a scheme based name and an absolute URI name. --- .../tomcat/util/file/ConfigurationSource.java | 10 +++ .../tomcat/util/file/TestConfigurationSource.java | 90 ++++++++++++++++++++++ 2 files changed, 100 insertions(+) diff --git a/java/org/apache/tomcat/util/file/ConfigurationSource.java b/java/org/apache/tomcat/util/file/ConfigurationSource.java index c7ca969058..a713c983f6 100644 --- a/java/org/apache/tomcat/util/file/ConfigurationSource.java +++ b/java/org/apache/tomcat/util/file/ConfigurationSource.java @@ -79,6 +79,16 @@ public interface ConfigurationSource { if (f.isFile()) { return f.toURI(); } + try { + return userDirUri.resolve(name); + } catch (IllegalArgumentException e) { + // URI.resolve() rejects names that contain characters + // which are not valid in a URI, such as a space. The + // contract requires a URI to be returned even when no + // resource exists, so fall back to the file based form + // which encodes the name correctly. + return f.toURI(); + } } return userDirUri.resolve(name); } diff --git a/test/org/apache/tomcat/util/file/TestConfigurationSource.java b/test/org/apache/tomcat/util/file/TestConfigurationSource.java new file mode 100644 index 0000000000..9990977e93 --- /dev/null +++ b/test/org/apache/tomcat/util/file/TestConfigurationSource.java @@ -0,0 +1,90 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.apache.tomcat.util.file; + +import java.io.File; +import java.net.URI; + +import org.junit.Assert; +import org.junit.Test; + +public class TestConfigurationSource { + + private static final ConfigurationSource DEFAULT = ConfigurationSource.DEFAULT; + + + /* + * getURI() is documented to return a URI even when no resource exists. A relative name that contains characters + * illegal in a URI (a space here) but valid in a file name must not trigger an IllegalArgumentException from + * URI.resolve(). + */ + @Test + public void testGetUriMissingFileWithIllegalUriCharacter() { + String name = "conf/does not exist.xml"; + + URI uri = DEFAULT.getURI(name); + + Assert.assertNotNull(uri); + // The file name is recovered unchanged by decoding the path. + Assert.assertEquals(new File(System.getProperty("user.dir"), name), new File(uri)); + } + + + @Test + public void testGetUriMissingFile() { + String name = "conf/does-not-exist.xml"; + + URI uri = DEFAULT.getURI(name); + + Assert.assertEquals(new File(System.getProperty("user.dir"), name).toURI(), uri); + } + + + @Test + public void testGetUriExistingFile() { + File file = new File("test/webresources/dir1/f1.txt"); + Assert.assertTrue(file.isFile()); + + URI uri = DEFAULT.getURI(file.getPath()); + + Assert.assertEquals(file.toURI(), uri); + } + + + /* + * Scheme based names that are not absolute URIs per UriUtil (classpath: and jar: have no "://") keep the + * URI.resolve() behaviour, which returns the name as a URI unchanged, as before the fix. + */ + @Test + public void testGetUriSchemeNameIsPreserved() { + String name = "classpath:org/apache/catalina/mbeans-descriptors.xml"; + + URI uri = DEFAULT.getURI(name); + + Assert.assertEquals(URI.create(name), uri); + } + + + @Test + public void testGetUriAbsoluteUriIsReturnedAsIs() { + String name = "file:/tmp/no-such-config.xml"; + + URI uri = DEFAULT.getURI(name); + + Assert.assertEquals(URI.create(name), uri); + } +} --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
