This is an automated email from the git hooks/post-receive script. tpot-guest pushed a commit to annotated tag upstream/1.0.10 in repository jffi-next.
commit 52968fa6b6910a81935ca5e9c1660ca4d2efeeff Author: Wayne Meissner <[email protected]> Date: Wed Apr 27 16:56:26 2011 +1000 Rework stub library loading, to always try and load the stub lib using the system classloader. --- src/com/kenai/jffi/Init.java | 222 ++++++------------- .../jffi/{Init.java => internal/StubLoader.java} | 238 +++++++++++++++++---- 2 files changed, 252 insertions(+), 208 deletions(-) diff --git a/src/com/kenai/jffi/Init.java b/src/com/kenai/jffi/Init.java index fab03b6..956c034 100644 --- a/src/com/kenai/jffi/Init.java +++ b/src/com/kenai/jffi/Init.java @@ -33,201 +33,99 @@ package com.kenai.jffi; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.util.Arrays; -import java.util.Properties; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; /** * Utility class to load the jffi stub library */ final class Init { - private static final String bootPropertyFilename = "boot.properties"; - private static final String bootLibraryPropertyName = "jffi.boot.library.path"; - private static final String stubLibraryName - = String.format("jffi-%d.%d", Foreign.VERSION_MAJOR, Foreign.VERSION_MINOR); - private static volatile boolean loaded = false; + static final String stubLoaderClassName = Init.class.getPackage().getName() + ".internal.StubLoader"; + // prevent instantiation private Init() {} /** * Loads the stub library */ - static final void load() { + static void load() { if (loaded) { return; } - - final String libName = getStubLibraryName(); - String bootPath = getBootPath(); - if (bootPath != null && loadFromBootPath(libName, bootPath)) { - return; - } + List<Throwable> failureCauses = new ArrayList<Throwable>(); + List<ClassLoader> loaders = getClassLoaders(); - try { - System.loadLibrary(libName); - return; - } catch (UnsatisfiedLinkError ex) {} - - loadFromJar(); - } - - private static final String getBootPath() { - - String bootPath = System.getProperty(bootLibraryPropertyName); - if (bootPath != null) { - return bootPath; - } - - InputStream is = getResourceAsStream(bootPropertyFilename); - if (is != null) { - Properties p = new Properties(); + for (ClassLoader cl : loaders) { try { - p.load(is); - return p.getProperty(bootLibraryPropertyName); - } catch (IOException ex) { - } finally { - try { - is.close(); - } catch (IOException ex) { - throw new RuntimeException(ex); + Class<?> c = Class.forName(stubLoaderClassName, true, cl); + Method isLoaded = c.getDeclaredMethod("isLoaded", new Class[0]); + loaded |= Boolean.class.cast(isLoaded.invoke(c, new Object[0])); + if (!loaded) { + Method getFailureCause = c.getDeclaredMethod("getFailureCause", new Class[0]); + throw new RuntimeException(Throwable.class.cast(getFailureCause.invoke(c, new Object[0]))); } + + } catch (IllegalAccessException ex) { + failureCauses.add(ex); + + } catch (InvocationTargetException ex) { + failureCauses.add(ex); + + } catch (ClassNotFoundException ex) { + failureCauses.add(ex); + + } catch (IllegalArgumentException ex) { + throw new RuntimeException(ex); + + } catch (NoSuchMethodException ex) { + throw new RuntimeException(ex); } } - return null; - } - - private static final boolean loadFromBootPath(String libName, String bootPath) { - String[] dirs = bootPath.split(File.pathSeparator); - for (int i = 0; i < dirs.length; ++i) { - String path = new File(new File(dirs[i]), System.mapLibraryName(libName)).getAbsolutePath(); - try { - System.load(path); - return true; - } catch (UnsatisfiedLinkError ex) { - } - if (Platform.getPlatform().getOS() == Platform.OS.DARWIN) { - String orig, ext; - if (path.endsWith("dylib")) { - orig = "dylib"; - ext = "jnilib"; - } else { - orig = "jnilib"; - ext = "dylib"; - } - try { - System.load(path.substring(0, path.lastIndexOf(orig)) + ext); - return true; - } catch (UnsatisfiedLinkError ex) { - } + if (!loaded && !failureCauses.isEmpty()) { + StringWriter sw = new StringWriter(); + PrintWriter pw = new PrintWriter(sw); + for (Throwable t : failureCauses) { + t.printStackTrace(pw); } + + throw new RuntimeException(sw.toString()); } - return false; } - private static final void loadFromJar() { - InputStream is = getStubLibraryStream(); - File dstFile = null; - FileOutputStream os = null; - + private static List<ClassLoader> getClassLoaders() { + List<ClassLoader> loaders = new ArrayList<ClassLoader>(); + ClassLoader cl = Init.class.getClassLoader(); + try { - dstFile = File.createTempFile("jffi", null); - dstFile.deleteOnExit(); - os = new FileOutputStream(dstFile); - ReadableByteChannel srcChannel = Channels.newChannel(is); - - for (long pos = 0; is.available() > 0; ) { - pos += os.getChannel().transferFrom(srcChannel, pos, Math.max(4096, is.available())); - } - - } catch (IOException ex) { - throw new UnsatisfiedLinkError(ex.getMessage()); - - } finally { - try { - if (os != null) { - os.close(); - } - is.close(); - } catch (IOException ex) { - throw new RuntimeException(ex); - } + loaders.add(ClassLoader.getSystemClassLoader()); + } catch (SecurityException ex) { } - System.load(dstFile.getAbsolutePath()); - } - - /** - * Gets an <tt>InputStream</tt> representing the stub library image stored in - * the jar file. - * - * @return A new <tt>InputStream</tt> - */ - private static final InputStream getStubLibraryStream() { - String stubPath = getStubLibraryPath(); - String[] paths = { stubPath, "/" + stubPath }; - - for (String path : paths) { - InputStream is = getResourceAsStream(path); - - // On MacOS, the stub might be named .dylib or .jnilib - cater for both - if (is == null && Platform.getPlatform().getOS() == Platform.OS.DARWIN) { - is = getResourceAsStream(path.replaceAll("dylib", "jnilib")); - } - if (is != null) { - return is; - } + try { + loaders.add(Thread.currentThread().getContextClassLoader()); + } catch (SecurityException ex) { } - - throw new UnsatisfiedLinkError("could not locate stub library" - + " in jar file. Tried " + Arrays.deepToString(paths)); - } - - private static final InputStream getResourceAsStream(String resourceName) { - // try both our classloader and context classloader - ClassLoader[] cls = new ClassLoader[] { - Init.class.getClassLoader(), - Thread.currentThread().getContextClassLoader() - }; - for (ClassLoader cl : cls) { - // skip null classloader (e.g. boot or null context loader) - if (cl == null) { - continue; - } - - InputStream is; - if ((is = cl.getResourceAsStream(resourceName)) != null) { - return is; + loaders.add(Init.class.getClassLoader()); + + // Remove all the nulls except one - in the case where this is loaded + // from the bootstrap classloader + int nullCount = 0; + for (Iterator<ClassLoader> it = loaders.iterator(); it.hasNext(); ) { + if (it.next() == null && ++nullCount > 1) { + it.remove(); } } - return null; - } - - /** - * Gets the name of the stub library. - * - * @return The name of the stub library as a <tt>String</tt> - */ - private static final String getStubLibraryName() { - return stubLibraryName; + return Collections.unmodifiableList(loaders); } - - /** - * Gets the path within the jar file of the stub native library. - * - * @return The path of the jar file. - */ - private static final String getStubLibraryPath() { - return "jni/" + Platform.getPlatform().getName() + "/"+ System.mapLibraryName(stubLibraryName); - } - } diff --git a/src/com/kenai/jffi/Init.java b/src/com/kenai/jffi/internal/StubLoader.java similarity index 53% copy from src/com/kenai/jffi/Init.java copy to src/com/kenai/jffi/internal/StubLoader.java index fab03b6..4b00fa9 100644 --- a/src/com/kenai/jffi/Init.java +++ b/src/com/kenai/jffi/internal/StubLoader.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2007, 2008 Wayne Meissner + * Copyright (C) 2011 Wayne Meissner * * This file is part of jffi. * @@ -14,24 +14,8 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. - * - * - * Alternatively, you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License - * for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with this work. If not, see <http://www.gnu.org/licenses/>. */ - - -package com.kenai.jffi; +package com.kenai.jffi.internal; import java.io.File; import java.io.FileOutputStream; @@ -43,27 +27,189 @@ import java.util.Arrays; import java.util.Properties; /** - * Utility class to load the jffi stub library + * Loads the native stub library. This is intended to only ever be called + * reflectively, so it cannot access other jffi classes. */ -final class Init { +public class StubLoader { + public final static int VERSION_MAJOR = getVersionField("MAJOR"); + public final static int VERSION_MINOR = getVersionField("MINOR"); + private static final String versionClassName = "com.kenai.jffi.Version"; + private static final String bootPropertyFilename = "boot.properties"; private static final String bootLibraryPropertyName = "jffi.boot.library.path"; private static final String stubLibraryName - = String.format("jffi-%d.%d", Foreign.VERSION_MAJOR, Foreign.VERSION_MINOR); + = String.format("jffi-%d.%d", VERSION_MAJOR, VERSION_MINOR); + private static final OS OS_ = determineOS(); + private static final CPU CPU_ = determineCPU(); + private static volatile Throwable failureCause = null; private static volatile boolean loaded = false; + + + public static final boolean isLoaded() { + return loaded; + } + + public static final Throwable getFailureCause() { + return failureCause; + } + + + public enum OS { + /** MacOSX */ + DARWIN, + /** FreeBSD */ + FREEBSD, + /** NetBSD */ + NETBSD, + /** OpenBSD */ + OPENBSD, + /** Linux */ + LINUX, + /** Solaris (and OpenSolaris) */ + SOLARIS, + /** The evil borg operating system */ + WINDOWS, + /** IBM AIX */ + AIX, + /** IBM zOS **/ + ZLINUX, + + /** No idea what the operating system is */ + UNKNOWN; + + @Override + public String toString() { return name().toLowerCase(); } + } + + /** + * The common names of cpu architectures. + * + * <b>Note</b> The names of the enum values are used in other parts of the + * code to determine where to find the native stub library. Do not rename. + */ + public enum CPU { + /** Intel ia32 */ + I386, + /** AMD 64 bit (aka EM64T/X64) */ + X86_64, + /** Power PC 32 bit */ + PPC, + /** Power PC 64 bit */ + PPC64, + /** Sun sparc 32 bit */ + SPARC, + /** Sun sparc 64 bit */ + SPARCV9, + /** IBM zSeries S/390 64 bit */ + S390X, + /** Unknown CPU */ + UNKNOWN; + + @Override + public String toString() { return name().toLowerCase(); } + } - // prevent instantiation - private Init() {} + /** + * Determines the operating system jffi is running on + * + * @return An member of the <tt>OS</tt> enum. + */ + private static final OS determineOS() { + String osName = System.getProperty("os.name").split(" ")[0].toLowerCase(); + if (osName.startsWith("mac") || osName.startsWith("darwin")) { + return OS.DARWIN; + } else if (osName.startsWith("linux")) { + return OS.LINUX; + } else if (osName.startsWith("sunos") || osName.startsWith("solaris")) { + return OS.SOLARIS; + } else if (osName.startsWith("aix")) { + return OS.AIX; + } else if (osName.startsWith("openbsd")) { + return OS.OPENBSD; + } else if (osName.startsWith("freebsd")) { + return OS.FREEBSD; + } else if (osName.startsWith("windows")) { + return OS.WINDOWS; + } else { + return OS.UNKNOWN; + } + } /** - * Loads the stub library + * Determines the CPU architecture the JVM is running on. + * + * This normalizes all the variations that are equivalent (e.g. i386, x86, i86pc) + * into a common cpu type. + * + * @return A member of the <tt>CPU</tt> enum. */ - static final void load() { - if (loaded) { - return; + private static final CPU determineCPU() { + String archString = System.getProperty("os.arch", "unknown").toLowerCase(); + if ("x86".equals(archString) || "i386".equals(archString) || "i86pc".equals(archString)) { + return CPU.I386; + } else if ("x86_64".equals(archString) || "amd64".equals(archString)) { + return CPU.X86_64; + } else if ("ppc".equals(archString) || "powerpc".equals(archString)) { + return CPU.PPC; + } else if ("powerpc64".equals(archString)) { + return CPU.PPC64; + } + + // Try to find by lookup up in the CPU list + try { + return CPU.valueOf(archString.toUpperCase()); + } catch (IllegalArgumentException ex) { + return CPU.UNKNOWN; } + } + + public static final CPU getCPU() { + return CPU_; + } + + public static OS getOS() { + return OS_; + } + /** + * Gets the name of the stub library. + * + * @return The name of the stub library as a <tt>String</tt> + */ + private static final String getStubLibraryName() { + return stubLibraryName; + } + + /** + * Gets the name of this <tt>Platform</tt>. + * + * @return The name of this platform. + */ + public static String getPlatformName() { + if (getOS().equals(OS.DARWIN)) { + return "Darwin"; + } + + + String osName = System.getProperty("os.name").split(" ")[0]; + return getCPU().name().toLowerCase() + "-" + osName; + } + /** + * Gets the path within the jar file of the stub native library. + * + * @return The path of the jar file. + */ + private static final String getStubLibraryPath() { + return "jni/" + getPlatformName() + "/"+ System.mapLibraryName(stubLibraryName); + } + + public StubLoader() {} + + /** + * Loads the stub library + */ + static final void load() { final String libName = getStubLibraryName(); String bootPath = getBootPath(); if (bootPath != null && loadFromBootPath(libName, bootPath)) { @@ -113,7 +259,7 @@ final class Init { return true; } catch (UnsatisfiedLinkError ex) { } - if (Platform.getPlatform().getOS() == Platform.OS.DARWIN) { + if (getOS() == OS.DARWIN) { String orig, ext; if (path.endsWith("dylib")) { orig = "dylib"; @@ -178,7 +324,7 @@ final class Init { InputStream is = getResourceAsStream(path); // On MacOS, the stub might be named .dylib or .jnilib - cater for both - if (is == null && Platform.getPlatform().getOS() == Platform.OS.DARWIN) { + if (is == null && getOS() == OS.DARWIN) { is = getResourceAsStream(path.replaceAll("dylib", "jnilib")); } if (is != null) { @@ -193,7 +339,8 @@ final class Init { private static final InputStream getResourceAsStream(String resourceName) { // try both our classloader and context classloader ClassLoader[] cls = new ClassLoader[] { - Init.class.getClassLoader(), + StubLoader.class.getClassLoader().getSystemClassLoader(), + StubLoader.class.getClassLoader(), Thread.currentThread().getContextClassLoader() }; @@ -211,23 +358,22 @@ final class Init { return null; } - - /** - * Gets the name of the stub library. - * - * @return The name of the stub library as a <tt>String</tt> - */ - private static final String getStubLibraryName() { - return stubLibraryName; + + private final static int getVersionField(String name) { + try { + Class c = Class.forName(versionClassName); + return (Integer) c.getField(name).get(c); + } catch (Throwable t) { + throw new RuntimeException(t); + } } - /** - * Gets the path within the jar file of the stub native library. - * - * @return The path of the jar file. - */ - private static final String getStubLibraryPath() { - return "jni/" + Platform.getPlatform().getName() + "/"+ System.mapLibraryName(stubLibraryName); + static { + try { + load(); + loaded = true; + } catch (Throwable t) { + failureCause = t; + } } - } -- Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-java/jffi-next.git _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

