JDK-7156873 : (zipfs) FileSystems.newFileSystem(uri, env) fails for uri with escaped octets
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.nio
  • Affected Version: 7
  • Priority: P4
  • Status: Closed
  • Resolution: Fixed
  • OS: generic,windows_7
  • CPU: generic,x86
  • Submitted: 2012-03-26
  • Updated: 2013-06-26
  • Resolved: 2012-05-14
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 7 JDK 8
7u40Fixed 8 b36Fixed
Related Reports
Duplicate :  
Duplicate :  
Duplicate :  
Duplicate :  
Description
I was planning on using the com.sun.nio.zipfs.ZipFileSystemProvider in a project I���m working on, but I noticed a strange behaviour when working with URIs that contain escaped octets ��� in particular, creating a FileSystem with ���jar��� scheme for a local filepath that contains spaces always fails with the following exception:
 
java.lang.IllegalArgumentException: Illegal character in path at index 12: file:/C:/dir with spaces/file.zip
    at com.sun.nio.zipfs.ZipFileSystemProvider.uriToPath(ZipFileSystemProvider.java:87)
    at com.sun.nio.zipfs.ZipFileSystemProvider.newFileSystem(ZipFileSystemProvider.java:107)
    at java.nio.file.FileSystems.newFileSystem(FileSystems.java:322)
    at java.nio.file.FileSystems.newFileSystem(FileSystems.java:272)

 

I had a look at the uriToPath(URI uri) method and noticed the following snippet that seems to be causing the issue:

String spec = uri.getSchemeSpecificPart();
int sep = spec.indexOf("!/");
if (sep != -1)
  spec = spec.substring(0, sep);
return Paths.get(new URI(spec)).toAbsolutePath();

The string returned by getSchemeSpecificPart() is passed back to the new URI(String) constructor. However, getSchemeSpecificPart() returns a string with decoded octets, which means that if the original URI contained any (%20 for spaces for example), they would not be propagated to the modified URI that contains the path to the underlying JAR. Perhaps getSchemeSpecificPartRaw() would be more suitable as it doesn���t decode octets? I have attached a small test case that demonstrates this issue.

Test case:

import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.file.FileSystems;
import java.util.HashMap;
import java.util.Map;

public class Test {
	public static void main(String[] args) throws IOException {
		File zip = new File("C:\\dir with spaces\\file.zip");
		URI uri = URI.create("jar:" + zip.toURI());
		Map<String, String> env = new HashMap<>();
		env.put("create", "true");
		FileSystems.newFileSystem(uri, env);
	}
}

Comments
EVALUATION The submitter is correct. The URI spec clearly specifies -The single-argument constructor requires any illegal characters in its argument to be quoted and preserves any escaped octets and other characters that are present. -The getSchemeSpecificPart methods decode any escaped octets in their corresponding components. The strings returned by these methods may contain both other characters and illegal characters, and will not contain any escaped octets So we might want to get the "raw" form instead of the current decoded one of the "scheme".
26-03-2012