From 0a45d6ca9b9a8d92b5e4c147be94fad8de344816 Mon Sep 17 00:00:00 2001
From: Sven Gothel <sgothel@jausoft.com>
Date: Thu, 22 Sep 2011 00:29:59 +0200
Subject: JNILibLoaderBase/TempJarCache: Prepare for loadLibrary(..) out of
 cached JARs

- JNILibLoaderBase: If TempJarCache is active, try find native library in cached JARs
- TempJarCache: Add bootstrabNativeLib(..) allowing bootstraping gluegen-rt from JAR w/o needing it
- JARUtil: minor edits (final)
---
 .../com/jogamp/common/jvm/JNILibLoaderBase.java    | 19 ++++++++-
 src/java/com/jogamp/common/util/JarUtil.java       | 12 +++---
 .../com/jogamp/common/util/cache/TempJarCache.java | 49 +++++++++++++++++++++-
 3 files changed, 71 insertions(+), 9 deletions(-)

diff --git a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
index 161f0c4..44cbd14 100644
--- a/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
+++ b/src/java/com/jogamp/common/jvm/JNILibLoaderBase.java
@@ -44,6 +44,9 @@ import java.lang.reflect.Method;
 import java.security.AccessController;
 import java.security.AccessControlContext;
 import java.util.HashSet;
+
+import com.jogamp.common.util.cache.TempJarCache;
+
 import jogamp.common.Debug;
 
 public class JNILibLoaderBase {
@@ -148,7 +151,6 @@ public class JNILibLoaderBase {
   // private static final Class<?> customLauncherClass;
   private static final Method customLoadLibraryMethod;
 
-  // FIXME centralize logging
   static {
     final String sunAppletLauncherProperty = "sun.jnlp.applet.launcher";
     final String sunAppletLauncherClassName = "org.jdesktop.applet.util.JNLPAppletLauncher";
@@ -222,7 +224,22 @@ public class JNILibLoaderBase {
           throw (UnsatisfiedLinkError) new UnsatisfiedLinkError("can not load library "+libraryName).initCause(e);
         }
     } else {
+      if(TempJarCache.isInitialized()) {
+          final String fullLibraryName = TempJarCache.findLibrary(libraryName);
+          if(null != fullLibraryName) {
+            if(DEBUG) {
+              System.err.println("JNILibLoaderBase.loadLibraryInternal("+libraryName+") -> System.load("+fullLibraryName+") (TempJarCache)");
+            }
+            System.load(fullLibraryName);
+            return; // done
+          } else if(DEBUG) {
+            System.err.println("JNILibLoaderBase.loadLibraryInternal("+libraryName+") -> TempJarCache not mapped");
+          }
+      }
       // System.err.println("sun.boot.library.path=" + Debug.getProperty("sun.boot.library.path", false));
+      if(DEBUG) {
+          System.err.println("JNILibLoaderBase.loadLibraryInternal("+libraryName+") -> System.loadLibrary("+libraryName+")");
+      }
       System.loadLibrary(libraryName);
     }
   }
diff --git a/src/java/com/jogamp/common/util/JarUtil.java b/src/java/com/jogamp/common/util/JarUtil.java
index a2e6be5..3cbd555 100644
--- a/src/java/com/jogamp/common/util/JarUtil.java
+++ b/src/java/com/jogamp/common/util/JarUtil.java
@@ -202,7 +202,7 @@ public class JarUtil {
                               boolean extractOtherFiles) throws IOException {
 
         if (VERBOSE) {
-            System.err.println("extractNativeLibs: "+jarFile.getName()+" -> "+dest+
+            System.err.println("extract: "+jarFile.getName()+" -> "+dest+
                                ", extractNativeLibraries "+extractNativeLibraries+
                                ", extractClassFiles"+extractClassFiles+
                                ", extractOtherFiles "+extractOtherFiles);
@@ -239,12 +239,11 @@ public class JarUtil {
                 continue;
             }
 
-            boolean isDir = entryName.endsWith("/");
+            final boolean isDir = entryName.endsWith("/");
             
-            boolean isRootEntry = entryName.indexOf('/') == -1 && 
-                                  entryName.indexOf(File.separatorChar) == -1;
+            final boolean isRootEntry = entryName.indexOf('/') == -1 && 
+                                        entryName.indexOf(File.separatorChar) == -1;
             
-            // strip prefix & suffix
             final File destFile = new File(dest, entryName);
             if(isDir) {
                 destFile.mkdir();
@@ -276,7 +275,7 @@ public class JarUtil {
         }
         return num;
     }
-    
+
     /**
      * Validate the certificates for each native Lib in the jar file.
      * Throws an IOException if any certificate is not valid.
@@ -306,7 +305,6 @@ public class JarUtil {
                 throw new IOException("Cannot validate certificate for " + entryName);
             }
         }
-
     }
 
     /**
diff --git a/src/java/com/jogamp/common/util/cache/TempJarCache.java b/src/java/com/jogamp/common/util/cache/TempJarCache.java
index 9da7d0c..dcc6651 100644
--- a/src/java/com/jogamp/common/util/cache/TempJarCache.java
+++ b/src/java/com/jogamp/common/util/cache/TempJarCache.java
@@ -27,12 +27,19 @@
  */
 package com.jogamp.common.util.cache;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.Enumeration;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
+import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
 
 import com.jogamp.common.os.NativeLibrary;
@@ -168,7 +175,7 @@ public class TempJarCache {
     }
     
     /**
-     * Adds all types, native libraries, class files and other files (resources),
+     * Adds all types, native libraries, class files and other files (resources)
      * if not yet added.
      *  
      * TODO class access pending
@@ -242,4 +249,44 @@ public class TempJarCache {
         return null;
     }
     
+    /**
+     * Bootstrapping version extracting the JAR files root entry containing libBaseName,
+     * assuming it's a native library. This is used to get the 'gluegen-rt'
+     * native library, hence bootstrapping. 
+     */
+    public static boolean bootstrapNativeLib(String libBaseName, JarFile jarFile) throws IOException {
+        checkInitialized();
+        if(!nativeLibJars.contains(jarFile) && !nativeLibMap.containsKey(libBaseName) ) {                    
+            final Enumeration<JarEntry> entries = jarFile.entries();
+            while (entries.hasMoreElements()) {
+                final JarEntry entry = (JarEntry) entries.nextElement();
+                final String entryName = entry.getName();
+    
+                if( entryName.indexOf('/') == -1 &&
+                    entryName.indexOf(File.separatorChar) == -1 &&
+                    entryName.indexOf(libBaseName) >= 0 ) 
+                {
+                    final File destFile = new File(tmpFileCache.getTempDir(), entryName);
+                    final InputStream in = new BufferedInputStream(jarFile.getInputStream(entry));
+                    final OutputStream out = new BufferedOutputStream(new FileOutputStream(destFile));
+                    int numBytes = 0; 
+                    try {
+                        final byte[] buf = new byte[ 2048 ];
+                        while (true) {
+                            int count;
+                            if ((count = in.read(buf)) == -1) { break; }
+                            out.write(buf, 0, count);
+                            numBytes += count;
+                        }
+                    } finally { in.close(); out.close(); }
+                    if (numBytes>0) {
+                        nativeLibMap.put(libBaseName, destFile.getAbsolutePath());
+                        nativeLibJars.add(jarFile);
+                        return true;
+                    }
+                }
+            }
+        }
+        return false;
+    }
 }
-- 
cgit v1.2.3