From c9093e491d4b78b12973ec1614bf3146fce26a83 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Fri, 18 Oct 2013 22:09:43 +0200 Subject: Fix Bug 857: GlueGen produces erroneous file URI on Windows, which breaks Netbeans's JarURLStreamHandler - 'URL IOUtil.toURL(URI)' - Needs to encode the file-path portion on Windows(*) if exists. The file-path here shall only be encoded as follows: - backslash -> slash - ensure starting with slash (*) We perform above action for all OS, if 'false == File.separator.equals("/")' - Added high verbosity in DEBUG mode to easy debugging for future cases .. - Cleanup URI/URL unit tests, i.e. split URLCompositionTest into: - TestIOUtilURICompose - TestIOUtilURIHandling (Now covers Bug 857 as well) - TestUrisWithAssetHandler - TestURIQueryProps Tested all unit tests manually on GNU/Linux and Windows w/ JRE 7u45 --- src/java/com/jogamp/common/util/IOUtil.java | 130 +++++++++++++++++++++++---- src/java/com/jogamp/common/util/JarUtil.java | 5 +- 2 files changed, 115 insertions(+), 20 deletions(-) (limited to 'src/java/com/jogamp/common/util') diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java index 16f191b..ef6a633 100644 --- a/src/java/com/jogamp/common/util/IOUtil.java +++ b/src/java/com/jogamp/common/util/IOUtil.java @@ -497,57 +497,119 @@ public class IOUtil { * for file scheme, i.e. file:/. * Otherwise the default {@link URL} translation {@link URI#toURL()} is being used. *

- * The folloing cases are considered: + * The following cases are considered: *

*

+ *

+ * Tested w/ unit test com.jogamp.common.util.TestIOUtilURIHandling + *

* @param uri * @return * @throws IOException * @throws IllegalArgumentException * @throws URISyntaxException */ - public static URL toURL(URI uri) throws IOException, IllegalArgumentException, URISyntaxException { + public static URL toURL(final URI uri) throws IOException, IllegalArgumentException, URISyntaxException { URL url = null; final String uriSchema = uri.getScheme(); - final boolean isJAR = IOUtil.JAR_SCHEME.equals(uriSchema); - final URI specificURI = isJAR ? JarUtil.getJarSubURI(uri) : uri; + final boolean isJar = IOUtil.JAR_SCHEME.equals(uriSchema); + final URI specificURI = isJar ? JarUtil.getJarSubURI(uri) : uri; + final boolean hasJarSubURI = specificURI != uri; + if( DEBUG ) { + System.out.println("IOUtil.toURL.0: isJAR "+isJar+", hasSubURI "+hasJarSubURI+Platform.getNewline()+ + "\t, uri "+uri+Platform.getNewline()+ + "\t -> "+specificURI.toString()); + } int mode = 0; if( IOUtil.FILE_SCHEME.equals( specificURI.getScheme() ) ) { File f; try { f = new File(specificURI); - } catch( IllegalArgumentException iae) { + } catch(Exception iae) { if( DEBUG ) { - System.out.println("toURL: "+uri+" -> File("+specificURI+") failed: "+iae.getMessage()); + System.out.println("Catched "+iae.getClass().getSimpleName()+": new File("+specificURI+") failed: "+iae.getMessage()); + iae.printStackTrace(); } f = null; } if( null != f ) { - if( specificURI == uri ) { - url = new URL(IOUtil.FILE_SCHEME+IOUtil.SCHEME_SEPARATOR+f.getPath()); - // url = f.toURI().toURL(); // Doesn't work, since it uses encoded path! - mode = 1; - } else { - final String post = isJAR ? IOUtil.JAR_SCHEME_SEPARATOR + JarUtil.getJarEntry(uri) : ""; - final String urlS = uriSchema+IOUtil.SCHEME_SEPARATOR+IOUtil.FILE_SCHEME+IOUtil.SCHEME_SEPARATOR+f.getPath()+post; - url = new URL(urlS); - mode = 2; + String urlS = null; + try { + final String fPath = f.getPath(); + final String fPathUriS = encodeFilePathToURI(fPath); + /** + * Below 'url = f.toURI().toURL()' Doesn't work, since it uses encoded path, + * but we need the decoded path due to subsequent file access. + * URI: jar:file:/C:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar!/ + * File: file:/C:/gluegen/build-x86_64%20öä%20lala/gluegen-rt.jar + * URI: fUri file:/C:/gluegen/build-x86_64%20öä%20lala/gluegen-rt.jar + * URL: fUrl file:/C:/gluegen/build-x86_64%20öä%20lala/gluegen-rt.jar + * + * Goal: file:/C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar!/ + */ + if(DEBUG) { + try { + final URI fUri = f.toURI(); + final URL fUrl = fUri.toURL(); + System.out.println("IOUtil.toURL.1b: fUri "+fUri+Platform.getNewline()+ + "\t, fUrl "+fUrl); + } catch (Exception ee) { + System.out.println("Catched "+ee.getClass().getSimpleName()+": f.toURI().toURL() failed: "+ee.getMessage()); + ee.printStackTrace(); + } + } + if( !hasJarSubURI ) { + urlS = IOUtil.FILE_SCHEME+IOUtil.SCHEME_SEPARATOR+fPathUriS; + if( DEBUG ) { + System.out.println("IOUtil.toURL.1: fPath "+fPath+Platform.getNewline()+ + "\t -> "+fPathUriS+Platform.getNewline()+ + "\t -> "+urlS); + } + url = new URL(urlS); + mode = 1; + } else { + final String jarEntry = JarUtil.getJarEntry(uri); + final String post = isJar ? IOUtil.JAR_SCHEME_SEPARATOR + jarEntry : ""; + urlS = uriSchema+IOUtil.SCHEME_SEPARATOR+IOUtil.FILE_SCHEME+IOUtil.SCHEME_SEPARATOR+fPathUriS+post; + if( DEBUG ) { + System.out.println("IOUtil.toURL.2: fPath "+fPath+Platform.getNewline()+ + "\t -> "+fPathUriS+Platform.getNewline()+ + "\t, jarEntry "+jarEntry+Platform.getNewline()+ + "\t, post "+post+Platform.getNewline()+ + "\t -> "+urlS); + } + url = new URL(urlS); + mode = 2; + } + } catch (Exception mue) { + if( DEBUG ) { + System.out.println("Catched "+mue.getClass().getSimpleName()+": new URL("+urlS+") failed: "+mue.getMessage()); + mue.printStackTrace(); + } } } } if( null == url ) { - url = uri.toURL(); - mode = 3; + try { + url = uri.toURL(); + mode = 3; + } catch (Exception e) { + if( DEBUG ) { + System.out.println("Catched "+e.getClass().getSimpleName()+": "+uri+".toURL() failed: "+e.getMessage()); + e.printStackTrace(); + } + } } if( DEBUG ) { - System.err.println("IOUtil.toURL: "+uri+", isJar "+isJAR+": "+specificURI+" -> mode "+mode+", "+url); + System.err.println("IOUtil.toURL.X: mode "+mode+", "+uri+Platform.getNewline()+ + "\t -> "+url); } return url; } @@ -800,6 +862,36 @@ public class IOUtil { return patternSpaceEnc.matcher(s).replaceAll(" "); } + private static final Pattern patternSingleBS = Pattern.compile("\\\\{1,}"); + + /** + * Escapes file path characters not complying w/ RFC 2396 and the {@link URI#URI(String)} ctor. + *

+ * Processes input filePath if {@link File#separatorChar} != '/' + * as follows: + *

+ *

+ *

+ * Even though Oracle's JarURLStreamHandler can handle backslashes and + * erroneous URIs w/ e.g. Windows file 'syntax', other may not (Netbeans).
+ * See Bug 857 - http://jogamp.org/bugzilla/show_bug.cgi?id=857 + *

+ */ + public static String encodeFilePathToURI(String filePath) { + if( !File.separator.equals("/") ) { + final String r = patternSingleBS.matcher(filePath).replaceAll("/"); + if( !r.startsWith("/") ) { + return "/" + r; + } else { + return r; + } + } + return filePath; + } + /** * Returns the connected URLConnection, or null if not url is not available */ diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java index 1689d54..5411d66 100644 --- a/src/java/com/jogamp/common/util/JarUtil.java +++ b/src/java/com/jogamp/common/util/JarUtil.java @@ -449,9 +449,12 @@ public class JarUtil { throw new IllegalArgumentException("null jarFileURI"); } if(DEBUG) { - System.out.println("getJarFile: "+jarFileURI.toString()); + System.out.println("getJarFile.0: "+jarFileURI.toString()); } final URL jarFileURL = IOUtil.toURL(jarFileURI); + if(DEBUG) { + System.out.println("getJarFile.1: "+jarFileURL.toString()); + } // final URL jarFileURL = jarFileURI.toURL(); // doesn't work due to encoded path even w/ file schema! final URLConnection urlc = jarFileURL.openConnection(); if(urlc instanceof JarURLConnection) { -- cgit v1.2.3