Project

Profile

Help

Bug #3745

closed

file:path-to-uri() fails or works incorrectly with relative path and UNC

Added by T Hata over 6 years ago. Updated about 5 years ago.

Status:
Closed
Priority:
Normal
Assignee:
Category:
Saxon extensions
Sprint/Milestone:
-
Start date:
2018-04-14
Due date:
% Done:

100%

Estimated time:
Legacy ID:
Applies to branch:
9.8, trunk
Fix Committed on Branch:
9.8, trunk
Fixed in Maintenance Release:
Platforms:

Description

http://www.saxonica.com/documentation/index.html#!functions/expath-file/path-to-uri

Transforms a file system path into a URI with the file:// scheme. If the path is relative, it is first resolved against the current working directory.

So, on Windows, put this file as C:\test dir\path-to-uri.xsl

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="#all" version="2.0" xmlns:file="http://expath.org/ns/file"
	xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:param as="xs:string" name="path" />
	<xsl:template name="main">
		<xsl:message select="'path=', $path" />
		<xsl:variable as="xs:anyURI" name="uri" select="file:path-to-uri($path)" />
		<xsl:message select="'uri=', $uri" />
		<xsl:sequence select="doc($uri)" />
	</xsl:template>
</xsl:stylesheet>

and verify that it works with a very simple relative path:

C:\test dir>dir /b path-to-uri.xsl
path-to-uri.xsl

C:\test dir>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:path-to-uri.xsl path="path-to-uri.xsl"
Saxon-EE 9.8.0.11J from Saxonica
Java version 1.8.0_161
...
Building tree for file:/C:/test%20dir/path-to-uri.xsl using class net.sf.saxon.tree.tiny.TinyBuilder
...

Looks good.

But file:path-to-uri() fails or returns unusable URI in the following cases:

Drive relative path

C:\test dir>dir /b c:path-to-uri.xsl
path-to-uri.xsl

C:\test dir>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:path-to-uri.xsl path="c:path-to-uri.xsl"
...
path= c:path-to-uri.xsl
java.io.IOException: The filename, directory name, or volume label syntax is incorrect
        at java.io.WinNTFileSystem.canonicalize0(Native Method)
        at java.io.WinNTFileSystem.canonicalize(Unknown Source)
        at java.io.File.getCanonicalPath(Unknown Source)
        at java.io.File.getCanonicalFile(Unknown Source)
        at com.saxonica.functions.extfn.EXPathFile.toFile(EXPathFile.java:1169)
        at com.saxonica.functions.extfn.EXPathFile.pathToUri(EXPathFile.java:1080)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at java.lang.reflect.Method.invoke(Unknown Source)
        at com.saxonica.expr.JavaExtensionFunctionCall.invokeMethod(JavaExtensionFunctionCall.java:828)
        at com.saxonica.expr.JavaExtensionFunctionCall.call(JavaExtensionFunctionCall.java:561)
        at com.saxonica.expr.JavaExtensionFunctionCall.iterate(JavaExtensionFunctionCall.java:438)
        at net.sf.saxon.expr.CardinalityChecker.evaluateItem(CardinalityChecker.java:280)
        at net.sf.saxon.expr.parser.ExpressionTool.evaluate(ExpressionTool.java:329)
        at net.sf.saxon.expr.LetExpression.eval(LetExpression.java:511)
        at net.sf.saxon.expr.LetExpression.processLeavingTail(LetExpression.java:692)
        at net.sf.saxon.expr.instruct.Block.processLeavingTail(Block.java:687)
        at net.sf.saxon.expr.instruct.Instruction.process(Instruction.java:151)
        at com.saxonica.ee.bytecode.ByteCodeCandidate.process(ByteCodeCandidate.java:141)
        at net.sf.saxon.expr.instruct.NamedTemplate.expand(NamedTemplate.java:265)
        at net.sf.saxon.Controller.callTemplate(Controller.java:2538)
        at net.sf.saxon.s9api.Xslt30Transformer.callTemplate(Xslt30Transformer.java:750)
        at net.sf.saxon.Transform.processFile(Transform.java:1252)
        at net.sf.saxon.Transform.doTransform(Transform.java:782)
        at net.sf.saxon.Transform.main(Transform.java:81)
Error at char 17 in xsl:variable/@select on line 7 column 78 of path-to-uri.xsl:
  IO error in file path:c:path-to-uri.xsl
IO error in file path:c:path-to-uri.xsl

Rooted relative path

C:\test dir>dir /b "\test dir\path-to-uri.xsl"
path-to-uri.xsl

C:\test dir>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:path-to-uri.xsl path="\test dir\path-to-uri.xsl"
...
path= \test dir\path-to-uri.xsl
uri= file:/C:/test%20dir/test%20dir/path-to-uri.xsl
URIResolver.resolve href="file:/C:/test%20dir/test%20dir/path-to-uri.xsl" base="file:/C:/test%20dir/path-to-uri.xsl"
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Error at char 4 in xsl:sequence/@select on line 9 column 38 of path-to-uri.xsl:
  FODC0002: I/O error reported by XML parser processing
  file:/C:/test%20dir/test%20dir/path-to-uri.xsl: C:\test dir\test dir\path-to-uri.xsl (The
  system cannot find the path specified)
I/O error reported by XML parser processing file:/C:/test%20dir/test%20dir/path-to-uri.xsl: C:\test dir\test dir\path-to-uri.xsl (The system cannot find the path specified)

UNC path

C:\test dir>dir /b "\\localhost\c$\test dir\path-to-uri.xsl"
path-to-uri.xsl

C:\test dir>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:path-to-uri.xsl path="\\localhost\c$\test dir\path-to-uri.xsl"
...
path= \\localhost\c$\test dir\path-to-uri.xsl
uri= file:/localhost/c$/test%20dir/path-to-uri.xsl
URIResolver.resolve href="file:/localhost/c$/test%20dir/path-to-uri.xsl" base="file:/C:/test%20dir/path-to-uri.xsl"
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Error at char 4 in xsl:sequence/@select on line 9 column 38 of path-to-uri.xsl:
  FODC0002: I/O error reported by XML parser processing
  file:/localhost/c$/test%20dir/path-to-uri.xsl: \localhost\c$\test dir\path-to-uri.xsl (The
  system cannot find the path specified)
I/O error reported by XML parser processing file:/localhost/c$/test%20dir/path-to-uri.xsl: \localhost\c$\test dir\path-to-uri.xsl (The system cannot find the path specified)

Related issues

Precedes Saxon - Bug #4280: Failure in file:base-dir(): "URI has an authority component"ClosedMichael Kay2018-04-162018-04-16

Actions
Actions #1

Updated by Michael Kay over 6 years ago

Unfortunately there is no definitive spec defining a mapping from file names to URIs.

The approach we use is basically:

        return toFile(path).toUri().normalize().toString());

where toFile() is:

            File file = new File(path);
            if (!file.isAbsolute()) {
                return file;
            }
            boolean maybeURI = path.startsWith("file:");
            if (maybeURI) {
                URI uri = new URI(path.replaceAll("\\\\", "/"));
                return new File(uri.normalize());
            } else {
                return new File(getWorkingDirectory(), path).getCanonicalFile();
            }

This is a literal implementation of what the EXPath spec says, but is probably not what it should say: Windows doesn't simply have a "current working directory", it has one current directory per drive. It looks to me as if we might get better results by resolving relative paths using Java's File.getAbsolutePath() rather than using new File(base, relative). Unfortunately the Saxon EXPath implementation provides the option of setting the current working directory using a system property expath.base.directory, which is mainly useful for testing; because Java doesn't know about this, File.getAbsolutePath() would ignore it. However, we could switch to using File.getAbsolutePath() in cases where expath.base.directory isn't set. We would then have to look again at the test suite and test driver...

Actions #2

Updated by Michael Kay over 6 years ago

  • Category set to Saxon extensions
  • Status changed from New to In Progress
  • Assignee set to Michael Kay
  • Priority changed from Low to Normal

I have created a build with this change and have been trying some test cases on a Windows machine.

Most of these examples are now working OK: the exception is UNC filenames. I suspect that the issue is related to https://bugs.java.com/view_bug.do?bug_id=4723726 which indicates that Java's URI.normalize() mangles UNC filenames.

The recommendation in that JDK bug entry is to use File.toPath().toUri() - but that requires JDK 7, and Saxon 9.8 is supported on JDK 6.

I have tried this (using reflection) and it seems to work (falling back to the existing code if you're on JDK 6). That is, the filename //system/path/a.xml is converted to the URI file://system/path/a.xml - I haven't actually tested whether this URI is usable, but if not, that's a different problem.

Actions #3

Updated by Michael Kay over 6 years ago

  • Status changed from In Progress to Resolved
  • Applies to branch 9.8, trunk added
  • Fix Committed on Branch 9.8, trunk added

Patched as described. In the case of UNC filenames, the correct URI is obtained only when JDK 7 or later is used.

Actions #4

Updated by T Hata over 6 years ago

Thanks for the improvement.

Unfortunately I'm afraid Saxon would not like @file://system/path/a.xml@.

Put this as @C:\test\uri.xsl@:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet exclude-result-prefixes="#all" version="2.0" xmlns:file="http://expath.org/ns/file"
	xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
	<xsl:param as="xs:string" name="uri" select="static-base-uri()" />
	<xsl:template name="main">
		<xsl:message select="'$uri=', $uri" />
		<xsl:sequence select="doc($uri)" />
	</xsl:template>
</xsl:stylesheet>
C:\>dir /b /s \\localhost\c$\test\uri.xsl
\\localhost\c$\test\uri.xsl

doc() works with @file:////localhost/...@:

C:\>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:\\localhost\c$\test\uri.xsl
...
$uri= file:////localhost/c$/test/uri.xsl
URIResolver.resolve href="file:////localhost/c$/test/uri.xsl" base="file:////localhost/c$/test/uri.xsl"
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Building tree for file:////localhost/c$/test/uri.xsl using class net.sf.saxon.tree.tiny.TinyBuilder

But not with @file://localhost/...@:

C:\>java -cp saxon9ee.jar net.sf.saxon.Transform -it:main -t -xsl:\\localhost\c$\test\uri.xsl uri=file://localhost/c$/test/uri.xsl
...
$uri= file://localhost/c$/test/uri.xsl
URIResolver.resolve href="file://localhost/c$/test/uri.xsl" base="file:////localhost/c$/test/uri.xsl"
Using parser com.sun.org.apache.xerces.internal.jaxp.SAXParserImpl$JAXPSAXParser
Error at char 4 in xsl:sequence/@select on line 7 column 38 of uri.xsl:
  FODC0002: I/O error reported by XML parser processing file://localhost/c$/test/uri.xsl:
  \c$\test\uri.xsl (The system cannot find the path specified)
I/O error reported by XML parser processing file://localhost/c$/test/uri.xsl: \c$\test\uri.xsl (The system cannot find the path specified)
Actions #5

Updated by Michael Kay over 6 years ago

According to https://stackoverflow.com/questions/1546419/convert-file-path-to-a-file-uri, the name "localhost" is magic. Do your conclusions also apply to a real server name?

Actions #6

Updated by T Hata over 6 years ago

file://real-server-name/ and file://127.0.0.1/ worked.

Looks like file://localhost/ and file://%3F/ do not work. (@file:////localhost/@ and file:////%3F/ work.) I think that is acceptable for now.

Actions #7

Updated by O'Neil Delpratt over 6 years ago

  • Status changed from Resolved to Closed
  • % Done changed from 0 to 100
  • Fixed in Maintenance Release 9.8.0.12 added

Bug fix applied in the Saxon 9.8.0.12 maintenance release.

Actions #8

Updated by Michael Kay about 5 years ago

  • Description updated (diff)
Actions #9

Updated by Michael Kay about 5 years ago

  • Precedes Bug #4280: Failure in file:base-dir(): "URI has an authority component" added
Actions #10

Updated by Michael Kay about 5 years ago

The investigation of bug #4280 revealed new insights on how Java and .NET handle UNC filenames (differently) in the "file" URI scheme. Most operations work (on both platforms), but Java's URI.normalize() is not usable with either representation.

Please register to edit this issue

Also available in: Atom PDF