diff --git a/java/craftlabs-auth-core/pom.xml b/java/craftlabs-auth-core/pom.xml index 37b0cd2..492ebed 100644 --- a/java/craftlabs-auth-core/pom.xml +++ b/java/craftlabs-auth-core/pom.xml @@ -19,6 +19,10 @@ com.fasterxml.jackson.core jackson-databind + + net.java.dev.jna + jna + org.junit.jupiter junit-jupiter diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/CraftCoreLibrary.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/CraftCoreLibrary.java new file mode 100644 index 0000000..3abc769 --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/CraftCoreLibrary.java @@ -0,0 +1,53 @@ +package cn.craftlabs.auth.internal; + +import com.sun.jna.Library; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import com.sun.jna.Structure; +import java.util.Arrays; +import java.util.List; + +public interface CraftCoreLibrary extends Library { + CraftCoreLibrary INSTANCE = Native.load("craftlabs_auth_core", CraftCoreLibrary.class); + + class CraftResult extends Structure { + public int success; + public String message; + + @Override + protected List getFieldOrder() { + return Arrays.asList("success", "message"); + } + } + + class LicenseInfoStruct extends Structure { + public int isLicensed; + public long expirationDate; + public Pointer featureNames; + public Pointer featureValues; + public int featureCount; + + @Override + protected List getFieldOrder() { + return Arrays.asList("isLicensed", "expirationDate", "featureNames", "featureValues", "featureCount"); + } + } + + Pointer craft_initialize(String configJson); + + void craft_destroy(Pointer handle); + + CraftResult craft_activate(Pointer handle, String licenseKey); + + CraftResult craft_check_license(Pointer handle); + + LicenseInfoStruct craft_get_license_info(Pointer handle); + + void craft_free_license_info(LicenseInfoStruct info); + + int craft_has_feature(Pointer handle, String featureName); + + CraftResult craft_release(Pointer handle); + + CraftResult craft_heartbeat(Pointer handle); +} diff --git a/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/JnaAuthProvider.java b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/JnaAuthProvider.java new file mode 100644 index 0000000..dade941 --- /dev/null +++ b/java/craftlabs-auth-core/src/main/java/cn/craftlabs/auth/internal/JnaAuthProvider.java @@ -0,0 +1,89 @@ +package cn.craftlabs.auth.internal; + +import cn.craftlabs.auth.AuthProvider; +import cn.craftlabs.auth.AuthResult; +import cn.craftlabs.auth.LicenseInfo; +import com.sun.jna.Native; +import com.sun.jna.Pointer; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +public class JnaAuthProvider implements AuthProvider { + private Pointer nativeHandle; + + @Override + public AuthResult initialize(String configJson) { + if (nativeHandle != null) { + CraftCoreLibrary.INSTANCE.craft_destroy(nativeHandle); + } + nativeHandle = CraftCoreLibrary.INSTANCE.craft_initialize( + configJson != null ? configJson : "{}"); + return new AuthResult(nativeHandle != null, "Initialized"); + } + + @Override + public AuthResult activate(String licenseKey) { + CraftCoreLibrary.CraftResult r = CraftCoreLibrary.INSTANCE.craft_activate( + nativeHandle, licenseKey); + return new AuthResult(r.success != 0, r.message); + } + + @Override + public AuthResult checkLicense() { + CraftCoreLibrary.CraftResult r = CraftCoreLibrary.INSTANCE.craft_check_license(nativeHandle); + return new AuthResult(r.success != 0, r.message); + } + + @Override + public LicenseInfo getLicenseInfo() { + CraftCoreLibrary.LicenseInfoStruct s = CraftCoreLibrary.INSTANCE.craft_get_license_info(nativeHandle); + if (s == null) { + return new LicenseInfo(false, null, null); + } + + Map features = null; + if (s.featureCount > 0 && s.featureNames != null) { + features = new HashMap<>(s.featureCount); + for (int i = 0; i < s.featureCount; i++) { + Pointer namePtr = s.featureNames.getPointer((long) i * Native.POINTER_SIZE); + String name = namePtr != null ? namePtr.getString(0) : null; + if (name != null) { + int val = s.featureValues != null + ? s.featureValues.getInt((long) i * Integer.BYTES) + : 0; + features.put(name, val != 0); + } + } + } + + Date expirationDate = s.expirationDate > 0 ? new Date(s.expirationDate) : null; + CraftCoreLibrary.INSTANCE.craft_free_license_info(s); + return new LicenseInfo(s.isLicensed != 0, expirationDate, features); + } + + @Override + public boolean hasFeature(String featureName) { + return CraftCoreLibrary.INSTANCE.craft_has_feature(nativeHandle, featureName) != 0; + } + + @Override + public AuthResult release() { + CraftCoreLibrary.CraftResult r = CraftCoreLibrary.INSTANCE.craft_release(nativeHandle); + return new AuthResult(r.success != 0, r.message); + } + + @Override + public AuthResult heartbeat() { + CraftCoreLibrary.CraftResult r = CraftCoreLibrary.INSTANCE.craft_heartbeat(nativeHandle); + return new AuthResult(r.success != 0, r.message); + } + + @Override + public void close() { + if (nativeHandle != null) { + CraftCoreLibrary.INSTANCE.craft_destroy(nativeHandle); + nativeHandle = null; + } + } +} diff --git a/java/pom.xml b/java/pom.xml index ddd2932..1e04e5b 100644 --- a/java/pom.xml +++ b/java/pom.xml @@ -51,6 +51,11 @@ ${json-schema-validator.version} test + + net.java.dev.jna + jna + 5.14.0 +