diff --git a/src/com/sun/jna/NativeLibrary.java b/src/com/sun/jna/NativeLibrary.java index 493155a593..d79cff619b 100644 --- a/src/com/sun/jna/NativeLibrary.java +++ b/src/com/sun/jna/NativeLibrary.java @@ -150,7 +150,7 @@ private static int openFlags(Map options) { return DEFAULT_OPEN_OPTIONS; } - private static NativeLibrary loadLibrary(String libraryName, Map options) { + private static NativeLibrary loadLibrary(final String libraryName, final Map options) { LOG.log(DEBUG_LOAD_LEVEL, "Looking for library '" + libraryName + "'"); List exceptions = new ArrayList(); @@ -242,30 +242,17 @@ else if (Platform.isLinux() || Platform.isFreeBSD()) { } // Search framework libraries on OS X else if (Platform.isMac() && !libraryName.endsWith(".dylib")) { - if (System.getProperty("os.version").compareTo("10.16") >= 0) { + for(String frameworkName : matchFramework(libraryName)) { try { - LOG.log(DEBUG_LOAD_LEVEL, "Trying " + libraryName); - handle = Native.open(libraryName, openFlags); + LOG.log(DEBUG_LOAD_LEVEL, "Trying " + frameworkName); + handle = Native.open(frameworkName, openFlags); + break; } catch(UnsatisfiedLinkError e2) { LOG.log(DEBUG_LOAD_LEVEL, "Loading failed with message: " + e2.getMessage()); exceptions.add(e2); } } - else { - LOG.log(DEBUG_LOAD_LEVEL, "Looking for matching frameworks"); - libraryPath = matchFramework(libraryName); - if (libraryPath != null) { - try { - LOG.log(DEBUG_LOAD_LEVEL, "Trying " + libraryPath); - handle = Native.open(libraryPath, openFlags); - } - catch(UnsatisfiedLinkError e2) { - LOG.log(DEBUG_LOAD_LEVEL, "Loading failed with message: " + e2.getMessage()); - exceptions.add(e2); - } - } - } } // Try the same library with a "lib" prefix else if (Platform.isWindows() && !isAbsolutePath) { @@ -351,30 +338,37 @@ private static void addSuppressedReflected(Throwable target, Throwable suppresse } /** Look for a matching framework (OSX) */ - static String matchFramework(String libraryName) { + static String[] matchFramework(String libraryName) { + Set paths = new LinkedHashSet(); File framework = new File(libraryName); if (framework.isAbsolute()) { - if (libraryName.indexOf(".framework") != -1 - && framework.exists()) { - return framework.getAbsolutePath(); + if (libraryName.contains(".framework")) { + if (framework.exists()) { + return new String[]{framework.getAbsolutePath()}; + } + paths.add(framework.getAbsolutePath()); } - framework = new File(new File(framework.getParentFile(), framework.getName() + ".framework"), framework.getName()); - if (framework.exists()) { - return framework.getAbsolutePath(); + else { + framework = new File(new File(framework.getParentFile(), framework.getName() + ".framework"), framework.getName()); + if (framework.exists()) { + return new String[]{framework.getAbsolutePath()}; + } + paths.add(framework.getAbsolutePath()); } } else { final String[] PREFIXES = { System.getProperty("user.home"), "", "/System" }; - String suffix = libraryName.indexOf(".framework") == -1 - ? libraryName + ".framework/" + libraryName : libraryName; - for (int i=0;i < PREFIXES.length;i++) { - String libraryPath = PREFIXES[i] + "/Library/Frameworks/" + suffix; - if (new File(libraryPath).exists()) { - return libraryPath; + String suffix = !libraryName.contains(".framework") + ? libraryName + ".framework/" + libraryName : libraryName; + for (String prefix : PREFIXES) { + framework = new File(prefix + "/Library/Frameworks/" + suffix); + if (framework.exists()) { + return new String[]{framework.getAbsolutePath()}; } + paths.add(framework.getAbsolutePath()); } } - return null; + return paths.toArray(new String[0]); } private String getLibraryName(String libraryName) { diff --git a/test/com/sun/jna/NativeLibraryTest.java b/test/com/sun/jna/NativeLibraryTest.java index b103335208..57f89a26e2 100644 --- a/test/com/sun/jna/NativeLibraryTest.java +++ b/test/com/sun/jna/NativeLibraryTest.java @@ -247,26 +247,81 @@ public void testGetProcess() { process.getFunction("printf"); } - private String expected(String f) { - return new File(f).exists() ? f : null; + public void testLoadFoundationFramework() { + if (!Platform.isMac()) { + return; + } + assertNotNull(NativeLibrary.getInstance("Foundation")); } - public void testMatchFramework() { + public void testMatchSystemFramework() { if (!Platform.isMac()) { return; } - final String[][] MAPPINGS = { - // Depending on the system, /Library/Frameworks may or may not - // have anything in it. - { "QtCore", expected("/Library/Frameworks/QtCore.framework/QtCore") }, - { "Adobe AIR", expected("/Library/Frameworks/Adobe AIR.framework/Adobe AIR") }, - - { "QuickTime", expected("/System/Library/Frameworks/QuickTime.framework/QuickTime") }, - { "QuickTime.framework/Versions/Current/QuickTime", expected("/System/Library/Frameworks/QuickTime.framework/Versions/Current/QuickTime") }, - }; - for (int i=0;i < MAPPINGS.length;i++) { - assertEquals("Wrong framework mapping", MAPPINGS[i][1], NativeLibrary.matchFramework(MAPPINGS[i][0])); + + assertEquals("Wrong framework mapping", 1, + NativeLibrary.matchFramework("/System/Library/Frameworks/Foundation.framework/Foundation").length); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/Foundation.framework/Foundation", + NativeLibrary.matchFramework("/System/Library/Frameworks/Foundation.framework/Foundation")[0]); + + assertEquals("Wrong framework mapping", 1, + NativeLibrary.matchFramework("/System/Library/Frameworks/Foundation").length); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/Foundation.framework/Foundation", + NativeLibrary.matchFramework("/System/Library/Frameworks/Foundation")[0]); + } + + public void testMatchOptionalFrameworkExists() { + if (!Platform.isMac()) { + return; + } + + if(!new File("/System/Library/Frameworks/QuickTime.framework").exists()) { + return; + } + + assertEquals("Wrong framework mapping", 1, + NativeLibrary.matchFramework("QuickTime").length); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/QuickTime.framework/QuickTime", + NativeLibrary.matchFramework("QuickTime")[0]); + + assertEquals("Wrong framework mapping", 1, + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime").length); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/QuickTime.framework/Versions/Current/QuickTime", + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime")[0]); + } + + public void testMatchOptionalFrameworkNotFound() { + if (!Platform.isMac()) { + return; } + + if(new File(System.getProperty("user.home") + "/Library/Frameworks/QuickTime.framework").exists()) { + return; + } + if(new File("/Library/Frameworks/QuickTime.framework").exists()) { + return; + } + if(new File("/System/Library/Frameworks/QuickTime.framework").exists()) { + return; + } + + assertEquals("Wrong framework mapping", 3, + NativeLibrary.matchFramework("QuickTime").length); + assertEquals("Wrong framework mapping", System.getProperty("user.home") + "/Library/Frameworks/QuickTime.framework/QuickTime", + NativeLibrary.matchFramework("QuickTime")[0]); + assertEquals("Wrong framework mapping", "/Library/Frameworks/QuickTime.framework/QuickTime", + NativeLibrary.matchFramework("QuickTime")[1]); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/QuickTime.framework/QuickTime", + NativeLibrary.matchFramework("QuickTime")[2]); + + assertEquals("Wrong framework mapping", 3, + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime").length); + assertEquals("Wrong framework mapping", System.getProperty("user.home") + "/Library/Frameworks/QuickTime.framework/Versions/Current/QuickTime", + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime")[0]); + assertEquals("Wrong framework mapping", "/Library/Frameworks/QuickTime.framework/Versions/Current/QuickTime", + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime")[1]); + assertEquals("Wrong framework mapping", "/System/Library/Frameworks/QuickTime.framework/Versions/Current/QuickTime", + NativeLibrary.matchFramework("QuickTime.framework/Versions/Current/QuickTime")[2]); } public void testLoadLibraryWithOptions() {