alef-backend-java 0.16.21

Java (Panama FFM) backend for alef
Documentation
final class {{ class_name }} {
    private static final Linker LINKER = Linker.nativeLinker();
    private static SymbolLookup LIB;
    private static final String NATIVES_RESOURCE_ROOT = "/natives";
    private static final Object NATIVE_EXTRACT_LOCK = new Object();
    private static String cachedExtractKey;
    private static Path cachedExtractDir;
    private static String loadedLibraryName;

    static {
        loadNativeLibrary();
        try {
            Arena arena = Arena.ofShared();
            // Try the loaded library name first (for System.load() path case)
            try {
                LIB = SymbolLookup.libraryLookup(loadedLibraryName, arena);
            } catch (Throwable inner1) {
                // Try with 'lib' prefix if not already present (for System.loadLibrary() case)
                String nameWithLib = loadedLibraryName.startsWith("lib") ? loadedLibraryName : "lib" + loadedLibraryName;
                try {
                    LIB = SymbolLookup.libraryLookup(nameWithLib, arena);
                } catch (Throwable inner2) {
                    // Last fallback: use LINKER.defaultLookup()
                    LIB = LINKER.defaultLookup();
                }
            }
        } catch (Throwable e) {
            throw new ExceptionInInitializerError("Failed to initialize library symbols: " + e.getMessage());
        }
    }

    private static void loadNativeLibrary() {
        String osName = System.getProperty("os.name", "").toLowerCase(java.util.Locale.ROOT);
        String osArch = System.getProperty("os.arch", "").toLowerCase(java.util.Locale.ROOT);

        String libName;
        String libExt;
        if (osName.contains("mac") || osName.contains("darwin")) {
            libName = "lib{{ lib_name }}";
            libExt = ".dylib";
        } else if (osName.contains("win")) {
            libName = "{{ lib_name }}";
            libExt = ".dll";
        } else {
            libName = "lib{{ lib_name }}";
            libExt = ".so";
        }

        String nativesRid = resolveNativesRid(osName, osArch);
        String nativesDir = NATIVES_RESOURCE_ROOT + "/" + nativesRid;

        Path extracted = tryExtractAndLoadFromResources(nativesDir, libName, libExt);
        if (extracted != null) {
            return;
        }

        try {
            System.loadLibrary("{{ lib_name }}");
            // Find the full path by searching java.library.path
            loadedLibraryName = findLoadedLibraryPath("{{ lib_name }}", libName, libExt);
        } catch (UnsatisfiedLinkError e) {
            String msg = "Failed to load {{ lib_name }} native library. Expected resource: " + nativesDir + "/" + libName
                    + libExt + " (RID: " + nativesRid + "). "
                    + "Ensure the library is bundled in the JAR under natives/{os-arch}/, "
                    + "or place it on the system library path (java.library.path).";
            UnsatisfiedLinkError out = new UnsatisfiedLinkError(msg + " Original error: " + e.getMessage());
            out.initCause(e);
            throw out;
        }
    }

    private static Path tryExtractAndLoadFromResources(String nativesDir, String libName, String libExt) {
        String resourcePath = nativesDir + "/" + libName + libExt;
        URL resource = NativeLib.class.getResource(resourcePath);
        if (resource == null) {
            return null;
        }

        try {
            Path tempDir = extractOrReuseNativeDirectory(nativesDir);
            Path libPath = tempDir.resolve(libName + libExt);
            if (!Files.exists(libPath)) {
                throw new UnsatisfiedLinkError("Missing extracted native library: " + libPath);
            }
            System.load(libPath.toAbsolutePath().toString());
            loadedLibraryName = libPath.toAbsolutePath().toString();
            return libPath;
        } catch (Exception e) {
            System.err.println("[NativeLib] Failed to extract and load native library from resources: " + e.getMessage());
            return null;
        }
    }

    private static Path extractOrReuseNativeDirectory(String nativesDir) throws Exception {
        URL location = NativeLib.class.getProtectionDomain().getCodeSource().getLocation();
        if (location == null) {
            throw new IllegalStateException("Missing code source location for {{ lib_name }} JAR");
        }

        Path codePath = Path.of(location.toURI());
        String key = codePath.toAbsolutePath() + "::" + nativesDir;

        synchronized (NATIVE_EXTRACT_LOCK) {
            if (cachedExtractDir != null && key.equals(cachedExtractKey)) {
                return cachedExtractDir;
            }
            Path tempDir = Files.createTempDirectory("{{ lib_name }}_native");
            tempDir.toFile().deleteOnExit();
            List<Path> extracted = extractNativeDirectory(codePath, nativesDir, tempDir);
            if (extracted.isEmpty()) {
                throw new IllegalStateException("No native files extracted from resources dir: " + nativesDir);
            }
            cachedExtractKey = key;
            cachedExtractDir = tempDir;
            return tempDir;
        }
    }

    private static List<Path> extractNativeDirectory(Path codePath, String nativesDir, Path destDir) throws Exception {
        if (!Files.exists(destDir) || !Files.isDirectory(destDir)) {
            throw new IllegalArgumentException("Destination directory does not exist: " + destDir);
        }

        String prefix = nativesDir.startsWith("/") ? nativesDir.substring(1) : nativesDir;
        if (!prefix.endsWith("/")) {
            prefix = prefix + "/";
        }

        if (Files.isDirectory(codePath)) {
            Path nativesPath = codePath.resolve(prefix);
            if (!Files.exists(nativesPath) || !Files.isDirectory(nativesPath)) {
                return List.of();
            }
            return copyDirectory(nativesPath, destDir);
        }

        List<Path> extracted = new ArrayList<>();
        try (JarFile jar = new JarFile(codePath.toFile())) {
            Enumeration<JarEntry> entries = jar.entries();
            while (entries.hasMoreElements()) {
                JarEntry entry = entries.nextElement();
                String name = entry.getName();
                if (!name.startsWith(prefix) || entry.isDirectory()) {
                    continue;
                }
                String relative = name.substring(prefix.length());
                Path out = safeResolve(destDir, relative);
                Files.createDirectories(out.getParent());
                try (var in = jar.getInputStream(entry)) {
                    Files.copy(in, out, StandardCopyOption.REPLACE_EXISTING);
                }
                out.toFile().deleteOnExit();
                extracted.add(out);
            }
        }
        return extracted;
    }

    private static List<Path> copyDirectory(Path srcDir, Path destDir) throws Exception {
        List<Path> copied = new ArrayList<>();
        try (var paths = Files.walk(srcDir)) {
            for (Path src : (Iterable<Path>) paths::iterator) {
                if (Files.isDirectory(src)) {
                    continue;
                }
                Path relative = srcDir.relativize(src);
                Path out = safeResolve(destDir, relative.toString());
                Files.createDirectories(out.getParent());
                Files.copy(src, out, StandardCopyOption.REPLACE_EXISTING);
                out.toFile().deleteOnExit();
                copied.add(out);
            }
        }
        return copied;
    }

    private static Path safeResolve(Path destDir, String relative) throws Exception {
        Path normalizedDest = destDir.toAbsolutePath().normalize();
        Path out = normalizedDest.resolve(relative).normalize();
        if (!out.startsWith(normalizedDest)) {
            throw new SecurityException("Blocked extracting native file outside destination directory: " + relative);
        }
        return out;
    }

    private static String resolveNativesRid(String osName, String osArch) {
        String arch;
        if (osArch.contains("aarch64") || osArch.contains("arm64")) {
            arch = "arm64";
        } else if (osArch.contains("x86_64") || osArch.contains("amd64")) {
            arch = "x86_64";
        } else {
            arch = osArch.replaceAll("[^a-z0-9_]+", "");
        }

        String os;
        if (osName.contains("mac") || osName.contains("darwin")) {
            os = "macos";
        } else if (osName.contains("win")) {
            os = "windows";
        } else {
            os = "linux";
        }

        return os + "-" + arch;
    }

    private static String findLoadedLibraryPath(String libName, String fullLibName, String libExt) {
        // Search java.library.path for the library file
        String javaLibPath = System.getProperty("java.library.path");
        if (javaLibPath != null) {
            for (String path : javaLibPath.split(File.pathSeparator)) {
                Path libPath = Paths.get(path, fullLibName + libExt);
                if (java.nio.file.Files.exists(libPath)) {
                    try {
                        return libPath.toRealPath().toString();
                    } catch (java.io.IOException e) {
                        return libPath.toAbsolutePath().toString();
                    }
                }
            }
        }
        // Fallback: try just the library name (may work on some systems)
        return libName;
    }

{% for function_handle in function_handles %}
{{ function_handle }}
{% endfor %}

    static final MethodHandle {{ prefix_upper }}_LAST_ERROR_CODE = LINKER.downcallHandle(
        LIB.find("{{ prefix }}_last_error_code").orElseThrow(),
        FunctionDescriptor.of(ValueLayout.JAVA_INT)
    );

    static final MethodHandle {{ prefix_upper }}_LAST_ERROR_CONTEXT = LINKER.downcallHandle(
        LIB.find("{{ prefix }}_last_error_context").orElseThrow(),
        FunctionDescriptor.of(ValueLayout.ADDRESS)
    );

{% for accessor_handle in accessor_handles %}
{{ accessor_handle }}
{% endfor %}

{% for builder_handle in builder_handles %}
{{ builder_handle }}
{% endfor %}

{% for trait_handle in trait_handles %}
{{ trait_handle }}
{% endfor %}

{% if visitor_handles %}
{{ visitor_handles }}
{% endif %}
}