Skip to content

Commit

Permalink
Revert to previous fix opening frameworks with full path. Adjust test…
Browse files Browse the repository at this point in the history
… coverage.

> Check for library presence by attempting to dlopen() the path, which will correctly check for the library in the cache.

Signed-off-by: David Kocher <[email protected]>
  • Loading branch information
dkocher committed Jul 2, 2020
1 parent 65085c1 commit e6c6b37
Show file tree
Hide file tree
Showing 2 changed files with 95 additions and 46 deletions.
58 changes: 26 additions & 32 deletions src/com/sun/jna/NativeLibrary.java
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ private static int openFlags(Map<String, ?> options) {
return DEFAULT_OPEN_OPTIONS;
}

private static NativeLibrary loadLibrary(String libraryName, Map<String, ?> options) {
private static NativeLibrary loadLibrary(final String libraryName, final Map<String, ?> options) {
LOG.log(DEBUG_LOAD_LEVEL, "Looking for library '" + libraryName + "'");

List<Throwable> exceptions = new ArrayList<Throwable>();
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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<String> paths = new LinkedHashSet<String>();
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) {
Expand Down
83 changes: 69 additions & 14 deletions test/com/sun/jna/NativeLibraryTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down

0 comments on commit e6c6b37

Please sign in to comment.