28import java.io.BufferedInputStream;
 
   29import java.io.BufferedOutputStream;
 
   31import java.io.FileOutputStream;
 
   32import java.io.IOException;
 
   33import java.io.InputStream;
 
   34import java.io.OutputStream;
 
   35import java.net.JarURLConnection;
 
   36import java.net.URISyntaxException;
 
   38import java.net.URLConnection;
 
   39import java.security.cert.Certificate;
 
   40import java.util.Enumeration;
 
   41import java.util.HashMap;
 
   43import java.util.jar.JarEntry;
 
   44import java.util.jar.JarFile;
 
   46import org.jau.io.IOUtil;
 
   47import org.jau.net.Uri;
 
   48import org.jau.sec.SecurityUtil;
 
   49import org.jau.sys.Debug;
 
   50import org.jau.sys.JNILibrary;
 
   51import org.jau.sys.PlatformProps;
 
   52import org.jau.sys.PlatformTypes;
 
   55    private static final boolean DEBUG = 
Debug.
debug(
"JarUtil");
 
   57    private static final int BUFFER_SIZE = 4096;
 
   86    @SuppressWarnings({ 
"removal" })
 
   87    public static void setResolver(
final Resolver r) 
throws IllegalArgumentException, IllegalStateException, SecurityException {
 
   89            throw new IllegalArgumentException(
"Null Resolver passed");
 
   92        if(resolver != 
null) {
 
   93            throw new IllegalStateException(
"Resolver already set!");
 
   97        if(security != 
null) {
 
   98            security.checkSetFactory();
 
 
  117    public static boolean hasJarUri(
final String clazzBinName, 
final ClassLoader cl) {
 
  119            return null != 
getJarUri(clazzBinName, cl);
 
  120        } 
catch (
final Exception e) {  }
 
 
  140    public static Uri getJarUri(
final String clazzBinName, 
final ClassLoader cl) 
throws IllegalArgumentException, IOException, URISyntaxException {
 
  141        if(
null == clazzBinName || 
null == cl) {
 
  142            throw new IllegalArgumentException(
"null arguments: clazzBinName "+clazzBinName+
", cl "+cl);
 
  148            final String scheme = url.getProtocol();
 
  149            if( 
null != resolver &&
 
  155                final URL _url = resolver.resolve( url );
 
  158                    System.err.println(
"getJarUri Resolver: "+url+
"\n\t-> "+_url+
"\n\t-> "+uri);
 
  163                    System.err.println(
"getJarUri Default "+url+
"\n\t-> "+uri);
 
  168            throw new IllegalArgumentException(
"Uri is not using scheme "+
Uri.
JAR_SCHEME+
": <"+uri+
">");
 
  171            System.err.println(
"getJarUri res: "+clazzBinName+
" -> "+url+
" -> "+uri);
 
 
  191        if(
null == classJarUri) {
 
  192            throw new IllegalArgumentException(
"Uri is null");
 
  194        if( !classJarUri.isJarScheme() ) {
 
  195            throw new IllegalArgumentException(
"Uri is not using scheme "+
Uri.
JAR_SCHEME+
": <"+classJarUri+
">");
 
  205            ssp = ssp.substring(0, idx); 
 
  207            throw new IllegalArgumentException(
"Uri does not contain jar uri terminator '!', in <"+classJarUri+
">");
 
  214        idx = ssp.lastIndexOf(
'/');
 
  217            idx = ssp.lastIndexOf(
':');
 
  219                throw new IllegalArgumentException(
"Uri does not contain protocol terminator ':', in <"+classJarUri+
">");
 
  222        ssp = ssp.substring(idx+1); 
 
  224        if(0 >= ssp.lastIndexOf(
".jar")) {
 
  225            throw new IllegalArgumentException(
"No Jar name in <"+classJarUri+
">");
 
  228            System.err.println(
"getJarName res: "+ssp);
 
 
  249    public static Uri.Encoded getJarBasename(
final String clazzBinName, 
final ClassLoader cl) 
throws IllegalArgumentException, IOException, URISyntaxException {
 
 
  263        if(
null == classJarUri) {
 
  264            throw new IllegalArgumentException(
"Uri is null");
 
  267            throw new IllegalArgumentException(
"Uri is not a using scheme "+
Uri.
JAR_SCHEME+
": <"+classJarUri+
">");
 
  280                System.err.println(
"getJarEntry res: "+classJarUri+
" -> "+uriSSP+
" -> "+idx+
" -> "+res);
 
  284            throw new IllegalArgumentException(
"JAR Uri does not contain jar uri terminator '!', uri <"+classJarUri+
">");
 
 
  304    public static Uri getJarFileUri(
final String clazzBinName, 
final ClassLoader cl) 
throws IllegalArgumentException, IOException, URISyntaxException {
 
  305        if(
null == clazzBinName || 
null == cl) {
 
  306            throw new IllegalArgumentException(
"null arguments: clazzBinName "+clazzBinName+
", cl "+cl);
 
  311            System.err.println(
"getJarFileUri res: "+uri);
 
 
  324        if(
null == baseUri || 
null == jarFileName) {
 
  325            throw new IllegalArgumentException(
"null arguments: baseUri "+baseUri+
", jarFileName "+jarFileName);
 
 
  336    public static Uri getJarFileUri(
final Uri jarSubUri) 
throws IllegalArgumentException, URISyntaxException {
 
  337        if(
null == jarSubUri) {
 
  338            throw new IllegalArgumentException(
"jarSubUri is null");
 
 
  350        if(
null == jarSubUriS) {
 
  351            throw new IllegalArgumentException(
"jarSubUriS is null");
 
 
  364        if(
null == jarEntry) {
 
  365            throw new IllegalArgumentException(
"jarEntry is null");
 
  367        return Uri.
cast(jarFileUri.toString()+jarEntry);
 
 
  379    public static JarFile 
getJarFile(
final String clazzBinName, 
final ClassLoader cl) 
throws IOException, IllegalArgumentException, URISyntaxException {
 
 
  390    public static JarFile 
getJarFile(
final Uri jarFileUri) 
throws IOException, IllegalArgumentException, URISyntaxException {
 
  391        if(
null == jarFileUri) {
 
  392            throw new IllegalArgumentException(
"null jarFileUri");
 
  395            System.err.println(
"getJarFile.0: "+jarFileUri.toString());
 
  397        final URL jarFileURL = jarFileUri.toURL();
 
  399            System.err.println(
"getJarFile.1: "+jarFileURL.toString());
 
  401        final URLConnection urlc = jarFileURL.openConnection();
 
  402        if(urlc instanceof JarURLConnection) {
 
  403            final JarURLConnection jarConnection = (JarURLConnection)jarFileURL.openConnection();
 
  404            final JarFile jarFile = jarConnection.getJarFile();
 
  406                System.err.println(
"getJarFile res: "+jarFile.getName());
 
  411            System.err.println(
"getJarFile res: NULL");
 
 
  448    public static Uri getRelativeOf(
final Class<?> classFromJavaJar, 
final Uri.
Encoded cutOffInclSubDir, 
final Uri.
Encoded relResPath) 
throws IllegalArgumentException, IOException, URISyntaxException {
 
  449        final ClassLoader cl = classFromJavaJar.getClassLoader();
 
  452            System.err.println(
"JarUtil.getRelativeOf: "+
"(classFromJavaJar "+classFromJavaJar+
", classJarUri "+classJarUri+
 
  453                    ", cutOffInclSubDir "+cutOffInclSubDir+
", relResPath "+relResPath+
"): ");
 
  457        if(
null == jarSubUri) {
 
  458            throw new IllegalArgumentException(
"JarSubUri is null of: "+classJarUri);
 
  462            System.err.println(
"JarUtil.getRelativeOf: "+
"uri "+jarSubUri.
toString()+
" -> "+jarUriRoot);
 
  466        if( jarUriRoot.endsWith(cutOffInclSubDir.get()) ) {
 
  467            resUri = jarUriRoot.concat(relResPath);
 
  469            resUri = jarUriRoot.concat(cutOffInclSubDir).concat(relResPath);
 
  472            System.err.println(
"JarUtil.getRelativeOf: "+
"...  -> "+resUri);
 
  477            System.err.println(
"JarUtil.getRelativeOf: "+
"fin "+resJarUri);
 
 
  487            System.err.println(
"JarUtil: getNativeLibNames: "+jarFile);
 
  490        final Map<String,String> nameMap = 
new HashMap<String, String>();
 
  491        final Enumeration<JarEntry> entries = jarFile.entries();
 
  493        while (entries.hasMoreElements()) {
 
  494            final JarEntry entry = entries.nextElement();
 
  495            final String entryName = entry.getName();
 
  498            if(
null != baseName) {
 
  499                nameMap.put(baseName, entryName);
 
 
  541    public static final int extract(
final File dest, 
final Map<String, String> nativeLibMap,
 
  542                                    final JarFile jarFile,
 
  543                                    final String nativeLibraryPath,
 
  544                                    final boolean extractNativeLibraries,
 
  545                                    final boolean extractClassFiles, 
final boolean extractOtherFiles) 
throws IOException {
 
  548            System.err.println(
"JarUtil: extract: "+jarFile.getName()+
" -> "+dest+
 
  549                               ", extractNativeLibraries "+extractNativeLibraries+
" ("+nativeLibraryPath+
")"+
 
  550                               ", extractClassFiles "+extractClassFiles+
 
  551                               ", extractOtherFiles "+extractOtherFiles);
 
  555        final Enumeration<JarEntry> entries = jarFile.entries();
 
  556        while (entries.hasMoreElements()) {
 
  557            final JarEntry entry = entries.nextElement();
 
  558            final String entryName = entry.getName();
 
  562            final boolean isNativeLib = 
null != libBaseName;
 
  564                if(!extractNativeLibraries) {
 
  566                        System.err.println(
"JarUtil: JarEntry : " + entryName + 
" native-lib skipped, skip all native libs");
 
  570                if(
null != nativeLibraryPath) {
 
  571                    final String nativeLibraryPathS;
 
  572                    final String dirnameS;
 
  574                        nativeLibraryPathS = 
IOUtil.
slashify(nativeLibraryPath, 
false , 
true );
 
  576                    } 
catch (
final URISyntaxException e) {
 
  577                        throw new IOException(e);
 
  579                    if( !nativeLibraryPathS.equals(dirnameS) ) {
 
  581                            System.err.println(
"JarUtil: JarEntry : " + entryName + 
" native-lib skipped, not in path: "+nativeLibraryPathS);
 
  588            final boolean isClassFile = entryName.endsWith(
".class");
 
  589            if(isClassFile && !extractClassFiles) {
 
  591                    System.err.println(
"JarUtil: JarEntry : " + entryName + 
" class-file skipped");
 
  596            if(!isNativeLib && !isClassFile && !extractOtherFiles) {
 
  598                    System.err.println(
"JarUtil: JarEntry : " + entryName + 
" other-file skipped");
 
  603            final boolean isDir = entryName.endsWith(
"/");
 
  605            final boolean isRootEntry = entryName.indexOf(
'/') == -1 &&
 
  606                                        entryName.indexOf(File.separatorChar) == -1;
 
  609                System.err.println(
"JarUtil: JarEntry : isNativeLib " + isNativeLib +
 
  610                                   ", isClassFile " + isClassFile + 
", isDir " + isDir +
 
  611                                   ", isRootEntry " + isRootEntry );
 
  614            final File destFile = 
new File(dest, entryName);
 
  617                    System.err.println(
"JarUtil: MKDIR: " + entryName + 
" -> " + destFile );
 
  621                final File destFolder = 
new File(destFile.getParent());
 
  622                if(!destFolder.exists()) {
 
  624                        System.err.println(
"JarUtil: MKDIR (parent): " + entryName + 
" -> " + destFolder );
 
  628                final InputStream in = 
new BufferedInputStream(jarFile.getInputStream(entry));
 
  629                final OutputStream out = 
new BufferedOutputStream(
new FileOutputStream(destFile));
 
  637                boolean addedAsNativeLib = 
false;
 
  640                    if (isNativeLib && ( isRootEntry || !nativeLibMap.containsKey(libBaseName) ) ) {
 
  641                        nativeLibMap.put(libBaseName, destFile.getAbsolutePath());
 
  642                        addedAsNativeLib = 
true;
 
  643                        fixNativeLibAttribs(destFile);
 
  647                    System.err.println(
"JarUtil: EXTRACT["+num+
"]: [" + libBaseName + 
" -> ] " + entryName + 
" -> " + destFile + 
": "+numBytes+
" bytes, addedAsNativeLib: "+addedAsNativeLib);
 
 
  660    private final static void fixNativeLibAttribs(
final File file) {
 
  665            final String fileAbsPath = file.getAbsolutePath();
 
  667                fixNativeLibAttribs(fileAbsPath);
 
  669                    System.err.println(
"JarUtil.fixNativeLibAttribs: "+fileAbsPath+
" - OK");
 
  671            } 
catch (
final Throwable t) {
 
  673                    System.err.println(
"JarUtil.fixNativeLibAttribs: "+fileAbsPath+
" - "+t.getClass().getSimpleName()+
": "+t.getMessage());
 
  678    private native 
static boolean fixNativeLibAttribs(String fname);
 
  689            throws IOException, SecurityException {
 
  692            System.err.println(
"JarUtil: validateCertificates: "+jarFile.getName());
 
  695        if (rootCerts == 
null || rootCerts.length == 0) {
 
  696            throw new IllegalArgumentException(
"Null certificates passed");
 
  699        final byte[] buf = 
new byte[1024];
 
  700        final Enumeration<JarEntry> entries = jarFile.entries();
 
  701        while (entries.hasMoreElements()) {
 
  702            final JarEntry entry = entries.nextElement();
 
  703            if( ! entry.isDirectory() && ! entry.getName().startsWith(
"META-INF/") ) {
 
  705                validateCertificate(rootCerts, jarFile, entry, buf);
 
 
  714    private static final void validateCertificate(
final Certificate[] rootCerts,
 
  715            final JarFile jar, 
final JarEntry entry, 
final byte[] buf) 
throws IOException, SecurityException {
 
  718            System.err.println(
"JarUtil: validate JarEntry : " + entry.getName());
 
  724        final InputStream is = jar.getInputStream(entry);
 
  726            while (is.read(buf) > 0) { }
 
  732        final Certificate[] nativeCerts = entry.getCertificates();
 
  733        if (nativeCerts == 
null || nativeCerts.length == 0) {
 
  734            throw new SecurityException(
"no certificate for " + entry.getName() + 
" in " + jar.getName());
 
  737        if( !SecurityUtil.equals(rootCerts, nativeCerts) ) {
 
  738            throw new SecurityException(
"certificates not equal for " + entry.getName() + 
" in " + jar.getName());
 
 
static URL getClassURL(final String clazzBinName, final ClassLoader cl)
static int copyStream2Stream(final InputStream in, final OutputStream out, final int totalNumBytes)
Copy the specified input stream to the specified output stream.
static String getDirname(String fname)
Returns unified '/' dirname including the last '/'.
static String slashify(final String path, final boolean startWithSlash, final boolean endWithSlash)
Immutable RFC3986 encoded string.
final int lastIndexOf(final int ch)
See String#lastIndexOf(int).
final Encoded substring(final int start)
See String#substring(int).
This class implements an immutable Uri as defined by RFC 2396.
Uri getDirectory()
Returns this Uri's directory Uri.
final String toString()
Returns the encoded input as String, never null, same as getEncoded().
final Encoded getEncoded()
Returns the encoded input, never null.
final Encoded schemeSpecificPart
Encoded scheme-specific-part, never null.
static final String HTTP_SCHEME
{@value}
final boolean isJarScheme()
Returns true, if this instance is a jar scheme, otherwise false.
static Uri cast(final String encodedUri)
Casts the given encoded String to a new Encoded instance used to create the resulting Uri instance vi...
final Uri getContainedUri()
If this instance's schemeSpecificPart contains a Uri itself, a sub-Uri, return schemeSpecificPart + #...
static Uri valueOf(final File file)
Creates a new Uri instance using the given File instance.
static final String FILE_SCHEME
{@value}
static final String JAR_SCHEME
{@value}
static final String HTTPS_SCHEME
{@value}
static final char JAR_SCHEME_SEPARATOR
A JAR sub-protocol is separated from the JAR entry w/ this separator {@value}.
static final char SCHEME_SEPARATOR
{@value}
static Uri getJarFileUri(final String clazzBinName, final ClassLoader cl)
The Class's "com.jogamp.common.GlueGenVersion" Uri jar:sub_protocol:/some/path/gluegen-rt....
static Uri getJarFileUri(final Uri baseUri, final Uri.Encoded jarFileName)
static Uri getJarUri(final String clazzBinName, final ClassLoader cl)
The Class's "com.jogamp.common.GlueGenVersion" Uri jar:sub_protocol:/some/path/gluegen-rt....
static JarFile getJarFile(final Uri jarFileUri)
static Uri.Encoded getJarBasename(final String clazzBinName, final ClassLoader cl)
The Class's com.jogamp.common.GlueGenVersion Uri jar:sub_protocol:/some/path/gluegen-rt....
static boolean hasJarUri(final String clazzBinName, final ClassLoader cl)
Returns true if the Class's "com.jogamp.common.GlueGenVersion" is loaded from a JarFile and hence has...
static Uri getJarFileUri(final Uri jarSubUri)
static void setResolver(final Resolver r)
Setting a custom Resolver instance.
static JarFile getJarFile(final String clazzBinName, final ClassLoader cl)
static Uri getRelativeOf(final Class<?> classFromJavaJar, final Uri.Encoded cutOffInclSubDir, final Uri.Encoded relResPath)
Locates the Jar file Uri of a given resource relative to a given class's Jar's Uri.
static final int extract(final File dest, final Map< String, String > nativeLibMap, final JarFile jarFile, final String nativeLibraryPath, final boolean extractNativeLibraries, final boolean extractClassFiles, final boolean extractOtherFiles)
Extract the files of the given jar file.
static final void validateCertificates(final Certificate[] rootCerts, final JarFile jarFile)
Validate the certificates for each native Lib in the jar file.
static Uri.Encoded getJarEntry(final Uri classJarUri)
The Class's Jar Uri jar:sub_protocol:/some/path/gluegen-rt.jar!
static Uri.Encoded getJarBasename(final Uri classJarUri)
The Class's Jar Uri jar:sub_protocol:/some/path/gluegen-rt.jar!
static Map< String, String > getNativeLibNames(final JarFile jarFile)
Return a map from native-lib-base-name to entry-name.
static Uri getJarFileUri(final Uri.Encoded jarSubUriS)
static Uri getJarEntryUri(final Uri jarFileUri, final Uri.Encoded jarEntry)
static final SecurityManager getSecurityManager()
Call wrapper for System#getSecurityManager().
Helper routines for logging and debugging.
static final boolean debug(final String subcomponent)
Static JNI Native Libraries handler.
static final String isValidNativeLibraryName(final String libName, final boolean isLowerCaseAlready)
Comparison of prefix and suffix of the given libName's basename is performed case insensitive
Interface allowing users to provide an URL resolver that will convert custom classloader URLs like Ec...