JDK-7181278 : Paths.get(uri) throws IllegalArgumentException using ZipFileSystemProvider
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_7
  • CPU: x86
  • Submitted: 2012-07-02
  • Updated: 2012-08-03
  • Resolved: 2012-07-11
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
javac 1.7.0_05

java version "1.7.0_05"
Java(TM) SE Runtime Environment (build 1.7.0_05-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.1-b03, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.1.7601]

A DESCRIPTION OF THE PROBLEM :
When you try to create a path from a jar URI using Paths.get(uri), ZipFileSystemProvider.uriToPath(uri) extracts the scheme specific part using uri.getSchemeSpecificPart() , takes a sub-string up to the "!/" string, from that creates a new URI. and then from that creates a Path to the jar file.

If the opaque section original jar URI contains any encoded characters (like "%20"), usage of uri.getSchemeSpecificPart() decodes those sequences causing the subsequent URI creation to throw an IllegalArgumentException since the source string now contains decoded characters.

ZipFileSystemProvider.uriToPath(uri) should use uri.getRawSchemeSpecificPart() instead to preserve the encoded characters for use in the new URI creation.

This makes it impossible to use a Path to access any jar resource with a path that includes encoded characters like spaces.

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
public static void main(String[] args) throws Exception {
    URL url = new URL("jar:file://dir%20name/test.jar!/jarfile.jar");
    URI uri = url.toURI();
    Path path = Paths.get(uri);
}



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
Paths.get(uri) returns a valid Path with no IllegalArgumentException when the opaque part of the jar scheme in the given URI contains encoded characters (like "%20").
ACTUAL -
When the opaque part of the jar scheme in the given URI contains encoded characters (like "%20"), ZipFileSystemProvider.uriToPath(uri) throws an IllegalArgumentException when it attempts to create a new URI from the decoded scheme specific part of the given URI.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.nio.file.FileSystemNotFoundException
	at com.sun.nio.zipfs.ZipFileSystemProvider.getFileSystem(ZipFileSystemProvider.java:171)
	at com.sun.nio.zipfs.ZipFileSystemProvider.getPath(ZipFileSystemProvider.java:157)
	at java.nio.file.Paths.get(Paths.java:143)
	at com.***.Main.main(Main.java:**)


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
public static void main(String[] args) throws Exception {
    URL url = new URL("jar:file://dir%20name/test.jar!/jarfile.jar");
    URI uri = url.toURI();
    Path path = Paths.get(uri);
}

---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Replacing the installed ZipFileSystemProvider with a sub-class that overrides the uriToPath(URI uri) as follows:

static Path uriToPath(URI uri) {
    String scheme = uri.getScheme();
    try {
        // only support legacy JAR URL syntax  jar:{uri}!/{entry} for now
        String spec = uri.getRawSchemeSpecificPart();
        int sep = spec.indexOf("!/");
        if (sep != -1) spec = spec.substring(0, sep);
        return Paths.get(new URI(spec)).toAbsolutePath();
    } catch (URISyntaxException e) {
        throw new IllegalArgumentException(e.getMessage(), e);
    }
}

The only difference is that the call to uri.getSchemeSpecificPart() has been replaced by uri.getRawSchemeSpecificPart().

Making this change to ZipFileSystemProvider will permanently correct this problem.

Also: There may be other instances of this general category of problem, decoding URI/URL parts and then using the result to create a new URI, in other parts of the JRE/JDK.