Repository: dita-ot/dita-ot
Issue: ValidationFilter stage breaks with unexpected error for invalid URL

I have this link in a DITA topic:

    <xref href="http://www,oxygenxml.com" format="html" scope="external"/>

notice there is a comma in the href attribute value instead of a dot.
I publish to HTML5, the publishing breaks with:

       D:\\projects\\DITA-OT3.x\\plugins\\org.dita.base\\build_preprocess.xml:96: java.lang.RuntimeException: Expected scheme-specific part at index 5: http:
	at org.dita.dost.util.URLUtils.setFragment(URLUtils.java:559)
	at org.dita.dost.util.URLUtils.stripFragment(URLUtils.java:541)
	at org.dita.dost.writer.ValidationFilter.validateReference(ValidationFilter.java:199)
	at org.dita.dost.writer.ValidationFilter.startElement(ValidationFilter.java:96)
	at org.dita.dost.writer.ProfilingFilter.startElement(ProfilingFilter.java:121)
	at org.xml.sax.helpers.XMLFilterImpl.startElement(Unknown Source)
	at org.dita.dost.writer.DebugFilter.startElement(DebugFilter.java:78)
	at org.apache.xerces.parsers.AbstractSAXParser.startElement(Unknown Source)
	at org.apache.xerces.parsers.AbstractXMLDocumentParser.emptyElement(Unknown Source)

The URL is not really invalid according to the URI standard, so you can create an URI over it:

     new URI("http://www,oxygenxml.com")

Changed files:
src/main/java/org/dita/dost/writer/ValidationFilter.java, src/test/java/org/dita/dost/util/URLUtilsTest.java, src/main/java/org/dita/dost/util/URLUtils.java

diff --git a/src/main/java/org/dita/dost/util/URLUtils.java b/src/main/java/org/dita/dost/util/URLUtils.java
index 94f40fd20..8eb0b87f0 100644
--- a/src/main/java/org/dita/dost/util/URLUtils.java
+++ b/src/main/java/org/dita/dost/util/URLUtils.java
@@ -572,7 +572,11 @@ public final class URLUtils {
      */
     public static URI setQuery(final URI path, final String query) {
         try {
-            return new URI(path.getScheme(), path.getUserInfo(), path.getHost(), path.getPort(), path.getPath(), query, path.getFragment());
+            if (path.getPath() != null) {
+                return new URI(path.getScheme(), path.getUserInfo(), path.getHost(), path.getPort(), path.getPath(), query, path.getFragment());
+            } else {
+                return new URI(path.getScheme(), path.getSchemeSpecificPart(), path.getFragment());
+            }
         } catch (final URISyntaxException e) {
             throw new RuntimeException(e.getMessage(), e);
         }
diff --git a/src/main/java/org/dita/dost/writer/ValidationFilter.java b/src/main/java/org/dita/dost/writer/ValidationFilter.java
index 585fbdc36..0c4cc91b8 100644
--- a/src/main/java/org/dita/dost/writer/ValidationFilter.java
+++ b/src/main/java/org/dita/dost/writer/ValidationFilter.java
@@ -197,9 +197,9 @@ public final class ValidationFilter extends AbstractXMLFilter {
         if (href != null) {
             try {
                 final URI uri = new URI(href);
-                final URI abs = URLUtils.setQuery(URLUtils.stripFragment(currentFile.resolve(uri)).normalize(), null);
-                if (abs.getScheme() != null && abs.getScheme().equals("file")) {
-                    final File p = new File(abs);
+                final URI abs = currentFile.resolve(uri).normalize();
+                if (Objects.equals(abs.getScheme(), "file")) {
+                    final File p = new File(URLUtils.setQuery(URLUtils.stripFragment(abs), null));
                     try {
                         final File canFile = p.getCanonicalFile();
                         final String absPath = p.getAbsolutePath();
diff --git a/src/test/java/org/dita/dost/util/URLUtilsTest.java b/src/test/java/org/dita/dost/util/URLUtilsTest.java
index f82d36fdf..a24d71cb9 100644
--- a/src/test/java/org/dita/dost/util/URLUtilsTest.java
+++ b/src/test/java/org/dita/dost/util/URLUtilsTest.java
@@ -188,6 +188,11 @@ public class URLUtilsTest {
         assertEquals(new URI("urn:foo:bar"), URLUtils.setFragment(new URI("urn:foo:bar"), null));
     }
 
+    @Test
+    public void setFragment_mailto() {
+        assertEquals(URI.create("mailto:email@example.com?subject=Email"), URLUtils.setFragment(URI.create("mailto:email@example.com?subject=Email"), null));
+    }
+
     @Test
     public void testRemoveFragment() throws URISyntaxException {
         assertEquals(new URI("foo"), URLUtils.removeFragment(new URI("foo#bar")));
@@ -291,4 +296,9 @@ public class URLUtilsTest {
         assertEquals(URI.create("foo"), URLUtils.setQuery(URI.create("foo?bar"), null));
         assertEquals(URI.create("foo?baz"), URLUtils.setQuery(URI.create("foo?bar"), "baz"));
     }
+
+    @Test
+    public void setQuery_mailto() {
+        assertEquals(URI.create("mailto:email@example.com?subject=Email"), URLUtils.setQuery(URI.create("mailto:email@example.com?subject=Email"), null));
+    }
 }