summaryrefslogtreecommitdiffstats
path: root/src/java/com/jogamp/common/os
diff options
context:
space:
mode:
authorSven Gothel <[email protected]>2010-06-10 06:13:06 +0200
committerSven Gothel <[email protected]>2010-06-10 06:13:06 +0200
commit555091d37a9a44fb7c35479ddecfee358a559e90 (patch)
tree350a3b9b7f55db85dcf3a808f0249bcd0ab32a74 /src/java/com/jogamp/common/os
parent710d86d31cd278583ee3d74b36595f4148a72133 (diff)
Adding DynamicLibraryBundle utility to bundle Tool and JNI native library loading and lookup
Add JNILibLoaderBase.loadLibrary(String libname, boolean ignoreError); DynamicLibraryBundle provides Tool and JNI native library loading and lookup New classes: com.jogamp.common.os.DynamicLibraryBundle com.jogamp.common.os.DynamicLibraryBundleInfo com.jogamp.common.util.MiscUtils.java Change: DEBUG/VERBOSE properties 'gluegen' -> 'jogamp'
Diffstat (limited to 'src/java/com/jogamp/common/os')
-rwxr-xr-xsrc/java/com/jogamp/common/os/DynamicLibraryBundle.java327
-rw-r--r--src/java/com/jogamp/common/os/DynamicLibraryBundleInfo.java75
-rwxr-xr-xsrc/java/com/jogamp/common/os/NativeLibrary.java6
-rwxr-xr-xsrc/java/com/jogamp/common/os/WindowsDynamicLinkerImpl.java2
4 files changed, 407 insertions, 3 deletions
diff --git a/src/java/com/jogamp/common/os/DynamicLibraryBundle.java b/src/java/com/jogamp/common/os/DynamicLibraryBundle.java
new file mode 100755
index 0000000..8e138ef
--- /dev/null
+++ b/src/java/com/jogamp/common/os/DynamicLibraryBundle.java
@@ -0,0 +1,327 @@
+/*
+ * Copyright (c) 2010, Sven Gothel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sven Gothel nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.jogamp.common.os;
+
+import java.util.*;
+import java.security.*;
+
+import com.jogamp.common.jvm.JNILibLoaderBase;
+import com.jogamp.common.util.MiscUtils;
+
+/**
+ * Provides bundling of:<br>
+ * <ul>
+ * <li>The to-be-glued native library, eg OpenGL32.dll. From hereon this is referred as the Tool.</li>
+ * <li>The JNI glue-code native library, eg jogl_desktop.dll. From heron this is referred as the Glue</li>
+ * </ul><br>
+ * An instance provides a complete {@link com.jogamp.common.os.DynamicLookupHelper}
+ * to {@link com.jogamp.gluegen.runtime.ProcAddressTable#reset(com.jogamp.common.os.DynamicLookupHelper lookup)}
+ * the {@link com.jogamp.gluegen.runtime.ProcAddressTable}.<br>
+ * At construction, it loads the Tool native library, loads Glue native library via
+ * {@link com.jogamp.common.os.DynamicLibraryBundleInfo#loadJNILibrary()}
+ * and resolves the optional Tool's <pre>GetProcAddress</pre> using {@link com.jogamp.common.os.DynamicLibraryBundleInfo#getToolGetProcAddressFuncNameList()}.
+ */
+public class DynamicLibraryBundle implements DynamicLookupHelper {
+ protected static final boolean DEBUG = NativeLibrary.DEBUG;
+ protected static final boolean DEBUG_LOOKUP = NativeLibrary.DEBUG_LOOKUP;
+
+ private DynamicLibraryBundleInfo info;
+
+ private List/*<List<String>>*/ toolLibNames;
+ private boolean[] toolLibLoaded;
+ private int toolLibLoadedNumber;
+ protected List/*<NativeLibrary>*/ nativeLibraries;
+
+ private List/*<String>*/ glueLibNames;
+ private boolean[] glueLibLoaded;
+ private int glueLibLoadedNumber;
+
+ private long toolGetProcAddressHandle;
+ private HashSet toolGetProcAddressFuncNameSet;
+ private List toolGetProcAddressFuncNameList;
+
+ public DynamicLibraryBundle(DynamicLibraryBundleInfo info) {
+ if(null==info) {
+ throw new RuntimeException("Null DynamicLibraryBundleInfo");
+ }
+ this.info = info;
+ if(DEBUG) {
+ System.out.println("DynamicLibraryBundle.init start with: "+info.getClass().getName());
+ }
+ nativeLibraries = new ArrayList();
+ toolLibNames = info.getToolLibNames();
+ glueLibNames = info.getGlueLibNames();
+ loadLibraries();
+ toolGetProcAddressFuncNameList = info.getToolGetProcAddressFuncNameList();
+ if(null!=toolGetProcAddressFuncNameList) {
+ toolGetProcAddressFuncNameSet = new HashSet(toolGetProcAddressFuncNameList);
+ toolGetProcAddressHandle = getToolGetProcAddressHandle();
+ } else {
+ toolGetProcAddressFuncNameSet = new HashSet();
+ toolGetProcAddressHandle = 0;
+ }
+ if(DEBUG) {
+ System.out.println("DynamicLibraryBundle.init Summary: "+info.getClass().getName());
+ System.out.println(" toolGetProcAddressFuncNameList: "+MiscUtils.toString(toolGetProcAddressFuncNameList));
+ System.out.println(" Tool Lib Names : "+MiscUtils.toString(toolLibNames));
+ System.out.println(" Tool Lib Loaded: "+getToolLibLoadedNumber()+"/"+getToolLibNumber()+", complete "+isToolLibComplete());
+ System.out.println(" Glue Lib Names : "+MiscUtils.toString(glueLibNames));
+ System.out.println(" Glue Lib Loaded: "+getGlueLibLoadedNumber()+"/"+getGlueLibNumber()+", complete "+isGlueLibComplete());
+ System.out.println(" All Complete: "+isLibComplete());
+ }
+ }
+
+ public final boolean isLibComplete() {
+ return isToolLibComplete() && isGlueLibComplete() ;
+ }
+
+ public final int getToolLibNumber() {
+ return toolLibNames.size();
+ }
+
+ public final int getToolLibLoadedNumber() {
+ return toolLibLoadedNumber;
+ }
+
+ public final boolean isToolLibComplete() {
+ return getToolLibNumber() == getToolLibLoadedNumber();
+ }
+
+ public final boolean isToolLibLoaded() {
+ return 0 < toolLibLoadedNumber;
+ }
+
+ public final boolean isToolLibLoaded(int i) {
+ if(0 <= i && i < toolLibLoaded.length) {
+ return toolLibLoaded[i];
+ }
+ return false;
+ }
+
+ public final int getGlueLibNumber() {
+ return glueLibNames.size();
+ }
+
+ public final int getGlueLibLoadedNumber() {
+ return glueLibLoadedNumber;
+ }
+
+ public final boolean isGlueLibComplete() {
+ return getGlueLibNumber() == getGlueLibLoadedNumber();
+ }
+
+ public final boolean isGlueLibLoaded(int i) {
+ if(0 <= i && i < glueLibLoaded.length) {
+ return glueLibLoaded[i];
+ }
+ return false;
+ }
+
+ public final DynamicLibraryBundleInfo getBundleInfo() { return info; }
+
+ protected long getToolGetProcAddressHandle() {
+ if(!isToolLibLoaded()) {
+ return 0;
+ }
+ long aptr = 0;
+ for(Iterator iter=toolGetProcAddressFuncNameList.iterator(); 0==aptr && iter.hasNext(); ) {
+ String name = (String) iter.next();
+ aptr = dynamicLookupFunctionOnLibs(name);
+ if(DEBUG) {
+ System.out.println("getToolGetProcAddressHandle: "+name+" -> 0x"+Long.toHexString(aptr));
+ }
+ }
+ return aptr;
+ }
+
+ protected NativeLibrary loadFirstAvailable(List/*<String>*/ libNames, ClassLoader loader, boolean global) {
+ for (Iterator iter = libNames.iterator(); iter.hasNext(); ) {
+ NativeLibrary lib = NativeLibrary.open((String) iter.next(), loader, global);
+ if (lib != null) {
+ return lib;
+ }
+ }
+ return null;
+ }
+
+ private void loadLibraries() {
+ if( null == toolLibNames || toolLibNames.size() == 0) {
+ if(DEBUG) {
+ System.out.println("No Tool native library names given");
+ }
+ return;
+ }
+
+ if( null == glueLibNames || glueLibNames.size() == 0 ) {
+ if(DEBUG) {
+ System.out.println("No Glue native library names given");
+ }
+ return;
+ }
+
+ toolLibLoadedNumber = 0;
+ int i;
+ toolLibLoaded = new boolean[toolLibNames.size()];
+ for(i=0; i<toolLibNames.size(); i++) {
+ toolLibLoaded[i] = false;
+ }
+
+ glueLibLoaded = new boolean[glueLibNames.size()];
+ for(i=0; i<glueLibNames.size(); i++) {
+ glueLibLoaded[i] = false;
+ }
+
+ ClassLoader loader = getClass().getClassLoader();
+ NativeLibrary lib = null;
+
+ i=0;
+ for(Iterator iter = toolLibNames.iterator(); iter.hasNext(); i++) {
+ Object listObj = iter.next();
+ List/*<String>*/ libNames = null;
+ if(listObj instanceof List) {
+ libNames = (List) listObj;
+ } else if(listObj instanceof String) {
+ libNames = new ArrayList();
+ libNames.add((String)listObj);
+ } else {
+ throw new RuntimeException("List element "+i+" must be either a List or String: "+MiscUtils.toString(toolLibNames));
+ }
+ if( null != libNames && libNames.size() > 0 ) {
+ lib = loadFirstAvailable(libNames, loader, info.shallLinkGlobal());
+ if ( null == lib ) {
+ if(DEBUG) {
+ System.out.println("Unable to load any Tool library of: "+MiscUtils.toString(libNames));
+ }
+ } else {
+ nativeLibraries.add(lib);
+ toolLibLoaded[i]=true;
+ toolLibLoadedNumber++;
+ if(DEBUG) {
+ System.out.println("Loaded Tool library: "+lib);
+ }
+ }
+ }
+ }
+ if( !isToolLibLoaded() ) {
+ if(DEBUG) {
+ System.out.println("No Tool libraries loaded");
+ }
+ return;
+ }
+
+ glueLibLoadedNumber = 0;
+ i=0;
+ for(Iterator iter = glueLibNames.iterator(); iter.hasNext(); i++) {
+ String libName = (String) iter.next();
+ boolean ignoreError = true;
+ boolean res;
+ try {
+ res = GlueJNILibLoaderBase.loadLibrary(libName, ignoreError);
+ if(DEBUG && !res) {
+ System.out.println("Info: Could not load JNI/Glue library: "+libName);
+ }
+ } catch (UnsatisfiedLinkError e) {
+ res = false;
+ if(DEBUG) {
+ System.out.println("Unable to load JNI/Glue library: "+libName);
+ e.printStackTrace();
+ }
+ }
+ glueLibLoaded[i] = res;
+ if(res) {
+ glueLibLoadedNumber++;
+ }
+ }
+ }
+
+ private long dynamicLookupFunctionOnLibs(String funcName) {
+ if(!isToolLibLoaded() || null==funcName) {
+ if(DEBUG_LOOKUP && !isToolLibLoaded()) {
+ System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** Tool native library not loaded");
+ }
+ return 0;
+ }
+ long addr = 0;
+ NativeLibrary lib = null;
+
+ if(info.shallLookupGlobal()) {
+ // Try a global symbol lookup first ..
+ addr = NativeLibrary.dynamicLookupFunctionGlobal(funcName);
+ }
+ // Look up this function name in all known libraries
+ for (Iterator iter = nativeLibraries.iterator(); 0==addr && iter.hasNext(); ) {
+ lib = (NativeLibrary) iter.next();
+ addr = lib.dynamicLookupFunction(funcName);
+ }
+ if(DEBUG_LOOKUP) {
+ String libName = ( null == lib ) ? "GLOBAL" : lib.toString();
+ if(0!=addr) {
+ System.err.println("Lookup-Native: <" + funcName + "> 0x" + Long.toHexString(addr) + " in lib " + libName );
+ } else {
+ System.err.println("Lookup-Native: <" + funcName + "> ** FAILED ** in libs " + MiscUtils.toString(nativeLibraries));
+ }
+ }
+ return addr;
+ }
+
+ public long dynamicLookupFunction(String funcName) {
+ if(!isToolLibLoaded() || null==funcName) {
+ if(DEBUG_LOOKUP && !isToolLibLoaded()) {
+ System.err.println("Lookup: <" + funcName + "> ** FAILED ** Tool native library not loaded");
+ }
+ return 0;
+ }
+
+ if(toolGetProcAddressFuncNameSet.contains(funcName)) {
+ return toolGetProcAddressHandle;
+ }
+
+ long addr = 0;
+
+ if(0 != toolGetProcAddressHandle) {
+ addr = info.toolDynamicLookupFunction(toolGetProcAddressHandle, funcName);
+ if(DEBUG_LOOKUP) {
+ if(0!=addr) {
+ System.err.println("Lookup-Tool: <"+funcName+"> 0x"+Long.toHexString(addr));
+ }
+ }
+ }
+ if(0==addr) {
+ addr = dynamicLookupFunctionOnLibs(funcName);
+ }
+ return addr;
+ }
+
+ /** Inherit access */
+ static class GlueJNILibLoaderBase extends JNILibLoaderBase {
+ protected static synchronized boolean loadLibrary(String libname, boolean ignoreError) {
+ return JNILibLoaderBase.loadLibrary(libname, ignoreError);
+ }
+ }
+}
+
diff --git a/src/java/com/jogamp/common/os/DynamicLibraryBundleInfo.java b/src/java/com/jogamp/common/os/DynamicLibraryBundleInfo.java
new file mode 100644
index 0000000..37ca538
--- /dev/null
+++ b/src/java/com/jogamp/common/os/DynamicLibraryBundleInfo.java
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2010, Sven Gothel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of Sven Gothel nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL Sven Gothel BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package com.jogamp.common.os;
+
+import java.util.*;
+import java.security.*;
+
+public interface DynamicLibraryBundleInfo {
+ public static final boolean DEBUG = DynamicLibraryBundle.DEBUG;
+
+ /** @return a list of Tool library names or alternative library name lists.<br>
+ * <ul>
+ * <li>GL/GLU example Unix: [ [ "libGL.so.1", "libGL.so", "GL" ], [ "libGLU.so", "GLU" ] ] </li>
+ * <li>GL/GLU example Windows: [ "OpenGL32", "GLU32" ] </li>
+ * <li>Cg/CgGL example: [ [ "libCg.so", "Cg" ], [ "libCgGL.so", "CgGL" ] ] </li>
+ * </pre>
+ */
+ public List getToolLibNames();
+
+ /** @return a list of Glue library names.<br>
+ * <ul>
+ * <li>GL: [ "nativewindow_x11", "jogl_gl2es12", "jogl_desktop" ] </li>
+ * <li>NEWT: [ "nativewindow_x11", "newt" ] </li>
+ * <li>Cg: [ "nativewindow_x11", "jogl_cg" ] </li>
+ * </ul><br>
+ * Only the last entry is crucial, ie all other are optional preload dependencies and may generate errors,
+ * which are ignored.
+ */
+ public List/*<String>*/ getGlueLibNames();
+
+ /** May return the native libraries <pre>GetProcAddressFunc</pre> names, the first found function is being used.<br>
+ * This could be eg: <pre> glXGetProcAddressARB, glXGetProcAddressARB </pre>.<br>
+ * If your Tool does not has this facility, just return null.
+ */
+ public List getToolGetProcAddressFuncNameList() ;
+
+ /** May implement the lookup function using the Tools facility.<br>
+ * The actual function pointer is provided to allow proper bootstrapping of the ProcAddressTable.<br>
+ */
+ public long toolDynamicLookupFunction(long toolGetProcAddressHandle, String funcName);
+
+ /** @return true if the native library symbols shall be made available for symbol resolution of subsequently loaded libraries. */
+ public boolean shallLinkGlobal();
+
+ /** @return true if the dynamic symbol lookup shall happen system wide, over all loaded libraries. Otherwise only the loaded native libraries are used for lookup, which shall be the default. */
+ public boolean shallLookupGlobal();
+
+}
+
+
diff --git a/src/java/com/jogamp/common/os/NativeLibrary.java b/src/java/com/jogamp/common/os/NativeLibrary.java
index 897e240..97aabae 100755
--- a/src/java/com/jogamp/common/os/NativeLibrary.java
+++ b/src/java/com/jogamp/common/os/NativeLibrary.java
@@ -62,7 +62,8 @@ public class NativeLibrary implements DynamicLookupHelper {
private static final int WINDOWS = 1;
private static final int UNIX = 2;
private static final int MACOSX = 3;
- private static boolean DEBUG;
+ protected static boolean DEBUG;
+ protected static boolean DEBUG_LOOKUP;
private static int platform;
private static DynamicLinker dynLink;
private static String[] prefixes;
@@ -81,7 +82,8 @@ public class NativeLibrary implements DynamicLookupHelper {
platform = UNIX;
}
- DEBUG = (System.getProperty("gluegen.debug.NativeLibrary") != null);
+ DEBUG = (System.getProperty("jogamp.debug.NativeLibrary") != null);
+ DEBUG_LOOKUP = (System.getProperty("jogamp.debug.NativeLibrary.Lookup") != null);
return null;
}
diff --git a/src/java/com/jogamp/common/os/WindowsDynamicLinkerImpl.java b/src/java/com/jogamp/common/os/WindowsDynamicLinkerImpl.java
index 935f386..7bbfe23 100755
--- a/src/java/com/jogamp/common/os/WindowsDynamicLinkerImpl.java
+++ b/src/java/com/jogamp/common/os/WindowsDynamicLinkerImpl.java
@@ -11,7 +11,7 @@ public class WindowsDynamicLinkerImpl implements DynamicLinker {
static {
AccessController.doPrivileged(new PrivilegedAction() {
public Object run() {
- DEBUG = (System.getProperty("gluegen.debug.NativeLibrary") != null);
+ DEBUG = (System.getProperty("jogamp.debug.NativeLibrary") != null);
return null;
}
});