diff --git a/bindings/java/src/blocking_operator.rs b/bindings/java/src/blocking_operator.rs index 55a645a4763b..c7fb4a076e8d 100644 --- a/bindings/java/src/blocking_operator.rs +++ b/bindings/java/src/blocking_operator.rs @@ -24,6 +24,7 @@ use jni::JNIEnv; use opendal::BlockingOperator; +use crate::jstring_to_string; use crate::Result; /// # Safety @@ -55,8 +56,8 @@ pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_read( } fn intern_read(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { - let path = env.get_string(&path)?; - let content = op.read(path.to_str()?)?; + let path = jstring_to_string(env, &path)?; + let content = op.read(&path)?; let result = env.byte_array_from_slice(content.as_slice())?; Ok(result.into_raw()) } @@ -83,9 +84,9 @@ fn intern_write( path: JString, content: JByteArray, ) -> Result<()> { - let path = env.get_string(&path)?; + let path = jstring_to_string(env, &path)?; let content = env.convert_byte_array(content)?; - Ok(op.write(path.to_str()?, content)?) + Ok(op.write(&path, content)?) } /// # Safety @@ -105,8 +106,8 @@ pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_stat( } fn intern_stat(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result { - let path = env.get_string(&path)?; - let metadata = op.stat(path.to_str()?)?; + let path = jstring_to_string(env, &path)?; + let metadata = op.stat(&path)?; Ok(Box::into_raw(Box::new(metadata)) as jlong) } @@ -126,8 +127,8 @@ pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_delete( } fn intern_delete(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { - let path = env.get_string(&path)?; - Ok(op.delete(path.to_str()?)?) + let path = jstring_to_string(env, &path)?; + Ok(op.delete(&path)?) } /// # Safety @@ -146,6 +147,6 @@ pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_createDir } fn intern_create_dir(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> Result<()> { - let path = env.get_string(&path)?; - Ok(op.create_dir(path.to_str()?)?) + let path = jstring_to_string(env, &path)?; + Ok(op.create_dir(&path)?) } diff --git a/bindings/java/src/lib.rs b/bindings/java/src/lib.rs index e293f1b05505..d46f6d715076 100644 --- a/bindings/java/src/lib.rs +++ b/bindings/java/src/lib.rs @@ -221,3 +221,12 @@ fn make_capability<'a>(env: &mut JNIEnv<'a>, cap: Capability) -> Result Result { + let res = unsafe { env.get_string_unchecked(s)? }; + Ok(res.into()) +} diff --git a/bindings/java/src/operator.rs b/bindings/java/src/operator.rs index 8f0c1549ec33..3244ac0adf33 100644 --- a/bindings/java/src/operator.rs +++ b/bindings/java/src/operator.rs @@ -34,6 +34,7 @@ use opendal::Scheme; use crate::get_current_env; use crate::get_global_runtime; use crate::jmap_to_hashmap; +use crate::jstring_to_string; use crate::make_operator_info; use crate::make_presigned_request; use crate::Result; @@ -52,7 +53,7 @@ pub extern "system" fn Java_org_apache_opendal_Operator_constructor( } fn intern_constructor(env: &mut JNIEnv, scheme: JString, map: JObject) -> Result { - let scheme = Scheme::from_str(env.get_string(&scheme)?.to_str()?)?; + let scheme = Scheme::from_str(jstring_to_string(env, &scheme)?.as_str())?; let map = jmap_to_hashmap(env, &map)?; let mut op = Operator::via_map(scheme, map)?; if !op.info().full_capability().blocking { @@ -100,7 +101,7 @@ fn intern_write( let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; let content = env.convert_byte_array(content)?; unsafe { get_global_runtime() }.spawn(async move { @@ -141,7 +142,7 @@ fn intern_append( let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; let content = env.convert_byte_array(content)?; unsafe { get_global_runtime() }.spawn(async move { @@ -176,7 +177,7 @@ fn intern_stat(env: &mut JNIEnv, op: *mut Operator, path: JString) -> Result Result Result Resu let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; unsafe { get_global_runtime() }.spawn(async move { let result = do_create_dir(op, path).await; @@ -356,7 +357,7 @@ fn intern_presign_read( let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; let expire = Duration::from_nanos(expire as u64); unsafe { get_global_runtime() }.spawn(async move { @@ -403,7 +404,7 @@ fn intern_presign_write( let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; let expire = Duration::from_nanos(expire as u64); unsafe { get_global_runtime() }.spawn(async move { @@ -450,7 +451,7 @@ fn intern_presign_stat( let op = unsafe { &mut *op }; let id = request_id(env)?; - let path = env.get_string(&path)?.to_str()?.to_string(); + let path = jstring_to_string(env, &path)?; let expire = Duration::from_nanos(expire as u64); unsafe { get_global_runtime() }.spawn(async move { diff --git a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java index 9df34a604bfb..df594fddb7d7 100644 --- a/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/test/behavior/AbstractBehaviorTest.java @@ -134,6 +134,21 @@ public void testStatFile() { } operator.delete(path).join(); } + + /** + * Write file with non ascii name should succeed. + */ + @Test + public void testWriteFileWithNonAsciiName() { + final String path = "βŒπŸ˜±δΈ­ζ–‡.test"; + final byte[] content = generateBytes(); + operator.write(path, content).join(); + try (final Metadata meta = operator.stat(path).join()) { + assertThat(meta.isFile()).isTrue(); + assertThat(meta.getContentLength()).isEqualTo(content.length); + } + operator.delete(path).join(); + } } @TestInstance(TestInstance.Lifecycle.PER_CLASS)