This is an automated email from the ASF dual-hosted git repository.

rmaucher pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/tomcat.git

commit b55d34f55dca510e7820357b4556599e60f28432
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]

Reply via email to