diff --git a/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java b/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java index 52ae872..3fdac94 100644 --- a/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java +++ b/CedarJava/src/main/java/com/cedarpolicy/model/policy/Policy.java @@ -85,6 +85,11 @@ public String toJson() throws InternalException, NullPointerException { return toJsonJni(policySrc); } + public static Policy fromJson(String policyId, String policyJson) throws InternalException, NullPointerException { + var policyText = fromJsonJni(policyJson); + return new Policy(policyText, policyId); + } + public static Policy parseStaticPolicy(String policyStr) throws InternalException, NullPointerException { var policyText = parsePolicyJni(policyStr); return new Policy(policyText, null); @@ -100,4 +105,5 @@ private static native String parsePolicyTemplateJni(String policyTemplateStr) throws InternalException, NullPointerException; private native String toJsonJni(String policyStr) throws InternalException, NullPointerException; + private static native String fromJsonJni(String policyJsonStr) throws InternalException, NullPointerException; } diff --git a/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java b/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java index 9bda9e3..ab29395 100644 --- a/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java +++ b/CedarJava/src/test/java/com/cedarpolicy/PolicyTests.java @@ -91,4 +91,22 @@ public void policyTemplateToJsonFailureTests() throws InternalException { assertTrue(e.getMessage().contains("expected a static policy, got a template containing the slot ?resource")); } } + + @Test + public void policyFromJsonTest() throws InternalException { + assertThrows(NullPointerException.class, () -> { + String nullJson = null; + Policy.fromJson(null, nullJson); + }); + assertThrows(InternalException.class, () -> { + String invalidJson = "effect\":\"permit\",\"principal\":{\"op\":\"All\"},\"action\":{\"op\":\"All\"}"; + Policy.fromJson(null, invalidJson); + }); + + String validJson = "{\"effect\":\"permit\",\"principal\":{\"op\":\"All\"},\"action\":{\"op\":\"All\"}," + + "\"resource\":{\"op\":\"All\"},\"conditions\":[]}"; + Policy p = Policy.fromJson(null, validJson); + String actualJson = p.toJson(); + assertEquals(validJson, actualJson); + } } diff --git a/CedarJavaFFI/src/interface.rs b/CedarJavaFFI/src/interface.rs index 1347845..ab14b02 100644 --- a/CedarJavaFFI/src/interface.rs +++ b/CedarJavaFFI/src/interface.rs @@ -386,6 +386,31 @@ fn to_json_internal<'a>(env: &mut JNIEnv<'a>, policy_jstr: JString<'a>) -> Resul } } +#[jni_fn("com.cedarpolicy.model.policy.Policy")] +pub fn fromJsonJni<'a>(mut env: JNIEnv<'a>, _: JClass, policy_json_jstr: JString<'a>) -> jvalue { + match from_json_internal(&mut env, policy_json_jstr) { + Err(e) => jni_failed(&mut env, e.as_ref()), + Ok(policy_text) => policy_text.as_jni(), + } +} + +fn from_json_internal<'a>(env: &mut JNIEnv<'a>, policy_json_jstr: JString<'a>) -> Result> { + if policy_json_jstr.is_null() { + raise_npe(env) + } else { + let policy_json_jstring = env.get_string(&policy_json_jstr)?; + let policy_json_string = String::from(policy_json_jstring); + let policy_json_value: Value = serde_json::from_str(&policy_json_string)?; + match Policy::from_json(None, policy_json_value) { + Err(e) => Err(Box::new(e)), + Ok(p) => { + let policy_text = format!("{}", p); + Ok(JValueGen::Object(env.new_string(&policy_text)?.into())) + } + } + } +} + #[jni_fn("com.cedarpolicy.value.EntityIdentifier")] pub fn getEntityIdentifierRepr<'a>(mut env: JNIEnv<'a>, _: JClass, obj: JObject<'a>) -> jvalue { match get_entity_identifier_repr_internal(&mut env, obj) {