[Jython-checkins] jython: Improve support for Windows UNC paths in getJarFileNameFromURL.
jeff.allen
jython-checkins at python.org
Wed Jul 18 04:28:26 EDT 2018
https://hg.python.org/jython/rev/c0b0894950ff
changeset: 8175:c0b0894950ff
user: Jeff Allen <ja.py at farowl.co.uk>
date: Wed Jul 18 08:07:34 2018 +0100
summary:
Improve support for Windows UNC paths in getJarFileNameFromURL.
This adds to the fix for issue #2410. Tests now include drive-letter and
UNC paths when the OS platform is Windows. We work around some strange
behaviour wrt UNC paths that may be a Java conformance issue.
files:
NEWS | 1 +
src/org/python/core/Py.java | 37 ++++++-
tests/java/org/python/core/PySystemStateTest.java | 51 ++++++++-
3 files changed, 80 insertions(+), 9 deletions(-)
diff --git a/NEWS b/NEWS
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@
Development tip
Bugs fixed
+ - [ 2410 ] Regression in PySystemStateTest (leading slash)
- [ 2639 ] Incorrect result when using != comparison against Java {List, Set, Map}
- [ 2672 ] Integer formatting emits two minus signs with -2^31
- [ 2688 ] ClassCastException when adding list of non-PyObjects
diff --git a/src/org/python/core/Py.java b/src/org/python/core/Py.java
--- a/src/org/python/core/Py.java
+++ b/src/org/python/core/Py.java
@@ -17,11 +17,11 @@
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
+import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;
-import java.net.URLDecoder;
import java.sql.Date;
import java.sql.Time;
import java.sql.Timestamp;
@@ -2609,6 +2609,11 @@
case "jar":
// url is jar:file:/some/path/some.jar!/package/with/A.class
+ if (Platform.IS_WINDOWS) {
+ // ... or jar:file://host/some/path/some.jar!/package/with/A.class
+ // ... or jar:file:////host/some/path/some.jar!/package/with/A.class
+ url = tweakWindowsFileURL(url);
+ }
URLConnection c = url.openConnection();
fileURI = ((JarURLConnection) c).getJarFileURL().toURI();
break;
@@ -2629,7 +2634,7 @@
// Unknown protocol or url==null: fileURI = null
break;
}
- } catch (IOException | URISyntaxException e) {
+ } catch (IOException | URISyntaxException | IllegalArgumentException e) {
// Handler cannot open connection or URL is malformed some way: fileURI = null
}
@@ -2637,6 +2642,34 @@
return fileURI == null ? null : new File(fileURI).toString();
}
+ /**
+ * If the argument is a {@code jar:file:} or {@code file:} URL, compensate for a bug in Java's
+ * construction of URLs affecting {@code java.io.File} and {@code java.net.URLConnection} on
+ * Windows. This is a helper for {@link #getJarFileNameFromURL(URL)}.
+ * <p>
+ * This bug bites when a JAR file is at a (Windows) UNC location, and a {@code jar:file:} URL is
+ * derived from {@code Class.getResource()} as it is in {@link #_getJarFileName()}. When URL is
+ * supplied to {@link #getJarFileNameFromURL(URL)}, the bug leads to a URI that falsely treats a
+ * server as an "authority". It subsequently causes an {@code IllegalArgumentException} with the
+ * message "URI has an authority component" when we try to construct a File. See
+ * {@link https://bugs.java.com/view_bug.do?bug_id=6360233} ("won't fix").
+ *
+ * @param url Possibly malformed URL
+ * @return corrected URL
+ */
+ private static URL tweakWindowsFileURL(URL url) throws MalformedURLException {
+ String urlstr = url.toString();
+ int fileIndex = urlstr.indexOf("file://"); // 7 chars
+ if (fileIndex >= 0) {
+ // Intended UNC path. If there is no slash following these two, insert "/" here:
+ int insert = fileIndex + 7;
+ if (urlstr.length() > insert && urlstr.charAt(insert) != '/') {
+ url = new URL(urlstr.substring(0, insert) + "//" + urlstr.substring(insert));
+ }
+ }
+ return url;
+ }
+
//------------------------contructor-section---------------------------
static class py2JyClassCacheItem {
List<Class<?>> interfaces;
diff --git a/tests/java/org/python/core/PySystemStateTest.java b/tests/java/org/python/core/PySystemStateTest.java
--- a/tests/java/org/python/core/PySystemStateTest.java
+++ b/tests/java/org/python/core/PySystemStateTest.java
@@ -5,6 +5,9 @@
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
import org.python.util.PythonInterpreter;
@@ -23,14 +26,17 @@
final String urlClassPath;
final String filePath;
+ /** This constructor adapts unixPath to Windows when on Windows. */
JarExample(String urlJarPath, String urlClassPath, String unixPath) {
+ this(urlJarPath, urlClassPath,
+ Platform.IS_WINDOWS ? new File(unixPath).toString() : unixPath, true);
+ }
+
+ /** This constructor accepts filePath exactly as given. */
+ JarExample(String urlJarPath, String urlClassPath, String filePath, boolean ignored) {
this.urlJarPath = urlJarPath;
this.urlClassPath = urlClassPath;
- if (Platform.IS_WINDOWS) {
- this.filePath = new File(unixPath).toString();
- } else {
- this.filePath = unixPath;
- }
+ this.filePath = filePath;
}
}
@@ -38,7 +44,7 @@
* Examples of URLs (just the path and class noise) and the reference answer. Provide the
* reference answer like a Un*x path (forward slash).
*/
- private static JarExample[] jarExamples = { //
+ private static List<JarExample> jarExamples = Arrays.asList(//
// simple jar-file url
new JarExample("/some_dir/some.jar", "a/package/with/A.class", "/some_dir/some.jar"),
// jar-file url to decode
@@ -48,7 +54,38 @@
// Some characters should be encoded in the URL, but emerge as themselves in the path.
new JarExample("/n%c3%a5gon/katalog/r%c3%a4tt.jar", "en/f%c3%b6rpackning/med/En.class",
"/någon/katalog/rätt.jar") //
- };
+ );
+
+ /* Check drive-letter and UNC path handling if on Windows. */
+ static {
+ if (Platform.IS_WINDOWS) {
+ // Add some examples to the list (must be made mutable for that).
+ jarExamples = new ArrayList<JarExample>(jarExamples);
+
+ // Drive-letter examples
+ jarExamples.add(new JarExample("/C:/some_dir/some.jar", "a/package/with/A.class",
+ "C:\\some_dir\\some.jar", true));
+ jarExamples.add(new JarExample("/E:/n%c3%a5gon/katalog/r%c3%a4tt.jar", "med/En.class",
+ "E:\\någon\\katalog\\rätt.jar", true));
+
+ // Simple network file path (UNC path without controversial characters)
+ String p = "/org/python/version.properies";
+ String r = "\\\\localhost\\shared\\jython-dev.jar";
+ // JAR UNC file resource URL as produced by File.getURL or getURI
+ jarExamples.add(new JarExample("////localhost/shared/jython-dev.jar", p, r, true));
+ // JAR UNC file resource URL as produced by URLClassLoader.getResource
+ jarExamples.add(new JarExample("//localhost/shared/jython-dev.jar", p, r, true));
+
+ // Network file path (UNC path with a controversial characters)
+ r = "\\\\localhost\\shared\\jy thon%dev.jar";
+ // JAR UNC file resource URL based on (deprecated) File.getURL is invalid
+ // jarExamples.add(new JarExample("//localhost/shared/jy thon%dev.jar", p, r, true));
+ // JAR UNC file resource URL based on File.getURI
+ jarExamples.add(new JarExample("////localhost/shared/jy%20thon%25dev.jar", p, r, true));
+ // JAR UNC file resource URL as produced by URLClassLoader.getResource
+ jarExamples.add(new JarExample("//localhost/shared/jy%20thon%25dev.jar", p, r, true));
+ }
+ }
/**
* Test case for finding the path in the local file system of the file located by a JAR-file
--
Repository URL: https://hg.python.org/jython
More information about the Jython-checkins
mailing list