This is an automated email from the ASF dual-hosted git repository.
andy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/jena.git
The following commit(s) were added to refs/heads/main by this push:
new c8a32ea1ed GH-3465: Preserve trailing slash
c8a32ea1ed is described below
commit c8a32ea1ed06fabd4fdc6ebf7d5ed65fafb1e7ab
Author: Andy Seaborne <[email protected]>
AuthorDate: Thu Sep 25 09:57:45 2025 +0100
GH-3465: Preserve trailing slash
---
.../src/main/java/org/apache/jena/rfc3986/AlgResolveIRI.java | 9 +++++++--
.../src/test/java/org/apache/jena/rfc3986/TestNormalize.java | 4 ++++
.../src/test/java/org/apache/jena/rfc3986/TestResolve.java | 10 ++++++++++
3 files changed, 21 insertions(+), 2 deletions(-)
diff --git
a/jena-iri3986/src/main/java/org/apache/jena/rfc3986/AlgResolveIRI.java
b/jena-iri3986/src/main/java/org/apache/jena/rfc3986/AlgResolveIRI.java
index d560f885cc..c4ee538166 100644
--- a/jena-iri3986/src/main/java/org/apache/jena/rfc3986/AlgResolveIRI.java
+++ b/jena-iri3986/src/main/java/org/apache/jena/rfc3986/AlgResolveIRI.java
@@ -198,12 +198,17 @@ public class AlgResolveIRI {
}
boolean initialSlash = segments[0].isEmpty();
+ // path has a trailing slash, special case is "/"
boolean trailingSlash = false;
- // Trailing slash if it isn't the initial "/" and it ends in "/" or
"/." or "/.."
- if ( N > 1 ) {
+ // Determine whether there is going to be a trailing slash.
+ // * if it isn't the initial "/" and it ends in "/"
+ // * there is "/." or "/.." which will be resolved below.
+ if ( N > (initialSlash ? 1 : 0) ) {
if ( segments[N-1].equals(".") || segments[N-1].equals("..") )
+ // Not the initial slash, and the last segment is "." or ".."
trailingSlash = true;
else if ( path.charAt(path.length()-1) == '/' )
+ // Not the initial slash, and the last character is "/"
trailingSlash = true;
}
diff --git
a/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestNormalize.java
b/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestNormalize.java
index c0cd569f11..9abc379509 100644
--- a/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestNormalize.java
+++ b/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestNormalize.java
@@ -45,6 +45,10 @@ public class TestNormalize {
@Test public void normalize_23() { testNormalize("http://host//..",
"http://host/"); }
@Test public void normalize_24() { testNormalize("http://host/abc//..",
"http://host/abc/"); }
+ @Test public void normalize_25() { testNormalize("http://host/abc/",
"http://host/abc/"); }
+ @Test public void normalize_26() { testNormalize("http://host/abc",
"http://host/abc"); }
+ @Test public void normalize_27() { testNormalize("http://host/",
"http://host/"); }
+
private void testNormalize(String input, String expected) {
IRI3986 iri = RFC3986.create(input);
IRI3986 iri2 = iri.normalize();
diff --git
a/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestResolve.java
b/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestResolve.java
index 1e3be41efe..87b1cfab3b 100644
--- a/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestResolve.java
+++ b/jena-iri3986/src/test/java/org/apache/jena/rfc3986/TestResolve.java
@@ -45,11 +45,21 @@ public class TestResolve {
@Test public void resolve_abs_11() {
testResolve("http://example/dir1/dir2/", "//EX/OtherPath",
"http://EX/OtherPath"); }
@Test public void resolve_abs_12() { testResolve("http:",
"//EX/OtherPath", "http://EX/OtherPath"); }
+ @Test public void resolve_abs_20() { testResolve("https://example/", "//",
"https://"); }
+ @Test public void resolve_abs_21() { testResolve("https://example/",
"//host", "https://host"); }
+ @Test public void resolve_abs_22() { testResolve("https://example/",
"//host/", "https://host/"); }
+ @Test public void resolve_abs_23() { testResolve("https://example/",
"//host/path", "https://host/path"); }
+
@Test public void resolve_ref_1() { testResolve("http://example/dir/",
"A", "http://example/dir/A"); }
@Test public void resolve_ref_2() { testResolve("http://example/dir", "A",
"http://example/A"); }
@Test public void resolve_ref_3() { testResolve("http://example/dir",
"A/", "http://example/A/"); }
@Test public void resolve_ref_4() { testResolve("http://example/dir/",
"A/", "http://example/dir/A/"); }
+ // Different scheme.
+ @Test public void resolve_ref_5() { testResolve("http://example/",
"https:subdir/", "https:subdir/"); }
+ @Test public void resolve_ref_6() { testResolve("http://example/",
"https:subdir", "https:subdir"); }
+ @Test public void resolve_ref_7() { testResolve("http://example/",
"urn:foo/", "urn:foo/"); }
+
@Test public void resolve_dot_01() {
testResolve("http://example/dir1/dir2/", ".", "http://example/dir1/dir2/"); }
@Test public void resolve_dot_02() { testResolve("http://example/", ".",
"http://example/"); }
@Test public void resolve_dot_03() {
testResolve("http://example/dir1/dir2/x", ".", "http://example/dir1/dir2/"); }