Skip to content

Commit a9633f2

Browse files
committed
Add overload method to load natives from JAR using a ClassLoader
As it will try to find the resource in the corresponding module and not the class's module only FFM needs it as it fetches natives from another module, this is necessary for users using modules
1 parent 6934f5a commit a9633f2

File tree

3 files changed

+53
-3
lines changed

3 files changed

+53
-3
lines changed

api/src/main/java/dev/freya02/discord/zstd/api/DiscordZstdNativesLoader.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,34 @@ public static synchronized boolean loadFromJar(String resourcePath, Class<?> cla
7777
load(nativePath);
7878
return true;
7979
}
80+
81+
/**
82+
* Loads the natives using the provided path from the provided class.
83+
*
84+
* <p>When, and only when using modules, the resource will be loaded from one of the modules loaded by the provided class loader.
85+
* <br>If the resource path does not represent a valid package name, it can be loaded from any module, if it forms a valid package name,
86+
* it is subject to encapsulation rules specified by {@link java.lang.Module#getResourceAsStream(String) Module.getResourceAsStream}.
87+
*
88+
* @param resourcePath
89+
* The path to the native library in the provided class
90+
* @param loader
91+
* The class loader from which to load the resource from
92+
*
93+
* @throws IllegalArgumentException
94+
* If {@code resourcePath} or {@code loader} is {@code null}
95+
* @throws IOException
96+
* If the resource does not exist or when extracting it fails
97+
*
98+
* @return {@code true} if the natives were loaded, {@code false} if they already were
99+
*/
100+
public static synchronized boolean loadFromJar(String resourcePath, ClassLoader loader) throws IOException {
101+
if (init)
102+
return false;
103+
Checks.notNull(resourcePath, "Resource path");
104+
Checks.notNull(loader, "Class loader");
105+
106+
Path nativePath = IOUtil.copyNativeFromJar(resourcePath, loader);
107+
load(nativePath);
108+
return true;
109+
}
80110
}

api/src/main/java/dev/freya02/discord/zstd/api/IOUtil.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,27 @@ static Path copyNativeFromJar(String resourcePath, Class<?> clazz) throws IOExce
1313
path.toFile().deleteOnExit();
1414

1515
try (InputStream stream = clazz.getResourceAsStream(resourcePath)) {
16+
if (stream == null) {
17+
if (resourcePath.startsWith("/")) {
18+
throw new FileNotFoundException("Natives not found at '" + resourcePath + "'");
19+
} else {
20+
throw new FileNotFoundException("Natives not found at '" + resourcePath + "' relative to '" + clazz.getPackage().getName() + "'");
21+
}
22+
}
23+
24+
Files.copy(stream, path, StandardCopyOption.REPLACE_EXISTING);
25+
}
26+
27+
return path;
28+
}
29+
30+
static Path copyNativeFromJar(String resourcePath, ClassLoader loader) throws IOException {
31+
final Path path = Files.createTempFile("libzstd", null);
32+
path.toFile().deleteOnExit();
33+
34+
try (InputStream stream = loader.getResourceAsStream(resourcePath)) {
1635
if (stream == null)
17-
throw new FileNotFoundException("Natives not found at '" + resourcePath + "' relative to '" + clazz.getPackage().getName() + "'");
36+
throw new FileNotFoundException("Natives not found at '" + resourcePath + "'");
1837

1938
Files.copy(stream, path, StandardCopyOption.REPLACE_EXISTING);
2039
}

ffm-impl/src/main/java/dev/freya02/discord/zstd/ffm/DiscordZstdFFM.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,9 @@ public DiscordZstdFFM() throws IOException {
1818
// Load natives if they weren't already
1919
if (!DiscordZstdNativesLoader.isLoaded()) {
2020
NativeUtil.System system = NativeUtil.getSystem();
21-
String absoluteNativeResource = String.format("/dev/freya02/discord/zstd/natives/%s/libzstd.%s", system.platform, system.sharedLibraryExtension);
22-
DiscordZstdNativesLoader.loadFromJar(absoluteNativeResource, DiscordZstd.class);
21+
String absoluteNativeResource = String.format("dev/freya02/discord/zstd/natives/%s/libzstd.%s", system.platform, system.sharedLibraryExtension);
22+
// Use ClassLoader as natives are in another module
23+
DiscordZstdNativesLoader.loadFromJar(absoluteNativeResource, DiscordZstd.class.getClassLoader());
2324
}
2425
}
2526

0 commit comments

Comments
 (0)