From dde91a061cb0bc209442fe0e74a532b91d1bb4b8 Mon Sep 17 00:00:00 2001 From: Sven Gothel Date: Mon, 8 Sep 2014 05:09:02 +0200 Subject: Bug 1063: Complete Uri impl. and adoption throughout GlueGen - Uri: - Add error correction (fix) of path at ctor in case a a contained Uri is requested from an opaque one. The latter might come from URI/URL and is not properly encoded! See Uri.PARSE_HINT_FIX_PATH - Simplify conversion methods: - valueOf(URI/URL): Re-encode only if not opaque - getNativeFilePath() -> toFile() - Move IOUtil Uri related constants to class Uri - Add DEBUG and DEBUG_SHOWFIX - Complete adoption of URI -> Uri changes - IOUtil, JarUtil and TempJarCache still holds some left over deprecated methods, which will be removed after officially starting 2.3.0 (JOGL dependencies) - Otherwise not URI utilization left - Tests - Cleaned ip TestUri01 and TestUri03Resolving - TestUri03Resolving also tests URL -> Uri, and hence mentioned Uri.PARSE_HINT_FIX_PATH --- .../com/jogamp/common/jvm/JNILibLoaderBase.java | 36 +-- src/java/com/jogamp/common/net/Uri.java | 352 +++++++++++++-------- src/java/com/jogamp/common/os/Platform.java | 8 +- src/java/com/jogamp/common/util/IOUtil.java | 126 ++------ src/java/com/jogamp/common/util/JarUtil.java | 301 ++++++++---------- .../com/jogamp/common/util/cache/TempJarCache.java | 155 +++++---- 6 files changed, 485 insertions(+), 493 deletions(-) (limited to 'src/java/com') diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java index 4bb68d3..9b1865f 100644 --- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java +++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java @@ -42,7 +42,6 @@ package com.jogamp.common.jvm; import java.io.IOException; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.security.AccessController; @@ -52,8 +51,8 @@ import java.util.HashSet; import java.util.Iterator; import java.util.List; +import com.jogamp.common.net.Uri; import com.jogamp.common.os.NativeLibrary; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.JarUtil; import com.jogamp.common.util.PropertyAccess; import com.jogamp.common.util.cache.TempJarCache; @@ -155,7 +154,7 @@ public class JNILibLoaderBase { /** * * @param classFromJavaJar - * @param classJarURI + * @param classJarUri * @param jarBasename jar basename w/ suffix * @param nativeJarBasename native jar basename w/ suffix * @return @@ -163,15 +162,15 @@ public class JNILibLoaderBase { * @throws SecurityException * @throws URISyntaxException */ - private static final boolean addNativeJarLibsImpl(final Class classFromJavaJar, final URI classJarURI, - final String jarBasename, final String nativeJarBasename) + private static final boolean addNativeJarLibsImpl(final Class classFromJavaJar, final Uri classJarUri, + final Uri.Encoded jarBasename, final Uri.Encoded nativeJarBasename) throws IOException, SecurityException, URISyntaxException { if (DEBUG) { final StringBuilder msg = new StringBuilder(); msg.append("JNILibLoaderBase: addNativeJarLibsImpl(").append(PlatformPropsImpl.NEWLINE); msg.append(" classFromJavaJar = ").append(classFromJavaJar).append(PlatformPropsImpl.NEWLINE); - msg.append(" classJarURI = ").append(classJarURI).append(PlatformPropsImpl.NEWLINE); + msg.append(" classJarURI = ").append(classJarUri).append(PlatformPropsImpl.NEWLINE); msg.append(" jarBasename = ").append(jarBasename).append(PlatformPropsImpl.NEWLINE); msg.append(" os.and.arch = ").append(PlatformPropsImpl.os_and_arch).append(PlatformPropsImpl.NEWLINE); msg.append(" nativeJarBasename = ").append(nativeJarBasename).append(PlatformPropsImpl.NEWLINE); @@ -181,15 +180,15 @@ public class JNILibLoaderBase { boolean ok = false; - final URI jarSubURI = JarUtil.getJarSubURI( classJarURI ); + final Uri jarSubURI = classJarUri.getContainedUri(); if (null == jarSubURI) { - throw new IllegalArgumentException("JarSubURI is null of: "+classJarURI); + throw new IllegalArgumentException("JarSubURI is null of: "+classJarUri); } - final String jarUriRoot_s = IOUtil.getURIDirname( jarSubURI.toString() ); + final Uri jarSubUriRoot = jarSubURI.getDirectory(); if (DEBUG) { - System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: initial: %s -> %s%n", jarSubURI, jarUriRoot_s); + System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: initial: %s -> %s%n", jarSubURI, jarSubUriRoot); } final String nativeLibraryPath = String.format("natives/%s/", PlatformPropsImpl.os_and_arch); @@ -201,7 +200,7 @@ public class JNILibLoaderBase { if (null != nativeLibraryURI) { // We probably have one big-fat jar file, containing java classes // and all native platform libraries under 'natives/os.and.arch'! - final URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot_s+jarBasename); + final Uri nativeJarURI = JarUtil.getJarFileUri( jarSubUriRoot.getEncoded().concat(jarBasename) ); try { if( TempJarCache.addNativeLibs(classFromJavaJar, nativeJarURI, nativeLibraryPath) ) { ok = true; @@ -218,7 +217,7 @@ public class JNILibLoaderBase { } if (!ok) { // We assume one slim native jar file per 'os.and.arch'! - final URI nativeJarURI = JarUtil.getJarFileURI(jarUriRoot_s+nativeJarBasename); + final Uri nativeJarURI = JarUtil.getJarFileUri( jarSubUriRoot.getEncoded().concat(nativeJarBasename) ); if (DEBUG) { System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: module: %s -> %s%n", nativeJarBasename, nativeJarURI); @@ -247,13 +246,13 @@ public class JNILibLoaderBase { } } final String os_and_arch_dot = PlatformPropsImpl.os_and_arch.replace('-', '.'); - final String nativeJarTagClassName = nativeJarTagPackage + "." + moduleName + "." + os_and_arch_dot + ".TAG" ; // TODO: sync with gluegen-cpptasks-base.xml + final String nativeJarTagClassName = nativeJarTagPackage + "." + moduleName + "." + os_and_arch_dot + ".TAG"; // TODO: sync with gluegen-cpptasks-base.xml try { if(DEBUG) { System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: Locating module %s, os.and.arch %s: %s%n", moduleName, os_and_arch_dot, nativeJarTagClassName); } - final URI nativeJarTagClassJarURI = JarUtil.getJarURI(nativeJarTagClassName, cl); + final Uri nativeJarTagClassJarURI = JarUtil.getJarUri(nativeJarTagClassName, cl); if (DEBUG) { System.err.printf("JNILibLoaderBase: addNativeJarLibsImpl: ClassLoader/TAG: %s -> %s%n", nativeJarTagClassName, nativeJarTagClassJarURI); } @@ -399,14 +398,14 @@ public class JNILibLoaderBase { } final ClassLoader cl = c.getClassLoader(); - final URI classJarURI = JarUtil.getJarURI(c.getName(), cl); - final String jarName = JarUtil.getJarBasename(classJarURI); + final Uri classJarURI = JarUtil.getJarUri(c.getName(), cl); + final Uri.Encoded jarName = JarUtil.getJarBasename(classJarURI); if (jarName == null) { continue; } - final String jarBasename = jarName.substring(0, jarName.indexOf(".jar")); + final Uri.Encoded jarBasename = jarName.substring(0, jarName.indexOf(".jar")); if(DEBUG) { System.err.printf("JNILibLoaderBase: jarBasename: %s%n", jarBasename); @@ -423,7 +422,8 @@ public class JNILibLoaderBase { } } - final String nativeJarBasename = String.format("%s-natives-%s.jar", jarBasename, PlatformPropsImpl.os_and_arch); + final Uri.Encoded nativeJarBasename = + Uri.Encoded.cast( String.format("%s-natives-%s.jar", jarBasename.get(), PlatformPropsImpl.os_and_arch) ); ok = JNILibLoaderBase.addNativeJarLibsImpl(c, classJarURI, jarName, nativeJarBasename); if (ok) { diff --git a/src/java/com/jogamp/common/net/Uri.java b/src/java/com/jogamp/common/net/Uri.java index 8c641dd..d1f2016 100644 --- a/src/java/com/jogamp/common/net/Uri.java +++ b/src/java/com/jogamp/common/net/Uri.java @@ -1,8 +1,9 @@ /** - * Copyright 2013 JogAmp Community. All rights reserved. + * Copyright 2014 JogAmp Community. All rights reserved. + * Copyright 2006, 2010 The Apache Software Foundation. * * This code is derived from the Apache Harmony project's {@code class java.net.URI.Helper}, - * copyright 2006, 2010 The Apache Software Foundation (http://www.apache.org/). + * and has been heavily modified for GlueGen/JogAmp. * * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the LICENSE.txt file distributed with @@ -24,13 +25,14 @@ package com.jogamp.common.net; import java.io.File; import java.io.UnsupportedEncodingException; import java.net.MalformedURLException; -import java.net.URI; import java.net.URISyntaxException; -import java.net.URL; import java.util.StringTokenizer; import java.util.regex.Pattern; +import jogamp.common.Debug; + import com.jogamp.common.util.IOUtil; +import com.jogamp.common.util.PropertyAccess; /** * This class implements an immutable Uri as defined by RFC 2396. @@ -156,6 +158,29 @@ import com.jogamp.common.util.IOUtil; * @since 2.2.1 */ public class Uri { + private static final boolean DEBUG; + private static final boolean DEBUG_SHOWFIX; + + static { + Debug.initSingleton(); + DEBUG = IOUtil.DEBUG || Debug.debug("Uri"); + DEBUG_SHOWFIX = PropertyAccess.isPropertyDefined("jogamp.debug.Uri.ShowFix", true); + } + + /** + * Usually used to fix a path from a previously contained and opaque Uri, + * i.e. {@link #getContainedUri()}. + *

+ * Such an opaque Uri w/ erroneous encoding may have been injected via + * {@link #valueOf(URI)} and {@link #valueOf(URL)} where the given URL or URI was opaque! + *

+ *

+ * This remedies issues when dealing w/ java URI/URL opaque sources, + * which do not comply to the spec, i.e. containe un-encoded chars, e.g. ':', '$', .. + *

+ */ + private static final int PARSE_HINT_FIX_PATH = 1 << 0; + private static final String DIGITS = "0123456789ABCDEF"; private static final String ENCODING = "UTF8"; @@ -248,12 +273,25 @@ public class Uri { public static final String FRAG_LEGAL = UNRESERVED + RESERVED; // Harmony: unreserved + reserved + /** {@value} */ + public static final char SCHEME_SEPARATOR = ':'; + /** {@value} */ + public static final char FRAGMENT_SEPARATOR = '#'; + /** {@value} */ + public static final String FILE_SCHEME = "file"; + /** {@value} */ + public static final String HTTP_SCHEME = "http"; + /** {@value} */ + public static final String HTTPS_SCHEME = "https"; + /** {@value} */ + public static final String JAR_SCHEME = "jar"; + /** A JAR sub-protocol is separated from the JAR entry w/ this separator {@value}. Even if no class is specified '!/' must follow!. */ + public static final char JAR_SCHEME_SEPARATOR = '!'; + /** * Immutable RFC3986 encoded string. */ public static class Encoded implements Comparable, CharSequence { - public static final Encoded EMPTY = new Encoded(""); - private final String s; /** @@ -395,6 +433,11 @@ public class Uri { /** See {@link String#lastIndexOf(String, int)}. */ public int lastIndexOf(final String str, final int fromIndex) { return s.lastIndexOf(str, fromIndex); } + /** See {@link String#startsWith(String, int)} */ + public boolean startsWith(final String prefix, final int toffset) { return s.startsWith(prefix, toffset); } + /** See {@link String#endsWith(String)} */ + public boolean endsWith(final String suffix) { return s.endsWith(suffix); } + /** See {@link String#equalsIgnoreCase(String)}. */ public final boolean equalsIgnoreCase(final Encoded anotherEncoded) { return s.equalsIgnoreCase(anotherEncoded.s); } } @@ -609,18 +652,18 @@ public class Uri { final StringBuilder uri = new StringBuilder(); if ( !emptyString(scheme) ) { uri.append(scheme); - uri.append(IOUtil.SCHEME_SEPARATOR); + uri.append(SCHEME_SEPARATOR); } if ( !emptyString(ssp) ) { // QUOTE ILLEGAL CHARACTERS uri.append(encode(ssp, SSP_LEGAL)); } if ( !emptyString(fragment) ) { - uri.append(IOUtil.FRAGMENT_SEPARATOR); + uri.append(FRAGMENT_SEPARATOR); // QUOTE ILLEGAL CHARACTERS uri.append(encode(fragment, FRAG_LEGAL)); } - return new Uri(new Encoded(uri.toString()), false); + return new Uri(new Encoded(uri.toString()), false, 0); } /** @@ -658,7 +701,7 @@ public class Uri { final StringBuilder uri = new StringBuilder(); if ( !emptyString(scheme) ) { uri.append(scheme); - uri.append(IOUtil.SCHEME_SEPARATOR); + uri.append(SCHEME_SEPARATOR); } if ( !emptyString(userinfo) || !emptyString(host) || port != -1) { @@ -674,7 +717,7 @@ public class Uri { if ( !emptyString(host) ) { // check for ipv6 addresses that hasn't been enclosed // in square brackets - if (host.indexOf(IOUtil.SCHEME_SEPARATOR) != -1 && host.indexOf(']') == -1 + if (host.indexOf(SCHEME_SEPARATOR) != -1 && host.indexOf(']') == -1 && host.indexOf('[') == -1) { host = "[" + host + "]"; } @@ -682,7 +725,7 @@ public class Uri { } if ( port != -1 ) { - uri.append(IOUtil.SCHEME_SEPARATOR); + uri.append(SCHEME_SEPARATOR); uri.append(port); } @@ -699,10 +742,10 @@ public class Uri { if ( !emptyString(fragment) ) { // QUOTE ILLEGAL CHARS - uri.append(IOUtil.FRAGMENT_SEPARATOR); + uri.append(FRAGMENT_SEPARATOR); uri.append(encode(fragment, FRAG_LEGAL)); } - return new Uri(new Encoded(uri.toString()), true); + return new Uri(new Encoded(uri.toString()), true, 0); } /** @@ -759,7 +802,7 @@ public class Uri { final StringBuilder uri = new StringBuilder(); if ( !emptyString(scheme) ) { uri.append(scheme); - uri.append(IOUtil.SCHEME_SEPARATOR); + uri.append(SCHEME_SEPARATOR); } if ( !emptyString(authority) ) { uri.append("//"); @@ -778,10 +821,10 @@ public class Uri { } if ( !emptyString(fragment) ) { // QUOTE ILLEGAL CHARS - uri.append(IOUtil.FRAGMENT_SEPARATOR); + uri.append(FRAGMENT_SEPARATOR); uri.append(encode(fragment, FRAG_LEGAL)); } - return new Uri(new Encoded(uri.toString()), false); + return new Uri(new Encoded(uri.toString()), false, 0); } /** @@ -820,13 +863,13 @@ public class Uri { } final StringBuilder uri = new StringBuilder(); - uri.append(IOUtil.FILE_SCHEME); - uri.append(IOUtil.SCHEME_SEPARATOR); + uri.append(FILE_SCHEME); + uri.append(SCHEME_SEPARATOR); // QUOTE ILLEGAL CHARS uri.append(encode(path, PATH_LEGAL)); - return new Uri(new Encoded(uri.toString()), false); + return new Uri(new Encoded(uri.toString()), false, 0); } /** @@ -852,45 +895,41 @@ public class Uri { /** * Creates a new Uri instance using the given URI instance. *

- * If {@code reencode} is {@code true}, decomposes and decoded parts of the given URI - * and reconstruct a new encoded Uri instance, re-encoding will be performed. + * Re-encoding will be performed if the given URI is {@link URI#isOpaque() not opaque}. *

*

- * If {@code reencode} is {@code false}, the encoded {@link URI#toString()} is being used for the new Uri instance, - * i.e. no re-encoding will be performed. + * See {@link #PARSE_HINT_FIX_PATH} for issues of injecting opaque URLs. *

* * @param uri A given URI instance - * @param reencode flag whether re-encoding shall be performed - * * @throws URISyntaxException * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. */ - public static Uri valueOf(final URI uri, final boolean reencode) throws URISyntaxException { - if( !reencode) { - return new Uri(new Encoded(uri.toString())); - } - final Uri recomposedUri; + public static Uri valueOf(final java.net.URI uri) throws URISyntaxException { if( uri.isOpaque()) { - // opaque, without host validation - recomposedUri = Uri.create(uri.getScheme(), uri.getSchemeSpecificPart(), uri.getFragment()); + // opaque, without host validation. + // Note: This may induce encoding errors of authority and path, see {@link #PARSE_HINT_FIX_PATH} + return new Uri(new Encoded( uri.toString() ), false, 0); } else if( null != uri.getHost() ) { // with host validation - recomposedUri = Uri.create(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), - uri.getPath(), uri.getQuery(), uri.getFragment()); + return Uri.create(uri.getScheme(), uri.getUserInfo(), uri.getHost(), uri.getPort(), + uri.getPath(), uri.getQuery(), uri.getFragment()); } else { // without host validation - recomposedUri = Uri.create(uri.getScheme(), uri.getAuthority(), - uri.getPath(), uri.getQuery(), uri.getFragment()); + return Uri.create(uri.getScheme(), uri.getAuthority(), + uri.getPath(), uri.getQuery(), uri.getFragment()); } - return recomposedUri; } /** - * Creates a new Uri instance using the given URL instance. + * Creates a new Uri instance using the given URL instance, + * convenient wrapper for {@link #valueOf(URI)} and {@link URL#toURI()}. + *

+ * Re-encoding will be performed if the given URL is {@link URI#isOpaque() not opaque}, see {@link #valueOf(URI)}. + *

*

- * No re-encoding will be performed. + * See {@link #PARSE_HINT_FIX_PATH} for issues of injecting opaque URLs. *

* * @param url A given URL instance @@ -899,8 +938,8 @@ public class Uri { * if the temporary created string doesn't fit to the * specification RFC2396 or could not be parsed correctly. */ - public static Uri valueOf(final URL url) throws URISyntaxException { - return new Uri(new Encoded(url.toString())); + public static Uri valueOf(final java.net.URL url) throws URISyntaxException { + return valueOf(url.toURI()); } // @@ -963,12 +1002,12 @@ public class Uri { * specification RFC2396 and RFC3986 or could not be parsed correctly. */ public Uri(final Encoded uri) throws URISyntaxException { - this(uri, false); + this(uri, false, 0); } /** Returns true, if this instance is a {@code file} {@code scheme}, otherwise false. */ public final boolean isFileScheme() { - return IOUtil.FILE_SCHEME.equals( scheme.get() ); + return FILE_SCHEME.equals( scheme.get() ); } /** @@ -1001,11 +1040,12 @@ public class Uri { /** * Returns a new {@link URI} instance using the encoded {@link #input} string, {@code new URI(uri.input)}, * i.e. no re-encoding will be performed. - * @see #toURI(boolean) + * @see #toURIReencoded(boolean) + * @see #valueOf(URI) */ - public final URI toURI() { + public final java.net.URI toURI() { try { - return new URI(input.get()); + return new java.net.URI(input.get()); } catch (final URISyntaxException e) { throw new Error(e); // Can't happen } @@ -1014,35 +1054,29 @@ public class Uri { /** * Returns a new {@link URI} instance based upon this instance. *

- * If {@code reencode} is {@code true}, all Uri parts of this instance will be decoded + * All Uri parts of this instance will be decoded * and encoded by the URI constructor, i.e. re-encoding will be performed. *

- *

- * If {@code reencode} is {@code false}, this instance encoded {@link #input} string is being used, see {@link #toURI()}, - * i.e. no re-encoding will be performed. - *

* * @throws URISyntaxException * if the given string {@code uri} doesn't fit to the * specification RFC2396 or could not be parsed correctly. - * @see #valueOf(URI, boolean) + * @see #toURI() + * @see #valueOf(URI) */ - public final URI toURI(final boolean reencode) throws URISyntaxException { - if( !reencode ) { - return toURI(); - } - final URI recomposedURI; + public final java.net.URI toURIReencoded() throws URISyntaxException { + final java.net.URI recomposedURI; if( opaque ) { // opaque, without host validation - recomposedURI = new URI(decode(scheme), decode(schemeSpecificPart), decode(fragment)); + recomposedURI = new java.net.URI(decode(scheme), decode(schemeSpecificPart), decode(fragment)); } else if( null != host ) { // with host validation - recomposedURI = new URI(decode(scheme), decode(userInfo), decode(host), port, - decode(path), decode(query), decode(fragment)); + recomposedURI = new java.net.URI(decode(scheme), decode(userInfo), decode(host), port, + decode(path), decode(query), decode(fragment)); } else { // without host validation - recomposedURI = new URI(decode(scheme), decode(authority), - decode(path), decode(query), decode(fragment)); + recomposedURI = new java.net.URI(decode(scheme), decode(authority), + decode(path), decode(query), decode(fragment)); } return recomposedURI; } @@ -1055,11 +1089,11 @@ public class Uri { * if an error occurs while creating the URL or no protocol * handler could be found. */ - public final URL toURL() throws MalformedURLException { + public final java.net.URL toURL() throws MalformedURLException { if (!absolute) { throw new IllegalArgumentException("Cannot convert relative Uri: "+input); } - return new URL(input.get()); + return new java.net.URL(input.get()); } /** @@ -1071,11 +1105,12 @@ public class Uri { *
  • slash -> backslash
  • *
  • drop a starting single backslash, preserving windows UNC
  • * + * and returns the resulting new {@link File} instance. *

    * Otherwise implementation returns {@code null}. *

    */ - public final String getNativeFilePath() { + public final File toFile() { if( isFileScheme() ) { final String authorityS; if( null == authority ) { @@ -1083,17 +1118,16 @@ public class Uri { } else { authorityS = "//"+authority.decode(); } - // return IOUtil.decodeURIToFilePath(authorityS + path); final String path = authorityS+this.path.decode(); if( File.separator.equals("\\") ) { final String r = patternSingleFS.matcher(path).replaceAll("\\\\"); if( r.startsWith("\\") && !r.startsWith("\\\\") ) { // '\\\\' denotes UNC hostname, which shall not be cut-off - return r.substring(1); + return new File(r.substring(1)); } else { - return r; + return new File(r); } } - return path; + return new File(path); } return null; } @@ -1127,8 +1161,8 @@ public class Uri { if( !emptyString(schemeSpecificPart) ) { final StringBuilder sb = new StringBuilder(); - if( scheme.equals(IOUtil.JAR_SCHEME) ) { - final int idx = schemeSpecificPart.lastIndexOf(IOUtil.JAR_SCHEME_SEPARATOR); + if( scheme.equals(JAR_SCHEME) ) { + final int idx = schemeSpecificPart.lastIndexOf(JAR_SCHEME_SEPARATOR); if (0 > idx) { throw new URISyntaxException(input.get(), "missing jar separator"); } @@ -1137,16 +1171,20 @@ public class Uri { sb.append( schemeSpecificPart.get() ); } if ( !emptyString(fragment) ) { - sb.append(IOUtil.FRAGMENT_SEPARATOR); + sb.append(FRAGMENT_SEPARATOR); sb.append(fragment); } try { - final Uri res = new Uri(new Encoded(sb.toString()), false); + final int parseHints = opaque ? PARSE_HINT_FIX_PATH : 0; + final Uri res = new Uri(new Encoded(sb.toString()), false, parseHints); if( null != res.scheme ) { return res; } } catch(final URISyntaxException e) { // OK, does not contain uri + if( DEBUG ) { + e.printStackTrace(); + } } } return null; @@ -1160,7 +1198,7 @@ public class Uri { * Method is {@code jar-file-entry} aware, i.e. will return the parent entry if exists. *

    *

    - * If this Uri does not contain any path separator, method returns {@code null}. + * If this Uri does not contain any path separator, or a parent folder Uri cannot be found, method returns {@code null}. *

    *
          * Example-1:
    @@ -1182,7 +1220,7 @@ public class Uri {
                     if( e <  pl - 1 ) {
                         // path is file or has a query
                         try {
    -                        return new Uri( new Encoded( scheme.get()+IOUtil.SCHEME_SEPARATOR+schemeSpecificPart.get().substring(0, e+1) ) );
    +                        return new Uri( new Encoded( scheme.get()+SCHEME_SEPARATOR+schemeSpecificPart.get().substring(0, e+1) ) );
                         } catch (final URISyntaxException ue) {
                             // not complete, hence removed authority, or even root folder -> return null
                         }
    @@ -1191,7 +1229,7 @@ public class Uri {
                     final int p = schemeSpecificPart.lastIndexOf("/", e-1);
                     if( p > 0 ) {
                         try {
    -                        return new Uri( new Encoded( scheme.get()+IOUtil.SCHEME_SEPARATOR+schemeSpecificPart.get().substring(0, p+1) ) );
    +                        return new Uri( new Encoded( scheme.get()+SCHEME_SEPARATOR+schemeSpecificPart.get().substring(0, p+1) ) );
                         } catch (final URISyntaxException ue) {
                             // not complete, hence removed authority, or even root folder -> return null
                         }
    @@ -1201,6 +1239,22 @@ public class Uri {
             return null;
         }
     
    +    /**
    +     * Concatenates the given encoded string to the {@link #getEncoded() encoded uri}
    +     * of this instance and returns {@link #Uri(Encoded) a new Uri instance} with the result.
    +     *
    +     * @throws URISyntaxException
    +     *             if the concatenated string {@code uri} doesn't fit to the
    +     *             specification RFC2396 and RFC3986 or could not be parsed correctly.
    +     */
    +    public final Uri concat(final Uri.Encoded suffix) throws URISyntaxException {
    +        if( null == suffix ) {
    +            return this;
    +        } else {
    +            return new Uri( input.concat(suffix) );
    +        }
    +    }
    +
         /// NEW START
     
         /**
    @@ -1232,7 +1286,11 @@ public class Uri {
             }
             try {
                 return Uri.cast(uriS.substring(0, idx+1)); // exclude jar name, include terminal '/' or ':'
    -        } catch (final URISyntaxException ue) {}
    +        } catch (final URISyntaxException ue) {
    +            if( DEBUG ) {
    +                ue.printStackTrace();
    +            }
    +        }
             return null;
         }
     
    @@ -1449,7 +1507,7 @@ public class Uri {
             final StringBuilder result = new StringBuilder();
             if (scheme != null) {
                 result.append(scheme.get().toLowerCase());
    -            result.append(IOUtil.SCHEME_SEPARATOR);
    +            result.append(SCHEME_SEPARATOR);
             }
             if (opaque) {
                 result.append(schemeSpecificPart.get());
    @@ -1460,11 +1518,11 @@ public class Uri {
                         result.append(authority.get());
                     } else {
                         if (userInfo != null) {
    -                        result.append(userInfo.get() + "@"); //$NON-NLS-1$
    +                        result.append(userInfo.get() + "@");
                         }
                         result.append(host.get().toLowerCase());
                         if (port != -1) {
    -                        result.append(IOUtil.SCHEME_SEPARATOR + port);
    +                        result.append(SCHEME_SEPARATOR + port);
                         }
                     }
                 }
    @@ -1480,7 +1538,7 @@ public class Uri {
             }
     
             if (fragment != null) {
    -            result.append(IOUtil.FRAGMENT_SEPARATOR);
    +            result.append(FRAGMENT_SEPARATOR);
                 result.append(fragment.get());
             }
             return convertHexToLowerCase(result.toString());
    @@ -1490,21 +1548,20 @@ public class Uri {
          *
          * @param input
          * @param expectServer
    +     * @param parseHints TODO
          * @throws URISyntaxException
          */
    -    private Uri(final Encoded input, final boolean expectServer) throws URISyntaxException {
    +    private Uri(final Encoded input, final boolean expectServer, final int parseHints) throws URISyntaxException {
             if( emptyString(input) ) {
                 throw new URISyntaxException(input.get(), "empty input");
             }
    -        this.input = input;
    -
             String temp = input.get();
             int index;
             // parse into Fragment, Scheme, and SchemeSpecificPart
             // then parse SchemeSpecificPart if necessary
     
             // Fragment
    -        index = temp.indexOf(IOUtil.FRAGMENT_SEPARATOR);
    +        index = temp.indexOf(FRAGMENT_SEPARATOR);
             if (index != -1) {
                 // remove the fragment from the end
                 fragment = new Encoded( temp.substring(index + 1) );
    @@ -1514,12 +1571,15 @@ public class Uri {
                 fragment = null;
             }
     
    +        String inputTemp = input.get(); // may get modified due to error correction
    +
             // Scheme and SchemeSpecificPart
    -        final int indexSchemeSep = temp.indexOf(IOUtil.SCHEME_SEPARATOR);
    +        final int indexSchemeSep = temp.indexOf(SCHEME_SEPARATOR);
             index = indexSchemeSep;
             final int indexSSP = temp.indexOf('/');
             final int indexQuerySep = temp.indexOf('?');
    -        final String schemeSpecificPartS;
    +
    +        String sspTemp; // may get modified due to error correction
     
             // if a '/' or '?' occurs before the first ':' the uri has no
             // specified scheme, and is therefore not absolute
    @@ -1534,24 +1594,22 @@ public class Uri {
                     failExpecting(input, "scheme", indexSchemeSep);
                 }
                 validateScheme(input, scheme, 0);
    -            schemeSpecificPartS = temp.substring(indexSchemeSep + 1);
    -            schemeSpecificPart = new Encoded( schemeSpecificPartS );
    -            if (schemeSpecificPart.length() == 0) {
    +            sspTemp = temp.substring(indexSchemeSep + 1);
    +            if (sspTemp.length() == 0) {
                     failExpecting(input, "scheme-specific-part", indexSchemeSep);
                 }
             } else {
                 absolute = false;
                 scheme = null;
    -            schemeSpecificPartS = temp;
    -            schemeSpecificPart = new Encoded( schemeSpecificPartS );
    +            sspTemp = temp;
             }
     
    -        if ( scheme == null ||  schemeSpecificPartS.length() > 0 && schemeSpecificPartS.charAt(0) == '/' ) {
    +        if ( scheme == null ||  sspTemp.length() > 0 && sspTemp.charAt(0) == '/' ) {
                 // Uri is hierarchical, not opaque
                 opaque = false;
     
                 // Query
    -            temp = schemeSpecificPartS;
    +            temp = sspTemp;
                 index = temp.indexOf('?');
                 if (index != -1) {
                     query = new Encoded( temp.substring(index + 1) );
    @@ -1561,19 +1619,24 @@ public class Uri {
                     query = null;
                 }
     
    +            String pathTemp; // may get modified due to error correction
    +            final int indexPathInSSP;
    +
                 // Authority and Path
                 if (temp.startsWith("//")) {
                     index = temp.indexOf('/', 2);
                     final String authorityS;
                     if (index != -1) {
                         authorityS = temp.substring(2, index);
    -                    path = new Encoded( temp.substring(index) );
    +                    pathTemp = temp.substring(index);
    +                    indexPathInSSP = index;
                     } else {
                         authorityS = temp.substring(2);
                         if (authorityS.length() == 0 && query == null && fragment == null) {
                             failExpecting(input, "authority, path [, query, fragment]", index);
                         }
    -                    path = Encoded.EMPTY;
    +                    pathTemp = "";
    +                    indexPathInSSP = -1;
                         // nothing left, so path is empty
                         // (not null, path should never be null if hierarchical/non-opaque)
                     }
    @@ -1584,26 +1647,67 @@ public class Uri {
                         validateAuthority(input, authority, indexSchemeSep + 3);
                     }
                 } else { // no authority specified
    -                path = new Encoded( temp );
    +                pathTemp = temp;
    +                indexPathInSSP = 0;
                     authority = null;
                 }
     
    -            int pathIndex = 0;
    +            int indexPath = 0; // in input
                 if (indexSSP > -1) {
    -                pathIndex += indexSSP;
    +                indexPath += indexSSP;
    +            }
    +            if (indexPathInSSP > -1) {
    +                indexPath += indexPathInSSP;
                 }
    -            if (index > -1) {
    -                pathIndex += index;
    +
    +            final int pathErrIdx = validateEncoded(pathTemp, PATH_LEGAL);
    +            if( 0 <= pathErrIdx ) {
    +                // Perform error correction on PATH if requested!
    +                if( 0 != ( parseHints & PARSE_HINT_FIX_PATH ) ) {
    +                    if( DEBUG_SHOWFIX ) {
    +                        System.err.println("Uri FIX_FILEPATH: input at index "+(indexPath+pathErrIdx)+": "+inputTemp);
    +                        System.err.println("Uri FIX_FILEPATH: ssp at index   "+(indexPathInSSP+pathErrIdx)+": "+sspTemp);
    +                        System.err.println("Uri FIX_FILEPATH: path  at index "+pathErrIdx+": "+pathTemp);
    +                    }
    +                    final int pathTempOldLen = pathTemp.length();
    +                    pathTemp = encode( decode( pathTemp ), PATH_LEGAL); // re-encode, and hope for the best!
    +                    validatePath(input, pathTemp, indexPath); // re-validate!
    +                    {
    +                        // Patch SSP + INPUT !
    +                        final StringBuilder sb = new StringBuilder();
    +                        if( indexPathInSSP > 0 ) {
    +                            sb.append( sspTemp.substring(0, indexPathInSSP) );
    +                        }
    +                        sb.append( pathTemp ).append( sspTemp.substring( indexPathInSSP + pathTempOldLen ) );
    +                        sspTemp = sb.toString(); // update
    +
    +                        sb.setLength(0);
    +                        if( indexPath > 0 ) {
    +                            sb.append( inputTemp.substring(0, indexPath) );
    +                        }
    +                        sb.append( pathTemp ).append( inputTemp.substring( indexPath + pathTempOldLen ) );
    +                        inputTemp = sb.toString(); // update
    +                    }
    +                    if( DEBUG_SHOWFIX ) {
    +                        System.err.println("Uri FIX_FILEPATH: result          : "+pathTemp);
    +                        System.err.println("Uri FIX_FILEPATH: ssp after       : "+sspTemp);
    +                        System.err.println("Uri FIX_FILEPATH: input after     : "+inputTemp);
    +                    }
    +                } else {
    +                    fail(input, "invalid path", indexPath+pathErrIdx);
    +                }
                 }
    -            validatePath(input, path, pathIndex);
    +            path = new Encoded( pathTemp );
             } else {
                 // Uri is not hierarchical, Uri is opaque
                 opaque = true;
                 query = null;
                 path = null;
                 authority = null;
    -            validateSsp(input, schemeSpecificPart, indexSchemeSep + 1);
    +            validateSsp(input, sspTemp, indexSchemeSep + 1);
             }
    +        schemeSpecificPart = new Encoded( sspTemp );
    +        this.input = inputTemp == input.get() ? input : new Encoded( inputTemp );
     
             /**
              * determine the host, port and userinfo if the authority parses
    @@ -1635,7 +1739,7 @@ public class Uri {
                     hostindex = index + 1;
                 }
     
    -            index = temp.lastIndexOf(IOUtil.SCHEME_SEPARATOR);
    +            index = temp.lastIndexOf(SCHEME_SEPARATOR);
                 final int endindex = temp.indexOf(']');
     
                 if (index != -1 && endindex < index) {
    @@ -1706,7 +1810,7 @@ public class Uri {
             }
         }
     
    -    private static void validateSsp(final Encoded uri, final Encoded ssp, final int index) throws URISyntaxException {
    +    private static void validateSsp(final Encoded uri, final String ssp, final int index) throws URISyntaxException {
             final int errIdx = validateEncoded(ssp, SSP_LEGAL);
             if( 0 <= errIdx ) {
                 fail(uri, "invalid scheme-specific-part", index+errIdx);
    @@ -1714,13 +1818,13 @@ public class Uri {
         }
     
         private static void validateAuthority(final Encoded uri, final Encoded authority, final int index) throws URISyntaxException {
    -        final int errIdx = validateEncoded(authority, AUTHORITY_LEGAL);
    +        final int errIdx = validateEncoded(authority.get(), AUTHORITY_LEGAL);
             if( 0 <= errIdx ) {
                 fail(uri, "invalid authority", index+errIdx);
             }
         }
     
    -    private static void validatePath(final Encoded uri, final Encoded path, final int index) throws URISyntaxException {
    +    private static void validatePath(final Encoded uri, final String path, final int index) throws URISyntaxException {
             final int errIdx = validateEncoded(path, PATH_LEGAL);
             if( 0 <= errIdx ) {
                 fail(uri, "invalid path", index+errIdx);
    @@ -1728,14 +1832,14 @@ public class Uri {
         }
     
         private static void validateQuery(final Encoded uri, final Encoded query, final int index) throws URISyntaxException {
    -        final int errIdx = validateEncoded(query, QUERY_LEGAL);
    +        final int errIdx = validateEncoded(query.get(), QUERY_LEGAL);
             if( 0 <= errIdx ) {
                 fail(uri, "invalid query", index+errIdx);
             }
         }
     
         private static void validateFragment(final Encoded uri, final Encoded fragment, final int index) throws URISyntaxException {
    -        final int errIdx = validateEncoded(fragment, FRAG_LEGAL);
    +        final int errIdx = validateEncoded(fragment.get(), FRAG_LEGAL);
             if( 0 <= errIdx ) {
                 fail(uri, "invalid fragment", index+errIdx);
             }
    @@ -1802,10 +1906,10 @@ public class Uri {
                 return false;
             }
             String label = null;
    -        final StringTokenizer st = new StringTokenizer(hostS, "."); //$NON-NLS-1$
    +        final StringTokenizer st = new StringTokenizer(hostS, ".");
             while (st.hasMoreTokens()) {
                 label = st.nextToken();
    -            if (label.startsWith("-") || label.endsWith("-")) { //$NON-NLS-1$ //$NON-NLS-2$
    +            if (label.startsWith("-") || label.endsWith("-")) {
                     return false;
                 }
             }
    @@ -1854,7 +1958,7 @@ public class Uri {
             boolean doubleColon = false;
             int numberOfColons = 0;
             int numberOfPeriods = 0;
    -        String word = ""; //$NON-NLS-1$
    +        String word = "";
             char c = 0;
             char prevChar = 0;
             int offset = 0; // offset for [] ip addresses
    @@ -1876,8 +1980,8 @@ public class Uri {
                         if (ipv6Address.charAt(length - 1) != ']') {
                             return false; // must have a close ]
                         }
    -                    if ((ipv6Address.charAt(1) == IOUtil.SCHEME_SEPARATOR_CHAR)
    -                            && (ipv6Address.charAt(2) != IOUtil.SCHEME_SEPARATOR_CHAR)) {
    +                    if ((ipv6Address.charAt(1) == SCHEME_SEPARATOR)
    +                            && (ipv6Address.charAt(2) != SCHEME_SEPARATOR)) {
                             return false;
                         }
                         offset = 1;
    @@ -1913,14 +2017,14 @@ public class Uri {
                         // with
                         // an IPv4 ending, otherwise 7 :'s is bad
                         if (numberOfColons == 7
    -                            && ipv6Address.charAt(0 + offset) != IOUtil.SCHEME_SEPARATOR_CHAR
    -                            && ipv6Address.charAt(1 + offset) != IOUtil.SCHEME_SEPARATOR_CHAR) {
    +                            && ipv6Address.charAt(0 + offset) != SCHEME_SEPARATOR
    +                            && ipv6Address.charAt(1 + offset) != SCHEME_SEPARATOR) {
                             return false;
                         }
    -                    word = ""; //$NON-NLS-1$
    +                    word = "";
                         break;
     
    -                case IOUtil.SCHEME_SEPARATOR_CHAR:
    +                case SCHEME_SEPARATOR:
                         numberOfColons++;
                         if (numberOfColons > 7) {
                             return false;
    @@ -1928,13 +2032,13 @@ public class Uri {
                         if (numberOfPeriods > 0) {
                             return false;
                         }
    -                    if (prevChar == IOUtil.SCHEME_SEPARATOR_CHAR) {
    +                    if (prevChar == SCHEME_SEPARATOR) {
                             if (doubleColon) {
                                 return false;
                             }
                             doubleColon = true;
                         }
    -                    word = ""; //$NON-NLS-1$
    +                    word = "";
                         break;
     
                     default:
    @@ -1963,8 +2067,8 @@ public class Uri {
                 // If we have an empty word at the end, it means we ended in
                 // either a : or a .
                 // If we did not end in :: then this is invalid
    -            if (word == "" && ipv6Address.charAt(length - 1 - offset) != IOUtil.SCHEME_SEPARATOR_CHAR //$NON-NLS-1$
    -                    && ipv6Address.charAt(length - 2 - offset) != IOUtil.SCHEME_SEPARATOR_CHAR) {
    +            if (word == "" && ipv6Address.charAt(length - 1 - offset) != SCHEME_SEPARATOR
    +                    && ipv6Address.charAt(length - 2 - offset) != SCHEME_SEPARATOR) {
                     return false;
                 }
             }
    @@ -2005,7 +2109,7 @@ public class Uri {
          *            {@code java.lang.String} the characters allowed in the String
          *            s
          */
    -    private static int validateEncoded(final Encoded encoded, final String legal) {
    +    private static int validateEncoded(final String encoded, final String legal) {
             for (int i = 0; i < encoded.length();) {
                 final char ch = encoded.charAt(i);
                 if (ch == '%') {
    diff --git a/src/java/com/jogamp/common/os/Platform.java b/src/java/com/jogamp/common/os/Platform.java
    index 12122a2..513d215 100644
    --- a/src/java/com/jogamp/common/os/Platform.java
    +++ b/src/java/com/jogamp/common/os/Platform.java
    @@ -28,12 +28,12 @@
     
     package com.jogamp.common.os;
     
    -import java.net.URI;
     import java.security.AccessController;
     import java.security.PrivilegedAction;
     import java.util.concurrent.TimeUnit;
     
     import com.jogamp.common.jvm.JNILibLoaderBase;
    +import com.jogamp.common.net.Uri;
     import com.jogamp.common.util.JarUtil;
     import com.jogamp.common.util.PropertyAccess;
     import com.jogamp.common.util.ReflectionUtil;
    @@ -184,11 +184,11 @@ public class Platform extends PlatformPropsImpl {
     
                     final ClassLoader cl = Platform.class.getClassLoader();
     
    -                final URI platformClassJarURI;
    +                final Uri platformClassJarURI;
                     {
    -                    URI _platformClassJarURI = null;
    +                    Uri _platformClassJarURI = null;
                         try {
    -                        _platformClassJarURI = JarUtil.getJarURI(Platform.class.getName(), cl);
    +                        _platformClassJarURI = JarUtil.getJarUri(Platform.class.getName(), cl);
                         } catch (final Exception e) { }
                         platformClassJarURI = _platformClassJarURI;
                     }
    diff --git a/src/java/com/jogamp/common/util/IOUtil.java b/src/java/com/jogamp/common/util/IOUtil.java
    index 7a5b7ec..3a09835 100644
    --- a/src/java/com/jogamp/common/util/IOUtil.java
    +++ b/src/java/com/jogamp/common/util/IOUtil.java
    @@ -40,7 +40,6 @@ import java.io.InputStream;
     import java.io.OutputStream;
     import java.io.PrintStream;
     import java.lang.reflect.Constructor;
    -import java.net.URI;
     import java.net.URISyntaxException;
     import java.net.URL;
     import java.net.URLConnection;
    @@ -60,23 +59,6 @@ import com.jogamp.common.os.Platform;
     public class IOUtil {
         public static final boolean DEBUG = Debug.debug("IOUtil");
     
    -    /** {@value} */
    -    public static final String SCHEME_SEPARATOR = ":";
    -    /** {@value} */
    -    public static final char SCHEME_SEPARATOR_CHAR = ':';
    -    /** {@value} */
    -    public static final char FRAGMENT_SEPARATOR = '#';
    -    /** {@value} */
    -    public static final String FILE_SCHEME = "file";
    -    /** {@value} */
    -    public static final String HTTP_SCHEME = "http";
    -    /** {@value} */
    -    public static final String HTTPS_SCHEME = "https";
    -    /** {@value} */
    -    public static final String JAR_SCHEME = "jar";
    -    /** A JAR subprotocol is separeted from the JAR entry w/ this separator {@value}. Even if no class is specified '!/' must follow!. */
    -    public static final char JAR_SCHEME_SEPARATOR = '!';
    -
         /** Std. temporary directory property key java.io.tmpdir. */
         private static final String java_io_tmpdir_propkey = "java.io.tmpdir";
         private static final String user_home_propkey = "user.home";
    @@ -295,7 +277,6 @@ public class IOUtil {
          */
     
         private static final Pattern patternSingleBS = Pattern.compile("\\\\{1}");
    -    private static final Pattern patternSingleFS = Pattern.compile("/{1}");
     
         /**
          *
    @@ -424,67 +405,6 @@ public class IOUtil {
             return fname;
         }
     
    -    /**
    -     * The URI's protocol:/some/path/gluegen-rt.jar
    -     * parent dirname URI protocol:/some/path/ will be returned.
    -     * 

    - * protocol may be "file", "http", etc.. - *

    - * - * @param uri "protocol:/some/path/gluegen-rt.jar" - * @return "protocol:/some/path/" - * @throws IllegalArgumentException if the URI doesn't match the expected formatting, or is null - * @throws URISyntaxException - * @deprecated Use {@link Uri#getDirectory()} - */ - public static URI getURIDirname(final URI uri) throws IllegalArgumentException, URISyntaxException { - if(null == uri) { - throw new IllegalArgumentException("URI is null"); - } - final String uriS = uri.toString(); - if( DEBUG ) { - System.err.println("getURIDirname "+uri+", extForm: "+uriS); - } - return new URI( getURIDirname(uriS) ); - } - - /** - * The URI's protocol:/some/path/gluegen-rt.jar - * parent dirname URI protocol:/some/path/ will be returned. - *

    - * protocol may be "file", "http", etc.. - *

    - * - * @param uri "protocol:/some/path/gluegen-rt.jar" (URI encoded) - * @return "protocol:/some/path/" - * @throws IllegalArgumentException if the URI doesn't match the expected formatting, or is null - * @throws URISyntaxException - * @deprecated Use {@link Uri#getDirectory()} - */ - public static String getURIDirname(String uriS) throws IllegalArgumentException, URISyntaxException { - if(null == uriS) { - throw new IllegalArgumentException("uriS is null"); - } - // from - // file:/some/path/gluegen-rt.jar _or_ rsrc:gluegen-rt.jar - // to - // file:/some/path/ _or_ rsrc: - int idx = uriS.lastIndexOf('/'); - if(0 > idx) { - // no abs-path, check for protocol terminator ':' - idx = uriS.lastIndexOf(':'); - if(0 > idx) { - throw new IllegalArgumentException("URI does not contain protocol terminator ':', in <"+uriS+">"); - } - } - uriS = uriS.substring(0, idx+1); // exclude jar name, include terminal '/' or ':' - - if( DEBUG ) { - System.err.println("getURIDirname res: "+uriS); - } - return uriS; - } - /*** * * RESOURCE LOCATION STUFF @@ -615,6 +535,20 @@ public class IOUtil { return null; } + /** + * Wraps {@link #getRelativeOf(URI, String)} for convenience. + * @param relativePath denotes a relative file to the baseLocation's parent directory (URI encoded) + * @throws IOException + * @deprecated Use {@link Uri#getRelativeOf(com.jogamp.common.net.Uri.Encoded)}. + */ + public static URL getRelativeOf(final URL baseURL, final String relativePath) throws IOException { + try { + return Uri.valueOf(baseURL).getRelativeOf(Uri.Encoded.cast(relativePath)).toURL(); + } catch (final URISyntaxException e) { + throw new IOException(e); + } + } + /** * Generates a path for the 'relativeFile' relative to the 'baseLocation'. * @@ -698,31 +632,19 @@ public class IOUtil { *

    * Otherwise it returns the {@link URI#toASCIIString()} encoded URI. *

    - * @deprecated Use {@link Uri#getNativeFilePath()}. + * @deprecated Use {@link Uri#toFile()} */ - public static String decodeURIIfFilePath(final URI uri) { - if( IOUtil.FILE_SCHEME.equals( uri.getScheme() ) ) { - final String authorityS; - { - final String authority = uri.getAuthority(); - if( null == authority ) { - authorityS = ""; - } else { - authorityS = "//"+authority; - } - final String path = patternSpaceEnc.matcher(authorityS+uri.getPath()).replaceAll(" "); // Uri TODO: Uri.decode(encoded); - if( File.separator.equals("\\") ) { - final String r = patternSingleFS.matcher(path).replaceAll("\\\\"); - if( r.startsWith("\\") && !r.startsWith("\\\\") ) { // '\\\\' denotes UNC hostname, which shall not be cut-off - return r.substring(1); - } else { - return r; - } - } - return path; + public static String decodeURIIfFilePath(final java.net.URI uri) { + try { + final File file = Uri.valueOf(uri).toFile(); + if( null != file ) { + return file.getPath(); + } else { + return uri.toASCIIString(); } + } catch (final URISyntaxException e) { + throw new RuntimeException(e); } - return uri.toASCIIString(); } /** diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java index 329ea51..745dd12 100644 --- a/src/java/com/jogamp/common/util/JarUtil.java +++ b/src/java/com/jogamp/common/util/JarUtil.java @@ -35,7 +35,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.JarURLConnection; -import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLConnection; @@ -112,18 +111,18 @@ public class JarUtil { * @param clazzBinName "com.jogamp.common.GlueGenVersion" * @param cl * @return true if the class is loaded from a Jar file, otherwise false. - * @see {@link #getJarURI(String, ClassLoader)} + * @see {@link #getJarUri(String, ClassLoader)} */ - public static boolean hasJarURI(final String clazzBinName, final ClassLoader cl) { + public static boolean hasJarUri(final String clazzBinName, final ClassLoader cl) { try { - return null != getJarURI(clazzBinName, cl); + return null != getJarUri(clazzBinName, cl); } catch (final Exception e) { /* ignore */ } return false; } /** * The Class's "com.jogamp.common.GlueGenVersion" - * URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class" + * Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class" * will be returned. *

    * sub_protocol may be "file", "http", etc.. @@ -132,108 +131,107 @@ public class JarUtil { * @param clazzBinName "com.jogamp.common.GlueGenVersion" * @param cl ClassLoader to locate the JarFile * @return "jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class" - * @throws IllegalArgumentException if the URI doesn't match the expected formatting or null arguments + * @throws IllegalArgumentException if the Uri doesn't match the expected formatting or null arguments * @throws IOException if the class's Jar file could not been found by the ClassLoader - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI + * @throws URISyntaxException if the Uri could not be translated into a RFC 2396 Uri * @see {@link IOUtil#getClassURL(String, ClassLoader)} */ - public static URI getJarURI(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { + public static Uri getJarUri(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { if(null == clazzBinName || null == cl) { throw new IllegalArgumentException("null arguments: clazzBinName "+clazzBinName+", cl "+cl); } - final URI uri; + final Uri uri; final URL url; { url = IOUtil.getClassURL(clazzBinName, cl); final String scheme = url.getProtocol(); if( null != resolver && - !scheme.equals( IOUtil.JAR_SCHEME ) && - !scheme.equals( IOUtil.FILE_SCHEME ) && - !scheme.equals( IOUtil.HTTP_SCHEME ) && - !scheme.equals( IOUtil.HTTPS_SCHEME ) ) + !scheme.equals( Uri.JAR_SCHEME ) && + !scheme.equals( Uri.FILE_SCHEME ) && + !scheme.equals( Uri.HTTP_SCHEME ) && + !scheme.equals( Uri.HTTPS_SCHEME ) ) { final URL _url = resolver.resolve( url ); - uri = _url.toURI(); + uri = Uri.valueOf(_url); if(DEBUG) { - System.err.println("getJarURI Resolver: "+url+"\n\t-> "+_url+"\n\t-> "+uri); + System.err.println("getJarUri Resolver: "+url+"\n\t-> "+_url+"\n\t-> "+uri); } } else { - uri = url.toURI(); + uri = Uri.valueOf(url); if(DEBUG) { - System.err.println("getJarURI Default "+url+"\n\t-> "+uri); + System.err.println("getJarUri Default "+url+"\n\t-> "+uri); } } } - // test name .. - if( !uri.getScheme().equals( IOUtil.JAR_SCHEME ) ) { - throw new IllegalArgumentException("URI is not using scheme "+IOUtil.JAR_SCHEME+": <"+uri+">"); + if( !uri.scheme.equals( Uri.JAR_SCHEME ) ) { + throw new IllegalArgumentException("Uri is not using scheme "+Uri.JAR_SCHEME+": <"+uri+">"); } if(DEBUG) { - System.err.println("getJarURI res: "+clazzBinName+" -> "+url+" -> "+uri); + System.err.println("getJarUri res: "+clazzBinName+" -> "+url+" -> "+uri); } return uri; } /** - * The Class's Jar URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class + * The Class's Jar Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * Jar basename gluegen-rt.jar will be returned. *

    * sub_protocol may be "file", "http", etc.. *

    * - * @param classJarURI as retrieved w/ {@link #getJarURI(String, ClassLoader) getJarURI("com.jogamp.common.GlueGenVersion", cl).toURI()}, + * @param classJarUri as retrieved w/ {@link #getJarUri(String, ClassLoader) getJarUri("com.jogamp.common.GlueGenVersion", cl)}, * i.e. jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * @return gluegen-rt.jar - * @throws IllegalArgumentException if the URI doesn't match the expected formatting or is null + * @throws IllegalArgumentException if the Uri doesn't match the expected formatting or is null * @see {@link IOUtil#getClassURL(String, ClassLoader)} */ - public static String getJarBasename(final URI classJarURI) throws IllegalArgumentException { - if(null == classJarURI) { - throw new IllegalArgumentException("URI is null"); + public static Uri.Encoded getJarBasename(final Uri classJarUri) throws IllegalArgumentException { + if(null == classJarUri) { + throw new IllegalArgumentException("Uri is null"); } - if( !classJarURI.getScheme().equals(IOUtil.JAR_SCHEME) ) { - throw new IllegalArgumentException("URI is not using scheme "+IOUtil.JAR_SCHEME+": <"+classJarURI+">"); + if( !classJarUri.scheme.equals(Uri.JAR_SCHEME) ) { + throw new IllegalArgumentException("Uri is not using scheme "+Uri.JAR_SCHEME+": <"+classJarUri+">"); } - String uriS = classJarURI.getSchemeSpecificPart(); + Uri.Encoded ssp = classJarUri.schemeSpecificPart; // from // file:/some/path/gluegen-rt.jar!/com/jogamp/common/util/cache/TempJarCache.class // to // file:/some/path/gluegen-rt.jar - int idx = uriS.lastIndexOf(IOUtil.JAR_SCHEME_SEPARATOR); + int idx = ssp.lastIndexOf(Uri.JAR_SCHEME_SEPARATOR); if (0 <= idx) { - uriS = uriS.substring(0, idx); // exclude '!/' + ssp = ssp.substring(0, idx); // exclude '!/' } else { - throw new IllegalArgumentException("URI does not contain jar uri terminator '!', in <"+classJarURI+">"); + throw new IllegalArgumentException("Uri does not contain jar uri terminator '!', in <"+classJarUri+">"); } // from // file:/some/path/gluegen-rt.jar // to // gluegen-rt.jar - idx = uriS.lastIndexOf('/'); + idx = ssp.lastIndexOf('/'); if(0 > idx) { // no abs-path, check for protocol terminator ':' - idx = uriS.lastIndexOf(':'); + idx = ssp.lastIndexOf(':'); if(0 > idx) { - throw new IllegalArgumentException("URI does not contain protocol terminator ':', in <"+classJarURI+">"); + throw new IllegalArgumentException("Uri does not contain protocol terminator ':', in <"+classJarUri+">"); } } - uriS = uriS.substring(idx+1); // just the jar name + ssp = ssp.substring(idx+1); // just the jar name - if(0 >= uriS.lastIndexOf(".jar")) { - throw new IllegalArgumentException("No Jar name in <"+classJarURI+">"); + if(0 >= ssp.lastIndexOf(".jar")) { + throw new IllegalArgumentException("No Jar name in <"+classJarUri+">"); } if(DEBUG) { - System.err.println("getJarName res: "+uriS); + System.err.println("getJarName res: "+ssp); } - return uriS; + return ssp; } /** * The Class's com.jogamp.common.GlueGenVersion - * URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class + * Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * Jar basename gluegen-rt.jar will be returned. *

    * sub_protocol may be "file", "http", etc.. @@ -242,120 +240,54 @@ public class JarUtil { * @param clazzBinName com.jogamp.common.GlueGenVersion * @param cl * @return gluegen-rt.jar - * @throws IllegalArgumentException if the URI doesn't match the expected formatting + * @throws IllegalArgumentException if the Uri doesn't match the expected formatting * @throws IOException if the class's Jar file could not been found by the ClassLoader. - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI + * @throws URISyntaxException if the Uri could not be translated into a RFC 2396 Uri * @see {@link IOUtil#getClassURL(String, ClassLoader)} */ - public static String getJarBasename(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { - return getJarBasename( getJarURI(clazzBinName, cl) ); + public static Uri.Encoded getJarBasename(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { + return getJarBasename( getJarUri(clazzBinName, cl) ); } /** - * The Class's Jar URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class - * Jar file's sub URI sub_protocol:/some/path/gluegen-rt.jar will be returned. - *

    - * sub_protocol may be "file", "http", etc.. - *

    - * - * @param classJarURI as retrieved w/ {@link #getJarURI(String, ClassLoader) getJarURI("com.jogamp.common.GlueGenVersion", cl).toURI()}, - * i.e. jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class - * @return sub_protocol:/some/path/gluegen-rt.jar - * @throws IllegalArgumentException if the URI doesn't match the expected formatting or is null - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI - * @see {@link IOUtil#getClassURL(String, ClassLoader)} - * @deprecated Use {@link Uri#getContainedUri()} and validate it's scheme, etc. - */ - public static URI getJarSubURI(final URI classJarURI) throws IllegalArgumentException, URISyntaxException { - if(null == classJarURI) { - throw new IllegalArgumentException("URI is null"); - } - if( !classJarURI.getScheme().equals(IOUtil.JAR_SCHEME) ) { - throw new IllegalArgumentException("URI is not a using scheme "+IOUtil.JAR_SCHEME+": <"+classJarURI+">"); - } - - // from - // file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class - // to - // file:/some/path/gluegen-rt.jar - final String uriSSP = classJarURI.getRawSchemeSpecificPart(); - final int idx = uriSSP.lastIndexOf(IOUtil.JAR_SCHEME_SEPARATOR); - final String uriSSPJar; - if (0 <= idx) { - uriSSPJar = uriSSP.substring(0, idx); // exclude '!/' - } else { - throw new IllegalArgumentException("JAR URI does not contain jar uri terminator '!', uri <"+classJarURI+">"); - } - if(0 >= uriSSPJar.lastIndexOf(".jar")) { - throw new IllegalArgumentException("No Jar name in <"+classJarURI+">"); - } - if(DEBUG) { - System.err.println("getJarSubURI res: "+classJarURI+" -> "+uriSSP+" -> "+uriSSPJar); - } - return new URI(uriSSPJar); - } - - /** - * The Class's Jar URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class + * The Class's Jar Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * Jar file's entry /com/jogamp/common/GlueGenVersion.class will be returned. * - * @param classJarURI as retrieved w/ {@link #getJarURI(String, ClassLoader) getJarURI("com.jogamp.common.GlueGenVersion", cl).toURI()}, + * @param classJarUri as retrieved w/ {@link #getJarUri(String, ClassLoader) getJarUri("com.jogamp.common.GlueGenVersion", cl)}, * i.e. jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * @return /com/jogamp/common/GlueGenVersion.class * @see {@link IOUtil#getClassURL(String, ClassLoader)} - * @deprecated Useless */ - public static String getJarEntry(final URI classJarURI) { - if(null == classJarURI) { - throw new IllegalArgumentException("URI is null"); + public static Uri.Encoded getJarEntry(final Uri classJarUri) { + if(null == classJarUri) { + throw new IllegalArgumentException("Uri is null"); } - if( !classJarURI.getScheme().equals(IOUtil.JAR_SCHEME) ) { - throw new IllegalArgumentException("URI is not a using scheme "+IOUtil.JAR_SCHEME+": <"+classJarURI+">"); + if( !classJarUri.scheme.equals(Uri.JAR_SCHEME) ) { + throw new IllegalArgumentException("Uri is not a using scheme "+Uri.JAR_SCHEME+": <"+classJarUri+">"); } - final String uriSSP = classJarURI.getSchemeSpecificPart(); - // Uri TODO ? final String uriSSP = classJarURI.getRawSchemeSpecificPart(); + final Uri.Encoded uriSSP = classJarUri.schemeSpecificPart; // from // file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class // to // /com/jogamp/common/GlueGenVersion.class - final int idx = uriSSP.lastIndexOf(IOUtil.JAR_SCHEME_SEPARATOR); + final int idx = uriSSP.lastIndexOf(Uri.JAR_SCHEME_SEPARATOR); if (0 <= idx) { - final String res = uriSSP.substring(idx+1); // right of '!' + final Uri.Encoded res = uriSSP.substring(idx+1); // right of '!' // Uri TODO ? final String res = Uri.decode(uriSSP.substring(idx+1)); // right of '!' if(DEBUG) { - System.err.println("getJarEntry res: "+classJarURI+" -> "+uriSSP+" -> "+idx+" -> "+res); + System.err.println("getJarEntry res: "+classJarUri+" -> "+uriSSP+" -> "+idx+" -> "+res); } return res; } else { - throw new IllegalArgumentException("JAR URI does not contain jar uri terminator '!', uri <"+classJarURI+">"); + throw new IllegalArgumentException("JAR Uri does not contain jar uri terminator '!', uri <"+classJarUri+">"); } } - /** - * The Class's com.jogamp.common.GlueGenVersion - * URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class - * Jar file's sub URI sub_protocol:/some/path/gluegen-rt.jar will be returned. - *

    - * sub_protocol may be "file", "http", etc.. - *

    - * - * @param clazzBinName com.jogamp.common.GlueGenVersion - * @param cl - * @return sub_protocol:/some/path/gluegen-rt.jar - * @throws IllegalArgumentException if the URI doesn't match the expected formatting - * @throws IOException if the class's Jar file could not been found by the ClassLoader - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI - * @see {@link IOUtil#getClassURL(String, ClassLoader)} - */ - public static URI getJarSubURI(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { - return getJarSubURI( getJarURI(clazzBinName, cl) ); - } - /** * The Class's "com.jogamp.common.GlueGenVersion" - * URI jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class" - * Jar file URI jar:sub_protocol:/some/path/gluegen-rt.jar!/ will be returned. + * Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class" + * Jar file Uri jar:sub_protocol:/some/path/gluegen-rt.jar!/ will be returned. *

    * sub_protocol may be "file", "http", etc.. *

    @@ -363,34 +295,35 @@ public class JarUtil { * @param clazzBinName "com.jogamp.common.GlueGenVersion" * @param cl * @return "jar:sub_protocol:/some/path/gluegen-rt.jar!/" - * @throws IllegalArgumentException if the URI doesn't match the expected formatting or null arguments + * @throws IllegalArgumentException if the Uri doesn't match the expected formatting or null arguments * @throws IOException if the class's Jar file could not been found by the ClassLoader - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI + * @throws URISyntaxException if the Uri could not be translated into a RFC 2396 Uri * @see {@link IOUtil#getClassURL(String, ClassLoader)} */ - public static URI getJarFileURI(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { + public static Uri getJarFileUri(final String clazzBinName, final ClassLoader cl) throws IllegalArgumentException, IOException, URISyntaxException { if(null == clazzBinName || null == cl) { throw new IllegalArgumentException("null arguments: clazzBinName "+clazzBinName+", cl "+cl); } - final URI uri = new URI(IOUtil.JAR_SCHEME+IOUtil.SCHEME_SEPARATOR+getJarSubURI(clazzBinName, cl).toString()+"!/"); + final Uri jarSubUri = getJarUri(clazzBinName, cl).getContainedUri(); + final Uri uri = Uri.cast(Uri.JAR_SCHEME+Uri.SCHEME_SEPARATOR+jarSubUri.toString()+"!/"); if(DEBUG) { - System.err.println("getJarFileURI res: "+uri); + System.err.println("getJarFileUri res: "+uri); } return uri; } /** * @param baseUri file:/some/path/ - * @param jarFileName gluegen-rt.jar (URI encoded) + * @param jarFileName gluegen-rt.jar (Uri encoded) * @return jar:file:/some/path/gluegen-rt.jar!/ * @throws URISyntaxException * @throws IllegalArgumentException null arguments */ - public static URI getJarFileURI(final URI baseUri, final String jarFileName) throws IllegalArgumentException, URISyntaxException { + public static Uri getJarFileUri(final Uri baseUri, final Uri.Encoded jarFileName) throws IllegalArgumentException, URISyntaxException { if(null == baseUri || null == jarFileName) { - throw new IllegalArgumentException("null arguments: baseURI "+baseUri+", jarFileName "+jarFileName); + throw new IllegalArgumentException("null arguments: baseUri "+baseUri+", jarFileName "+jarFileName); } - return new URI(IOUtil.JAR_SCHEME+IOUtil.SCHEME_SEPARATOR+baseUri.toString()+jarFileName+"!/"); + return Uri.cast(Uri.JAR_SCHEME+Uri.SCHEME_SEPARATOR+baseUri.toString()+jarFileName+"!/"); } /** @@ -399,38 +332,38 @@ public class JarUtil { * @throws IllegalArgumentException null arguments * @throws URISyntaxException */ - public static URI getJarFileURI(final URI jarSubUri) throws IllegalArgumentException, URISyntaxException { + public static Uri getJarFileUri(final Uri jarSubUri) throws IllegalArgumentException, URISyntaxException { if(null == jarSubUri) { - throw new IllegalArgumentException("jarSubURI is null"); + throw new IllegalArgumentException("jarSubUri is null"); } - return new URI(IOUtil.JAR_SCHEME+IOUtil.SCHEME_SEPARATOR+jarSubUri.toString()+"!/"); + return Uri.cast(Uri.JAR_SCHEME+Uri.SCHEME_SEPARATOR+jarSubUri.toString()+"!/"); } /** - * @param jarSubUriS file:/some/path/gluegen-rt.jar (URI encoded) + * @param jarSubUriS file:/some/path/gluegen-rt.jar (Uri encoded) * @return jar:file:/some/path/gluegen-rt.jar!/ * @throws IllegalArgumentException null arguments * @throws URISyntaxException */ - public static URI getJarFileURI(final String jarSubUriS) throws IllegalArgumentException, URISyntaxException { + public static Uri getJarFileUri(final Uri.Encoded jarSubUriS) throws IllegalArgumentException, URISyntaxException { if(null == jarSubUriS) { - throw new IllegalArgumentException("jarSubURIS is null"); + throw new IllegalArgumentException("jarSubUriS is null"); } - return new URI(IOUtil.JAR_SCHEME+IOUtil.SCHEME_SEPARATOR+jarSubUriS+"!/"); + return Uri.cast(Uri.JAR_SCHEME+Uri.SCHEME_SEPARATOR+jarSubUriS+"!/"); } /** - * @param jarFileURI jar:file:/some/path/gluegen-rt.jar!/ + * @param jarFileUri jar:file:/some/path/gluegen-rt.jar!/ * @param jarEntry com/jogamp/common/GlueGenVersion.class * @return jar:file:/some/path/gluegen-rt.jar!/com/jogamp/common/GlueGenVersion.class * @throws IllegalArgumentException null arguments * @throws URISyntaxException */ - public static URI getJarEntryURI(final URI jarFileURI, final String jarEntry) throws IllegalArgumentException, URISyntaxException { + public static Uri getJarEntryUri(final Uri jarFileUri, final Uri.Encoded jarEntry) throws IllegalArgumentException, URISyntaxException { if(null == jarEntry) { throw new IllegalArgumentException("jarEntry is null"); } - return new URI(jarFileURI.toString()+jarEntry); + return Uri.cast(jarFileUri.toString()+jarEntry); } /** @@ -439,28 +372,28 @@ public class JarUtil { * @return JarFile containing the named class within the given ClassLoader * @throws IOException if the class's Jar file could not been found by the ClassLoader * @throws IllegalArgumentException null arguments - * @throws URISyntaxException if the URI could not be translated into a RFC 2396 URI - * @see {@link #getJarFileURI(String, ClassLoader)} + * @throws URISyntaxException if the Uri could not be translated into a RFC 2396 Uri + * @see {@link #getJarFileUri(String, ClassLoader)} */ public static JarFile getJarFile(final String clazzBinName, final ClassLoader cl) throws IOException, IllegalArgumentException, URISyntaxException { - return getJarFile( getJarFileURI(clazzBinName, cl) ); + return getJarFile( getJarFileUri(clazzBinName, cl) ); } /** - * @param jarFileURI jar:file:/some/path/gluegen-rt.jar!/ - * @return JarFile as named by URI within the given ClassLoader + * @param jarFileUri jar:file:/some/path/gluegen-rt.jar!/ + * @return JarFile as named by Uri within the given ClassLoader * @throws IllegalArgumentException null arguments * @throws IOException if the Jar file could not been found * @throws URISyntaxException */ - public static JarFile getJarFile(final URI jarFileURI) throws IOException, IllegalArgumentException, URISyntaxException { - if(null == jarFileURI) { - throw new IllegalArgumentException("null jarFileURI"); + public static JarFile getJarFile(final Uri jarFileUri) throws IOException, IllegalArgumentException, URISyntaxException { + if(null == jarFileUri) { + throw new IllegalArgumentException("null jarFileUri"); } if(DEBUG) { - System.err.println("getJarFile.0: "+jarFileURI.toString()); + System.err.println("getJarFile.0: "+jarFileUri.toString()); } - final URL jarFileURL = jarFileURI.toURL(); + final URL jarFileURL = jarFileUri.toURL(); if(DEBUG) { System.err.println("getJarFile.1: "+jarFileURL.toString()); } @@ -480,8 +413,22 @@ public class JarUtil { } /** - * Locates the {@link JarUtil#getJarFileURI(URI) Jar file URI} of a given resource - * relative to a given class's Jar's URI. + * See {@link #getRelativeOf(Class, com.jogamp.common.net.Uri.Encoded, com.jogamp.common.net.Uri.Encoded)}. + * @param classFromJavaJar URI encoded! + * @param cutOffInclSubDir URI encoded! + * @param relResPath URI encoded! + * @return + * @throws IllegalArgumentException + * @throws IOException + * @throws URISyntaxException + * @deprecated Use {@link #getRelativeOf(Class, com.jogamp.common.net.Uri.Encoded, com.jogamp.common.net.Uri.Encoded)}. + */ + public static java.net.URI getRelativeOf(final Class classFromJavaJar, final String cutOffInclSubDir, final String relResPath) throws IllegalArgumentException, IOException, URISyntaxException { + return getRelativeOf(classFromJavaJar, Uri.Encoded.cast(cutOffInclSubDir), Uri.Encoded.cast(relResPath)).toURI(); + } + /** + * Locates the {@link JarUtil#getJarFileUri(Uri) Jar file Uri} of a given resource + * relative to a given class's Jar's Uri. *
          *   class's jar url path + cutOffInclSubDir + relResPath,
          * 
    @@ -502,47 +449,47 @@ public class JarUtil { * * TODO: Enhance documentation! * - * @param classFromJavaJar Used to get the root URI for the class's Jar URI. + * @param classFromJavaJar Used to get the root Uri for the class's Jar Uri. * @param cutOffInclSubDir The cut off included sub-directory prepending the relative resource path. - * If the root URI includes cutOffInclSubDir, it is no more added to the result. - * @param relResPath The relative resource path. (URI encoded) - * @return The resulting resource URI, which is not tested. + * If the root Uri includes cutOffInclSubDir, it is no more added to the result. + * @param relResPath The relative resource path. (Uri encoded) + * @return The resulting resource Uri, which is not tested. * @throws IllegalArgumentException * @throws IOException * @throws URISyntaxException */ - public static URI getRelativeOf(final Class classFromJavaJar, final String cutOffInclSubDir, final String relResPath) throws IllegalArgumentException, IOException, URISyntaxException { + public static Uri getRelativeOf(final Class classFromJavaJar, final Uri.Encoded cutOffInclSubDir, final Uri.Encoded relResPath) throws IllegalArgumentException, IOException, URISyntaxException { final ClassLoader cl = classFromJavaJar.getClassLoader(); - final URI classJarURI = JarUtil.getJarURI(classFromJavaJar.getName(), cl); + final Uri classJarUri = JarUtil.getJarUri(classFromJavaJar.getName(), cl); if( DEBUG ) { - System.err.println("JarUtil.getRelativeOf: "+"(classFromJavaJar "+classFromJavaJar+", classJarURI "+classJarURI+ + System.err.println("JarUtil.getRelativeOf: "+"(classFromJavaJar "+classFromJavaJar+", classJarUri "+classJarUri+ ", cutOffInclSubDir "+cutOffInclSubDir+", relResPath "+relResPath+"): "); } - final URI jarSubURI = JarUtil.getJarSubURI( classJarURI ); - if(null == jarSubURI) { - throw new IllegalArgumentException("JarSubURI is null of: "+classJarURI); + final Uri jarSubUri = classJarUri.getContainedUri(); + if(null == jarSubUri) { + throw new IllegalArgumentException("JarSubUri is null of: "+classJarUri); } - final String jarUriRoot_s = IOUtil.getURIDirname( jarSubURI.toString() ); + final Uri.Encoded jarUriRoot = jarSubUri.getDirectory().getEncoded(); if( DEBUG ) { - System.err.println("JarUtil.getRelativeOf: "+"uri "+jarSubURI.toString()+" -> "+jarUriRoot_s); + System.err.println("JarUtil.getRelativeOf: "+"uri "+jarSubUri.toString()+" -> "+jarUriRoot); } - final String resUri_s; - if( jarUriRoot_s.endsWith(cutOffInclSubDir) ) { - resUri_s = jarUriRoot_s+relResPath; + final Uri.Encoded resUri; + if( jarUriRoot.endsWith(cutOffInclSubDir.get()) ) { + resUri = jarUriRoot.concat(relResPath); } else { - resUri_s = jarUriRoot_s+cutOffInclSubDir+relResPath; + resUri = jarUriRoot.concat(cutOffInclSubDir).concat(relResPath); } if( DEBUG ) { - System.err.println("JarUtil.getRelativeOf: "+"... -> "+resUri_s); + System.err.println("JarUtil.getRelativeOf: "+"... -> "+resUri); } - final URI resURI = JarUtil.getJarFileURI(resUri_s); + final Uri resJarUri = JarUtil.getJarFileUri(resUri); if( DEBUG ) { - System.err.println("JarUtil.getRelativeOf: "+"fin "+resURI); + System.err.println("JarUtil.getRelativeOf: "+"fin "+resJarUri); } - return resURI; + return resJarUri; } /** diff --git a/src/java/com/jogamp/common/util/cache/TempJarCache.java b/src/java/com/jogamp/common/util/cache/TempJarCache.java index 8979a43..05d92e1 100644 --- a/src/java/com/jogamp/common/util/cache/TempJarCache.java +++ b/src/java/com/jogamp/common/util/cache/TempJarCache.java @@ -29,7 +29,6 @@ package com.jogamp.common.util.cache; import java.io.File; import java.io.IOException; -import java.net.URI; import java.net.URISyntaxException; import java.security.cert.Certificate; import java.util.HashMap; @@ -40,7 +39,6 @@ import jogamp.common.Debug; import com.jogamp.common.net.Uri; import com.jogamp.common.os.NativeLibrary; -import com.jogamp.common.util.IOUtil; import com.jogamp.common.util.JarUtil; import com.jogamp.common.util.SecurityUtil; @@ -69,9 +67,9 @@ public class TempJarCache { } // Set of jar files added - private static Map nativeLibJars; - private static Map classFileJars; - private static Map resourceFileJars; + private static Map nativeLibJars; + private static Map classFileJars; + private static Map resourceFileJars; private static TempFileCache tmpFileCache; @@ -97,9 +95,9 @@ public class TempJarCache { if(!staticInitError) { // Initialize the collections of resources nativeLibMap = new HashMap(); - nativeLibJars = new HashMap(); - classFileJars = new HashMap(); - resourceFileJars = new HashMap(); + nativeLibJars = new HashMap(); + classFileJars = new HashMap(); + resourceFileJars = new HashMap(); } if(DEBUG) { System.err.println("TempJarCache.initSingleton(): ok "+(false==staticInitError)+", "+ tmpFileCache.getTempDir()); @@ -183,62 +181,62 @@ public class TempJarCache { return tmpFileCache; } - public synchronized static boolean checkNativeLibs(final URI jarURI, final LoadState exp) throws IOException { + public synchronized static boolean checkNativeLibs(final Uri jarUri, final LoadState exp) throws IOException { checkInitialized(); - if(null == jarURI) { - throw new IllegalArgumentException("jarURI is null"); + if(null == jarUri) { + throw new IllegalArgumentException("jarUri is null"); } - return testLoadState(nativeLibJars.get(jarURI), exp); + return testLoadState(nativeLibJars.get(jarUri), exp); } - public synchronized static boolean checkClasses(final URI jarURI, final LoadState exp) throws IOException { + public synchronized static boolean checkClasses(final Uri jarUri, final LoadState exp) throws IOException { checkInitialized(); - if(null == jarURI) { - throw new IllegalArgumentException("jarURI is null"); + if(null == jarUri) { + throw new IllegalArgumentException("jarUri is null"); } - return testLoadState(classFileJars.get(jarURI), exp); + return testLoadState(classFileJars.get(jarUri), exp); } - public synchronized static boolean checkResources(final URI jarURI, final LoadState exp) throws IOException { + public synchronized static boolean checkResources(final Uri jarUri, final LoadState exp) throws IOException { checkInitialized(); - if(null == jarURI) { - throw new IllegalArgumentException("jarURI is null"); + if(null == jarUri) { + throw new IllegalArgumentException("jarUri is null"); } - return testLoadState(resourceFileJars.get(jarURI), exp); + return testLoadState(resourceFileJars.get(jarUri), exp); } /** * Adds native libraries, if not yet added. * * @param certClass if class is certified, the JarFile entries needs to have the same certificate - * @param jarURI + * @param jarUri * @param nativeLibraryPath if not null, only extracts native libraries within this path. - * @return true if native libraries were added or previously loaded from given jarURI, otherwise false - * @throws IOException if the jarURI could not be loaded or a previous load attempt failed + * @return true if native libraries were added or previously loaded from given jarUri, otherwise false + * @throws IOException if the jarUri could not be loaded or a previous load attempt failed * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException */ - public synchronized static final boolean addNativeLibs(final Class certClass, final URI jarURI, final String nativeLibraryPath) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { + public synchronized static final boolean addNativeLibs(final Class certClass, final Uri jarUri, final String nativeLibraryPath) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { checkInitialized(); - final LoadState nativeLibJarsLS = nativeLibJars.get(jarURI); + final LoadState nativeLibJarsLS = nativeLibJars.get(jarUri); if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) ) { - nativeLibJars.put(jarURI, LoadState.LOOKED_UP); - final JarFile jarFile = JarUtil.getJarFile(jarURI); + nativeLibJars.put(jarUri, LoadState.LOOKED_UP); + final JarFile jarFile = JarUtil.getJarFile(jarUri); if(DEBUG) { - System.err.println("TempJarCache: addNativeLibs: "+jarURI+": nativeJar "+jarFile.getName()+" (NEW)"); + System.err.println("TempJarCache: addNativeLibs: "+jarUri+": nativeJar "+jarFile.getName()+" (NEW)"); } validateCertificates(certClass, jarFile); final int num = JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile, nativeLibraryPath, true, false, false); - nativeLibJars.put(jarURI, LoadState.LOADED); + nativeLibJars.put(jarUri, LoadState.LOADED); return num > 0; } else if( testLoadState(nativeLibJarsLS, LoadState.LOADED) ) { if(DEBUG) { - System.err.println("TempJarCache: addNativeLibs: "+jarURI+": nativeJar "+jarURI+" (REUSE)"); + System.err.println("TempJarCache: addNativeLibs: "+jarUri+": nativeJar "+jarUri+" (REUSE)"); } return true; } - throw new IOException("TempJarCache: addNativeLibs: "+jarURI+", previous load attempt failed"); + throw new IOException("TempJarCache: addNativeLibs: "+jarUri+", previous load attempt failed"); } /** @@ -248,56 +246,69 @@ public class TempJarCache { * needs Classloader.defineClass(..) access, ie. own derivation - will do when needed .. * * @param certClass if class is certified, the JarFile entries needs to have the same certificate - * @param jarURI - * @throws IOException if the jarURI could not be loaded or a previous load attempt failed + * @param jarUri + * @throws IOException if the jarUri could not be loaded or a previous load attempt failed * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException */ - public synchronized static final void addClasses(final Class certClass, final URI jarURI) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { + public synchronized static final void addClasses(final Class certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { checkInitialized(); - final LoadState classFileJarsLS = classFileJars.get(jarURI); + final LoadState classFileJarsLS = classFileJars.get(jarUri); if( !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) ) { - classFileJars.put(jarURI, LoadState.LOOKED_UP); - final JarFile jarFile = JarUtil.getJarFile(jarURI); + classFileJars.put(jarUri, LoadState.LOOKED_UP); + final JarFile jarFile = JarUtil.getJarFile(jarUri); if(DEBUG) { - System.err.println("TempJarCache: addClasses: "+jarURI+": nativeJar "+jarFile.getName()); + System.err.println("TempJarCache: addClasses: "+jarUri+": nativeJar "+jarFile.getName()); } validateCertificates(certClass, jarFile); JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile, null /* nativeLibraryPath */, false, true, false); - classFileJars.put(jarURI, LoadState.LOADED); + classFileJars.put(jarUri, LoadState.LOADED); } else if( !testLoadState(classFileJarsLS, LoadState.LOADED) ) { - throw new IOException("TempJarCache: addClasses: "+jarURI+", previous load attempt failed"); + throw new IOException("TempJarCache: addClasses: "+jarUri+", previous load attempt failed"); } } + /** + * See {@link #addResources(Class, Uri)} + * @param certClass + * @param jarURI + * @throws IOException + * @throws SecurityException + * @throws IllegalArgumentException + * @throws URISyntaxException + * @deprecated Use {@link #addResources(Class, Uri)} + */ + public synchronized static final void addResources(final Class certClass, final java.net.URI jarURI) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { + addResources(certClass, Uri.valueOf(jarURI)); + } /** * Adds native resources, if not yet added. * * @param certClass if class is certified, the JarFile entries needs to have the same certificate - * @param jarURI + * @param jarUri * @return - * @throws IOException if the jarURI could not be loaded or a previous load attempt failed + * @throws IOException if the jarUri could not be loaded or a previous load attempt failed * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException */ - public synchronized static final void addResources(final Class certClass, final URI jarURI) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { + public synchronized static final void addResources(final Class certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { checkInitialized(); - final LoadState resourceFileJarsLS = resourceFileJars.get(jarURI); + final LoadState resourceFileJarsLS = resourceFileJars.get(jarUri); if( !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) { - resourceFileJars.put(jarURI, LoadState.LOOKED_UP); - final JarFile jarFile = JarUtil.getJarFile(jarURI); + resourceFileJars.put(jarUri, LoadState.LOOKED_UP); + final JarFile jarFile = JarUtil.getJarFile(jarUri); if(DEBUG) { - System.err.println("TempJarCache: addResources: "+jarURI+": nativeJar "+jarFile.getName()); + System.err.println("TempJarCache: addResources: "+jarUri+": nativeJar "+jarFile.getName()); } validateCertificates(certClass, jarFile); JarUtil.extract(tmpFileCache.getTempDir(), null, jarFile, null /* nativeLibraryPath */, false, false, true); - resourceFileJars.put(jarURI, LoadState.LOADED); + resourceFileJars.put(jarUri, LoadState.LOADED); } else if( !testLoadState(resourceFileJarsLS, LoadState.LOADED) ) { - throw new IOException("TempJarCache: addResources: "+jarURI+", previous load attempt failed"); + throw new IOException("TempJarCache: addResources: "+jarUri+", previous load attempt failed"); } } @@ -309,20 +320,20 @@ public class TempJarCache { * needs Classloader.defineClass(..) access, ie. own derivation - will do when needed .. * * @param certClass if class is certified, the JarFile entries needs to have the same certificate - * @param jarURI - * @throws IOException if the jarURI could not be loaded or a previous load attempt failed + * @param jarUri + * @throws IOException if the jarUri could not be loaded or a previous load attempt failed * @throws SecurityException * @throws URISyntaxException * @throws IllegalArgumentException */ - public synchronized static final void addAll(final Class certClass, final URI jarURI) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { + public synchronized static final void addAll(final Class certClass, final Uri jarUri) throws IOException, SecurityException, IllegalArgumentException, URISyntaxException { checkInitialized(); - if(null == jarURI) { - throw new IllegalArgumentException("jarURI is null"); + if(null == jarUri) { + throw new IllegalArgumentException("jarUri is null"); } - final LoadState nativeLibJarsLS = nativeLibJars.get(jarURI); - final LoadState classFileJarsLS = classFileJars.get(jarURI); - final LoadState resourceFileJarsLS = resourceFileJars.get(jarURI); + final LoadState nativeLibJarsLS = nativeLibJars.get(jarUri); + final LoadState classFileJarsLS = classFileJars.get(jarUri); + final LoadState resourceFileJarsLS = resourceFileJars.get(jarUri); if( !testLoadState(nativeLibJarsLS, LoadState.LOOKED_UP) || !testLoadState(classFileJarsLS, LoadState.LOOKED_UP) || !testLoadState(resourceFileJarsLS, LoadState.LOOKED_UP) ) { @@ -333,18 +344,18 @@ public class TempJarCache { // mark looked-up (those who are not loaded) if(extractNativeLibraries) { - nativeLibJars.put(jarURI, LoadState.LOOKED_UP); + nativeLibJars.put(jarUri, LoadState.LOOKED_UP); } if(extractClassFiles) { - classFileJars.put(jarURI, LoadState.LOOKED_UP); + classFileJars.put(jarUri, LoadState.LOOKED_UP); } if(extractOtherFiles) { - resourceFileJars.put(jarURI, LoadState.LOOKED_UP); + resourceFileJars.put(jarUri, LoadState.LOOKED_UP); } - final JarFile jarFile = JarUtil.getJarFile(jarURI); + final JarFile jarFile = JarUtil.getJarFile(jarUri); if(DEBUG) { - System.err.println("TempJarCache: addAll: "+jarURI+": nativeJar "+jarFile.getName()); + System.err.println("TempJarCache: addAll: "+jarUri+": nativeJar "+jarFile.getName()); } validateCertificates(certClass, jarFile); JarUtil.extract(tmpFileCache.getTempDir(), nativeLibMap, jarFile, @@ -352,18 +363,18 @@ public class TempJarCache { // mark loaded (those were just loaded) if(extractNativeLibraries) { - nativeLibJars.put(jarURI, LoadState.LOADED); + nativeLibJars.put(jarUri, LoadState.LOADED); } if(extractClassFiles) { - classFileJars.put(jarURI, LoadState.LOADED); + classFileJars.put(jarUri, LoadState.LOADED); } if(extractOtherFiles) { - resourceFileJars.put(jarURI, LoadState.LOADED); + resourceFileJars.put(jarUri, LoadState.LOADED); } } else if( !testLoadState(nativeLibJarsLS, LoadState.LOADED) || !testLoadState(classFileJarsLS, LoadState.LOADED) || !testLoadState(resourceFileJarsLS, LoadState.LOADED) ) { - throw new IOException("TempJarCache: addAll: "+jarURI+", previous load attempt failed"); + throw new IOException("TempJarCache: addAll: "+jarUri+", previous load attempt failed"); } } @@ -408,12 +419,20 @@ public class TempJarCache { return null; } + /** + * See {@link #getResourceUri(String)} + * @deprecated Use {@link #getResourceUri(String)} + */ + public synchronized static final java.net.URI getResource(final String name) throws URISyntaxException { + return getResourceUri(name).toURI(); + } + /** Similar to {@link ClassLoader#getResource(String)}. */ - public synchronized static final URI getResource(final String name) throws URISyntaxException { + public synchronized static final Uri getResourceUri(final String name) throws URISyntaxException { checkInitialized(); final File f = new File(tmpFileCache.getTempDir(), name); if(f.exists()) { - return Uri.valueOf(f).toURI(); + return Uri.valueOf(f); } return null; } -- cgit v1.2.3