Loader.java

package com.surrealdb;

import java.io.*;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Comparator;
import java.util.Locale;
import java.util.stream.Stream;

class Loader {

    static String SURREALDB = "surrealdb";
    static String SURREALDB_LIBNAME = System.mapLibraryName(SURREALDB);

    static void loadNative() throws RuntimeException {
        try {
            System.loadLibrary(SURREALDB);
        } catch (final UnsatisfiedLinkError e) {
            try {
                System.load(extract(getPath()).getAbsolutePath());
            } catch (Exception e2) {
                throw new RuntimeException("Couldn't load " + SURREALDB, e2);
            }
        }
    }

    private static String getPath() {
        final String vendor = System.getProperty("java.vendor").toLowerCase(Locale.ENGLISH);
        final String arch = System.getProperty("os.arch").toLowerCase(Locale.ENGLISH);
        final String name = System.getProperty("os.name").toLowerCase(Locale.ENGLISH);
        final boolean android = vendor.contains("android");
        final boolean linux = !android && name.contains("linux");
        final boolean windows = !linux && name.contains("win");
        final boolean osx = !windows && name.contains("mac");
        final boolean intel64 = arch.contains("x86_64") || arch.contains("amd64");
        final boolean intel32 = !intel64 && arch.contains("i386") || arch.contains("i686") || arch.contains("x86");
        final boolean arm64 = arch.contains("aarch64") || arch.contains("arm64");
        final boolean arm32 = !arm64 && (arch.contains("armv7") || arch.contains("arm"));
        if (android) {
            if (arm64)
                return "android_arm64";
            if (intel64)
                return "android_64";
            if (arm32)
                return "android_arm32";
            if (intel32)
                return "android_32";
        } else if (linux) {
            if (arm64)
                return "linux_arm64";
            if (intel64)
                return "linux_64";
            if (arm32)
                return "linux_arm32";
            if (intel32)
                return "linux_32";
        } else if (windows) {
            if (intel64)
                return "windows_64";
            if (intel32)
                return "windows_32";
        } else if (osx) {
            if (arm64)
                return "osx_arm64";
            else if (intel64)
                return "osx_64";
        }
        throw new RuntimeException("Unsupported architecture: " + arch + " - name: " + name);
    }

    private static void copy(InputStream input, OutputStream output) throws IOException {
        final byte[] buffer = new byte[8192];
        int bytesRead;
        while ((bytesRead = input.read(buffer)) != -1) {
            output.write(buffer, 0, bytesRead);
        }
    }

    private static File extract(String path) throws IOException {
        final String TargetsPath = "natives/" + path + "/" + SURREALDB_LIBNAME;
        final URL Targets = Surreal.class.getClassLoader().getResource(TargetsPath);
        if (Targets == null) {
            throw new RuntimeException("Couldn't find Targets: " + TargetsPath);
        }
        final Path tempDir = Files.createTempDirectory("surrealdb");

        // Add a hook to delete the temporary files on shutdown
        Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            try {
                deleteDirectory(tempDir);
            } catch (IOException e) {
                // Safe to ignore
            }
        }));

        final URLConnection connection = Targets.openConnection();
        connection.setUseCaches(false);
        try (InputStream in = new BufferedInputStream(connection.getInputStream())) {
            final File outfile = new File(tempDir.toFile(), SURREALDB_LIBNAME);
            try (FileOutputStream out = new FileOutputStream(outfile)) {
                copy(in, out);
            }
            return outfile;
        }
    }

    private static void deleteDirectory(Path path) throws IOException {
        if (Files.isDirectory(path)) {
            try (Stream<Path> walker = Files.walk(path)) {
                walker.sorted(Comparator.reverseOrder())
                    .forEach(p -> {
                        try {
                            Files.delete(p);
                        } catch (IOException e) {
                            // Safe to ignore
                        }
                    });
            }
        }
    }

}