From 4c835f0337674a0181c43f448d44d961e27b2f54 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Thu, 28 Nov 2013 12:47:46 +0100 Subject: IOUtil.toURL(..) Apply decodeFromURI(uri.getPath()) if file-scheme; Add IOUtil.decodeURIToFilePath(..) for native usage. Refine comments, API doc. toURL(..): Apply space conversion, decodeFromURI(..), on file-scheme path, ensuring decoded space. ++ Add decodeURIToFilePath(String uriPath) and decodeURIToFilePath(URI uri) Both methods shall simplify decoding a file-URI for native platform usage. Tested in TestIOUtilURIHandling +++ --- make/scripts/runtest-x64.bat | 10 +- make/scripts/runtest.sh | 5 +- src/java/com/jogamp/common/util/IOUtil.java | 86 ++++++++-- src/java/com/jogamp/common/util/JarUtil.java | 2 +- .../jogamp/common/util/TestIOUtilURIHandling.java | 184 +++++++++++++++++++-- 5 files changed, 251 insertions(+), 36 deletions(-) diff --git a/make/scripts/runtest-x64.bat b/make/scripts/runtest-x64.bat index 91cba6a..d356b30 100755 --- a/make/scripts/runtest-x64.bat +++ b/make/scripts/runtest-x64.bat @@ -3,9 +3,9 @@ REM scripts\java-win64.bat com.jogamp.common.util.TestVersionInfo REM scripts\java-win64.bat com.jogamp.gluegen.test.junit.generation.Test1p1JavaEmitter REM scripts\java-win64.bat com.jogamp.common.os.TestElfReader01 -REM scripts\java-win64.bat com.jogamp.common.util.TestIOUtil01 2>&1 | tee -a $LOG -REM scripts\java-win64.bat com.jogamp.common.util.TestIOUtilURICompose 2>&1 | tee -a $LOG -scripts\java-win64.bat com.jogamp.common.util.TestIOUtilURIHandling 2>&1 | tee -a $LOG -REM scripts\java-win64.bat com.jogamp.common.net.TestUrisWithAssetHandler 2>&1 | tee -a $LOG -REM scripts\java-win64.bat com.jogamp.common.net.TestURIQueryProps 2>&1 | tee -a $LOG +REM scripts\java-win64.bat com.jogamp.common.util.TestIOUtil01 +REM scripts\java-win64.bat com.jogamp.common.util.TestIOUtilURICompose +scripts\java-win64.bat com.jogamp.common.util.TestIOUtilURIHandling +REM scripts\java-win64.bat com.jogamp.common.net.TestUrisWithAssetHandler +REM scripts\java-win64.bat com.jogamp.common.net.TestURIQueryProps diff --git a/make/scripts/runtest.sh b/make/scripts/runtest.sh index 61257d1..b2e2d64 100755 --- a/make/scripts/runtest.sh +++ b/make/scripts/runtest.sh @@ -95,8 +95,9 @@ function onetest() { #onetest com.jogamp.common.util.TestRunnableTask01 2>&1 | tee -a $LOG #onetest com.jogamp.common.util.TestIOUtil01 2>&1 | tee -a $LOG #onetest com.jogamp.common.util.TestIOUtilURICompose 2>&1 | tee -a $LOG -#onetest com.jogamp.common.util.TestIOUtilURIHandling 2>&1 | tee -a $LOG -onetest com.jogamp.common.util.TestTempJarCache 2>&1 | tee -a $LOG +#onetest com.jogamp.common.GlueGenVersion 2>&1 | tee -a $LOG +onetest com.jogamp.common.util.TestIOUtilURIHandling 2>&1 | tee -a $LOG +#onetest com.jogamp.common.util.TestTempJarCache 2>&1 | tee -a $LOG #onetest com.jogamp.common.util.TestJarUtil 2>&1 | tee -a $LOG #onetest com.jogamp.common.util.TestValueConversion 2>&1 | tee -a $LOG #onetest com.jogamp.common.util.TestSyncRingBuffer01 $* diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java index c719310..d6ef87a 100644 --- a/src/java/com/jogamp/common/util/IOUtil.java +++ b/src/java/com/jogamp/common/util/IOUtil.java @@ -493,17 +493,26 @@ public class IOUtil { } /** - * Converts an {@link URI} to an {@link URL} while using a non encoded path - * for file scheme, i.e. file:/. + * Converts an {@link URI} to an {@link URL} while using a non encoded path. + *

+ * A file scheme path, i.e. path following file:, is converted as follows:
+ *
+ File file = new File( {@link #decodeFromURI(String) decodeFromURI}( specificURI.getPath() ) );
+ String uriFilePath = {@link #encodeFilePathToURI(String) encodeFilePathToURI}( file.getPath() );
+ *

+ * above conversion results in a decoded file path appropriate to be used by subsequent file i/o operations (JarFile, zip, ..). + *

+ *

* Otherwise the default {@link URL} translation {@link URI#toURL()} is being used. + *

*

* The following cases are considered: *

*

@@ -527,18 +536,19 @@ public class IOUtil { "\t, uri "+uri+PlatformPropsImpl.NEWLINE+ "\t str -> "+specificURI.toString()+PlatformPropsImpl.NEWLINE+ "\t ascii -> "+specificURI.toASCIIString()+PlatformPropsImpl.NEWLINE+ + "\t ssp -> "+specificURI.getSchemeSpecificPart()+PlatformPropsImpl.NEWLINE+ + "\t frag -> "+specificURI.getFragment()+PlatformPropsImpl.NEWLINE+ "\t path -> "+specificURI.getPath()+PlatformPropsImpl.NEWLINE+ - "\t decoded.path -> "+decodeFromURI(specificURI.getPath()) - ); + "\t path.decoded -> "+decodeFromURI( specificURI.getPath() ) ); } int mode = 0; if( IOUtil.FILE_SCHEME.equals( specificURI.getScheme() ) ) { File f; try { - f = new File(specificURI); + f = new File( decodeFromURI( specificURI.getPath() ) ); // validates uri, uses decoded uri.getPath() and normalizes it } catch(Exception iae) { if( DEBUG ) { - System.err.println("Catched "+iae.getClass().getSimpleName()+": new File("+decodeFromURI(specificURI.getPath())+") failed: "+iae.getMessage()); + System.err.println("Catched "+iae.getClass().getSimpleName()+": new File("+decodeFromURI( specificURI.getPath() )+") failed: "+iae.getMessage()); iae.printStackTrace(); } f = null; @@ -861,17 +871,21 @@ public class IOUtil { /** * Reverses escaping of characters as performed via {@link #encodeToURI(String)}. + * */ public static String decodeFromURI(String s) { return patternSpaceEnc.matcher(s).replaceAll(" "); } private static final Pattern patternSingleBS = Pattern.compile("\\\\{1,}"); + private static final Pattern patternSingleFS = Pattern.compile("/{1,}"); /** - * Escapes file path characters not complying w/ RFC 2396 and the {@link URI#URI(String)} ctor. + * Encodes file path characters not complying w/ RFC 2396 and the {@link URI#URI(String)} ctor. *

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

*

*

+ * Note that this method does not perform space encoding, + * which can be utilized via {@link #encodeToURI(String)}. + *

+ *

* 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 *

+ * @see #encodeToURI(String) */ - public static String encodeFilePathToURI(String filePath) { + public static String encodeFilePathToURI(final String filePath) { if( !File.separator.equals("/") ) { final String r = patternSingleBS.matcher(filePath).replaceAll("/"); if( !r.startsWith("/") ) { @@ -896,6 +915,49 @@ public class IOUtil { return filePath; } + /** + * Decodes uri-file path characters complying w/ RFC 2396 to native file-path. + *

+ * Implementation decodes the space-encoding path={@link #decodeFromURI(String) decodeFromURI}(uriPath). + *

+ *

+ * Then it processes the path if {@link File#separatorChar} != '/' + * as follows: + *

+ *

+ * @see #decodeFromURI(String) + */ + public static String decodeURIToFilePath(final String uriPath) { + final String path = IOUtil.decodeFromURI(uriPath); + if( !File.separator.equals("/") ) { + final String r = patternSingleFS.matcher(path).replaceAll("\\\\"); + if( r.startsWith("\\") ) { + return r.substring(1); + } else { + return r; + } + } + return path; + } + + /** + * If uri is a file scheme, + * implementation returns the decoded {@link URI#getPath()} via {@link #decodeURIToFilePath(String)}, + * otherwise it returns the {@link URI#toASCIIString()} encoded URI. + * + * @see #decodeFromURI(String) + * @see #decodeURIToFilePath(String) + */ + public static String decodeURIIfFilePath(final URI uri) { + if( IOUtil.FILE_SCHEME.equals( uri.getScheme() ) ) { + return decodeURIToFilePath( uri.getPath() ); + } + return uri.toASCIIString(); + } + /** * Returns the connected URLConnection, or null if not url is not available */ @@ -1206,7 +1268,7 @@ public class IOUtil { // 1) java.io.tmpdir/jogamp if( null == tempRootExec && isStringSet(java_io_tmpdir) ) { - if( Platform.OSType.MACOS == Platform.getOSType() ) { + if( Platform.OSType.MACOS == PlatformPropsImpl.OS_TYPE ) { // Bug 865: Safari >= 6.1 [OSX] May employ xattr on 'com.apple.quarantine' on 'PluginProcess.app' // We attempt to fix this issue _after_ gluegen native lib is loaded, see JarUtil.fixNativeLibAttribs(File). tempRootExec = getSubTempDir(new File(java_io_tmpdir), tmpSubDir, false /* executable */, "tempX1"); diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java index d22d441..77f1a84 100644 --- a/src/java/com/jogamp/common/util/JarUtil.java +++ b/src/java/com/jogamp/common/util/JarUtil.java @@ -287,7 +287,7 @@ public class JarUtil { if(0 >= uriS1.lastIndexOf(".jar")) { throw new IllegalArgumentException("No Jar name in <"+classJarURI+">"); } - final String uriS2 = IOUtil.encodeToURI(uriS1); + final String uriS2 = IOUtil.encodeToURI(uriS1); // 'new URI(String)' will not encode space! if(DEBUG) { System.err.println("getJarSubURI res: "+classJarURI+" -> "+uriS0+" -> "+uriS1+" -> "+uriS2); } diff --git a/src/junit/com/jogamp/common/util/TestIOUtilURIHandling.java b/src/junit/com/jogamp/common/util/TestIOUtilURIHandling.java index 73f6ce7..6103d9a 100644 --- a/src/junit/com/jogamp/common/util/TestIOUtilURIHandling.java +++ b/src/junit/com/jogamp/common/util/TestIOUtilURIHandling.java @@ -1,13 +1,18 @@ package com.jogamp.common.util; import static com.jogamp.common.net.URIDumpUtil.showURX; +import static com.jogamp.common.net.URIDumpUtil.showURI; +import static com.jogamp.common.net.URIDumpUtil.showURL; +import java.io.File; import java.io.IOException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; +import jogamp.common.os.PlatformPropsImpl; + import org.junit.Assert; import org.junit.Test; @@ -25,6 +30,11 @@ public class TestIOUtilURIHandling extends JunitTracer { new String[] {"http://localhost/gluegen/build-x86_64/gluegen-rt.jar", "http://localhost/gluegen/build-x86_64/gluegen-rt.jar"}, + new String[] {"http://localhost/gluegen/build-x86_64%20lala/gluegen-rt.jar", + "http://localhost/gluegen/build-x86_64%20lala/gluegen-rt.jar" + // "http://localhost/gluegen/build-x86_64 lala/gluegen-rt.jar" + }, + new String[] {"http://localhost/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", "http://localhost/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar" // "http://localhost/gluegen/build-x86_64 öä lala/gluegen-rt.jar" @@ -45,12 +55,20 @@ public class TestIOUtilURIHandling extends JunitTracer { "jar:http://localhost/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class" // "jar:http://localhost/gluegen/build-x86_64 öä lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class" }, + /** Not possible, '#' is fragment in URI + new String[] {"jar:http://localhost/gluegen/%23/gluegen-rt.jar!/", + "jar:http://localhost/gluegen/%23/gluegen-rt.jar!/" + // "jar:http://localhost/gluegen/#/gluegen-rt.jar!/" + }, */ }; static final String[][] uriFileSArrayUnix = new String[][] { new String[] {"file:/gluegen/build-x86_64/gluegen-rt.jar", "file:/gluegen/build-x86_64/gluegen-rt.jar"}, + new String[] {"file:/gluegen/build-x86_64%20lala/gluegen-rt.jar", + "file:/gluegen/build-x86_64 lala/gluegen-rt.jar"}, + new String[] {"file:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", "file:/gluegen/build-x86_64 öä lala/gluegen-rt.jar"}, @@ -65,12 +83,19 @@ public class TestIOUtilURIHandling extends JunitTracer { new String[] {"jar:file:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class", "jar:file:/gluegen/build-x86_64 öä lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class" }, + + /** Not possible, '#' is fragment in URI + new String[] {"jar:file:/gluegen/%23/gluegen-rt.jar!/", + "jar:file:/gluegen/#/gluegen-rt.jar!/" }, */ }; static final String[][] uriFileSArrayWindows = new String[][] { new String[] {"file:/C:/gluegen/build-x86_64/gluegen-rt.jar", "file:/C:/gluegen/build-x86_64/gluegen-rt.jar"}, + new String[] {"file:/C:/gluegen/build-x86_64%20lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64 lala/gluegen-rt.jar"}, + new String[] {"file:/C:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", "file:/C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar"}, @@ -85,46 +110,172 @@ public class TestIOUtilURIHandling extends JunitTracer { new String[] {"jar:file:/C:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class", "jar:file:/C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar!/com/jogamp/common/os/Platform.class" }, + + /** Not possible, '#' is fragment in URI + new String[] {"jar:file:/C:/gluegen/%23/gluegen-rt.jar!/", + "jar:file:/C:/gluegen/#/gluegen-rt.jar!/" }, */ + }; + + static final String[][] fileSArrayUnix = new String[][] { + new String[] {"/gluegen/build-x86_64/gluegen-rt.jar", + "file:/gluegen/build-x86_64/gluegen-rt.jar", + "file:/gluegen/build-x86_64/gluegen-rt.jar", + "/gluegen/build-x86_64/gluegen-rt.jar"}, + + new String[] {"/gluegen/build-x86_64 lala/gluegen-rt.jar", + "file:/gluegen/build-x86_64%20lala/gluegen-rt.jar", + "file:/gluegen/build-x86_64 lala/gluegen-rt.jar", + "/gluegen/build-x86_64 lala/gluegen-rt.jar"}, + + new String[] {"/gluegen/build-x86_64 öä lala/gluegen-rt.jar", + "file:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", + "file:/gluegen/build-x86_64 öä lala/gluegen-rt.jar", + "/gluegen/build-x86_64 öä lala/gluegen-rt.jar"}, + + /* No support for '#' fragment in URI path ! + new String[] {"/gluegen/#/gluegen-rt.jar", + "file:/gluegen/%23/gluegen-rt.jar", + "file:/gluegen/#/gluegen-rt.jar", + "/gluegen/#/gluegen-rt.jar" }, */ + }; + + static final String[][] fileSArrayWindows = new String[][] { + new String[] {"C:/gluegen/build-x86_64/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64/gluegen-rt.jar", + "C:\\gluegen\\build-x86_64\\gluegen-rt.jar"}, + + new String[] {"C:/gluegen/build-x86_64 lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64%20lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64 lala/gluegen-rt.jar", + "C:\\gluegen\\build-x86_64 lala\\gluegen-rt.jar"}, + + new String[] {"C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar", + "C:\\gluegen\\build-x86_64 öä lala\\gluegen-rt.jar"}, + + new String[] {"C:\\gluegen\\build-x86_64 öä lala\\gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64%20%c3%b6%c3%a4%20lala/gluegen-rt.jar", + "file:/C:/gluegen/build-x86_64 öä lala/gluegen-rt.jar", + "C:\\gluegen\\build-x86_64 öä lala\\gluegen-rt.jar"}, + + /* No support for '#' fragment in URI path ! + new String[] {"C:/gluegen/#/gluegen-rt.jar", + "file:/C:/gluegen/%23/gluegen-rt.jar", + "file:/C:/gluegen/#/gluegen-rt.jar", + "C:\\gluegen\\#\\gluegen-rt.jar" }, */ }; @Test public void test01HttpURI2URL() throws IOException, URISyntaxException { - testURI2URL(uriHttpSArray, false /*usesFile*/, false /*matchOS*/); + testURI2URL(getSimpleTestName("."), uriHttpSArray); } @Test public void test02FileUnixURI2URL() throws IOException, URISyntaxException { - testURI2URL(uriFileSArrayUnix, true /*usesFile*/, Platform.OSType.WINDOWS != Platform.getOSType() /*matchOS*/); + testURI2URL(getSimpleTestName("."), uriFileSArrayUnix); } @Test - public void test02FileWindowsURI2URL() throws IOException, URISyntaxException { - testURI2URL(uriFileSArrayWindows, true /*usesFile*/, Platform.OSType.WINDOWS == Platform.getOSType() /*matchOS*/); + public void test03FileWindowsURI2URL() throws IOException, URISyntaxException { + testURI2URL(getSimpleTestName("."), uriFileSArrayWindows); } - static void testURI2URL(String[][] uriSArray, boolean usesFile, boolean matchOS) throws IOException, URISyntaxException { + @Test + public void test04FileUnixURI2URL() throws IOException, URISyntaxException { + if( Platform.OSType.WINDOWS != PlatformPropsImpl.OS_TYPE ) { + testFile2URI(getSimpleTestName("."), fileSArrayUnix); + } + } + + @Test + public void test05FileWindowsURI2URL() throws IOException, URISyntaxException { + if( Platform.OSType.WINDOWS == PlatformPropsImpl.OS_TYPE ) { + testFile2URI(getSimpleTestName("."), fileSArrayWindows); + } + } + + static void testURI2URL(String testname, String[][] uriSArray) throws IOException, URISyntaxException { + boolean ok = true; for(int i=0; i