From 6cc34323e91763479203927f6fb4b18389709db2 Mon Sep 17 00:00:00 2001 From: G-XD Date: Thu, 21 Sep 2023 17:31:53 +0800 Subject: [PATCH 1/3] feat(binding/java): support info ops --- bindings/java/src/blocking_operator.rs | 25 ++ bindings/java/src/lib.rs | 98 ++++++- .../org/apache/opendal/BlockingOperator.java | 6 + .../java/org/apache/opendal/Capability.java | 270 ++++++++++++++++++ .../java/org/apache/opendal/Operator.java | 6 + .../java/org/apache/opendal/OperatorInfo.java | 45 +++ bindings/java/src/operator.rs | 23 ++ .../org/apache/opendal/OperatorInfoTest.java | 94 ++++++ 8 files changed, 563 insertions(+), 4 deletions(-) create mode 100644 bindings/java/src/main/java/org/apache/opendal/Capability.java create mode 100644 bindings/java/src/main/java/org/apache/opendal/OperatorInfo.java create mode 100644 bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java diff --git a/bindings/java/src/blocking_operator.rs b/bindings/java/src/blocking_operator.rs index d9e5b5ad2cba..980b899cdd41 100644 --- a/bindings/java/src/blocking_operator.rs +++ b/bindings/java/src/blocking_operator.rs @@ -31,6 +31,7 @@ use opendal::Scheme; use crate::get_global_runtime; use crate::jmap_to_hashmap; +use crate::make_operator_info; use crate::Result; #[no_mangle] @@ -160,3 +161,27 @@ fn intern_delete(env: &mut JNIEnv, op: &mut BlockingOperator, path: JString) -> let path = env.get_string(&path)?; Ok(op.delete(path.to_str()?)?) } + +/// # Safety +/// +/// This function should not be called before the Operator are ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_BlockingOperator_info<'local>( + mut env: JNIEnv<'local>, + _: JClass, + op: *mut BlockingOperator, +) -> JObject<'local> { + intern_info(&mut env, &mut *op).unwrap_or_else(|e| { + e.throw(&mut env); + JObject::null() + }) +} + +fn intern_info<'local>( + env: &mut JNIEnv<'local>, + op: &mut BlockingOperator, +) -> Result> { + let info = op.info(); + + make_operator_info(env, info) +} diff --git a/bindings/java/src/lib.rs b/bindings/java/src/lib.rs index 353855d4c5d4..9e90160d4981 100644 --- a/bindings/java/src/lib.rs +++ b/bindings/java/src/lib.rs @@ -19,21 +19,23 @@ use std::cell::RefCell; use std::collections::HashMap; use std::ffi::c_void; -use jni::objects::JMap; +use crate::error::Error; use jni::objects::JObject; use jni::objects::JString; -use jni::objects::JValue; +use jni::objects::{JMap, JValue}; +use jni::sys::jboolean; use jni::sys::jint; +use jni::sys::jlong; use jni::sys::JNI_VERSION_1_8; use jni::JNIEnv; use jni::JavaVM; use once_cell::sync::OnceCell; use opendal::raw::PresignedRequest; +use opendal::Capability; +use opendal::OperatorInfo; use tokio::runtime::Builder; use tokio::runtime::Runtime; -use crate::error::Error; - mod blocking_operator; mod error; mod metadata; @@ -144,3 +146,91 @@ fn make_presigned_request<'a>(env: &mut JNIEnv<'a>, req: PresignedRequest) -> Re )?; Ok(result) } + +fn make_operator_info<'a>(env: &mut JNIEnv<'a>, info: OperatorInfo) -> Result> { + let operator_info_class = env.find_class("org/apache/opendal/OperatorInfo")?; + + let schema = env.new_string(info.scheme().to_string())?; + let root = env.new_string(info.root().to_string())?; + let name = env.new_string(info.name().to_string())?; + let full_capability_obj = make_capability(env, info.full_capability())?; + let native_capability_obj = make_capability(env, info.native_capability())?; + + let operator_info_obj = env + .new_object( + operator_info_class, + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Lorg/apache/opendal/Capability;Lorg/apache/opendal/Capability;)V", + &[ + JValue::Object(&schema), + JValue::Object(&root), + JValue::Object(&name), + JValue::Object(&full_capability_obj), + JValue::Object(&native_capability_obj), + ], + )?; + + Ok(operator_info_obj) +} + +fn make_capability<'a>(env: &mut JNIEnv<'a>, cap: Capability) -> Result> { + let capability_class = env.find_class("org/apache/opendal/Capability")?; + + let write_multi_max_size = make_long(env, cap.write_multi_max_size)?; + let write_multi_min_size = make_long(env, cap.write_multi_min_size)?; + let write_multi_align_size = make_long(env, cap.write_multi_align_size)?; + let batch_max_operations = make_long(env, cap.batch_max_operations)?; + + let capability = env.new_object(capability_class, "(ZZZZZZZZZZZZZZZZZZLjava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;ZZZZZZZZZZZZZZZLjava/lang/Long;Z)V", + &[ + JValue::Bool(cap.stat as jboolean), + JValue::Bool(cap.stat_with_if_match as jboolean), + JValue::Bool(cap.stat_with_if_none_match as jboolean), + JValue::Bool(cap.read as jboolean), + JValue::Bool(cap.read_can_seek as jboolean), + JValue::Bool(cap.read_can_next as jboolean), + JValue::Bool(cap.read_with_range as jboolean), + JValue::Bool(cap.read_with_if_match as jboolean), + JValue::Bool(cap.read_with_if_none_match as jboolean), + JValue::Bool(cap.read_with_override_cache_control as jboolean), + JValue::Bool(cap.read_with_override_content_disposition as jboolean), + JValue::Bool(cap.read_with_override_content_type as jboolean), + JValue::Bool(cap.write as jboolean), + JValue::Bool(cap.write_can_multi as jboolean), + JValue::Bool(cap.write_can_append as jboolean), + JValue::Bool(cap.write_with_content_type as jboolean), + JValue::Bool(cap.write_with_content_disposition as jboolean), + JValue::Bool(cap.write_with_cache_control as jboolean), + JValue::Object(&write_multi_max_size), + JValue::Object(&write_multi_min_size), + JValue::Object(&write_multi_align_size), + JValue::Bool(cap.create_dir as jboolean), + JValue::Bool(cap.delete as jboolean), + JValue::Bool(cap.copy as jboolean), + JValue::Bool(cap.rename as jboolean), + JValue::Bool(cap.list as jboolean), + JValue::Bool(cap.list_with_limit as jboolean), + JValue::Bool(cap.list_with_start_after as jboolean), + JValue::Bool(cap.list_with_delimiter_slash as jboolean), + JValue::Bool(cap.list_without_delimiter as jboolean), + JValue::Bool(cap.presign as jboolean), + JValue::Bool(cap.presign_read as jboolean), + JValue::Bool(cap.presign_stat as jboolean), + JValue::Bool(cap.presign_write as jboolean), + JValue::Bool(cap.batch as jboolean), + JValue::Bool(cap.batch_delete as jboolean), + JValue::Object(&batch_max_operations), + JValue::Bool(cap.blocking as jboolean), + ])?; + + Ok(capability) +} + +fn make_long<'a>(env: &mut JNIEnv<'a>, value: Option) -> Result> { + let long_class = env.find_class("java/lang/Long")?; + + let result = match value { + Some(val) => env.new_object(long_class, "(J)V", &[JValue::Long(val as jlong)])?, + None => JObject::null(), + }; + Ok(result) +} diff --git a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java index 1d8e2bf25a66..e82bdfea8be5 100644 --- a/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java +++ b/bindings/java/src/main/java/org/apache/opendal/BlockingOperator.java @@ -61,6 +61,10 @@ public Metadata stat(String path) { return new Metadata(stat(nativeHandle, path)); } + public OperatorInfo info() { + return info(nativeHandle); + } + @Override protected native void disposeInternal(long handle); @@ -73,4 +77,6 @@ public Metadata stat(String path) { private static native void delete(long nativeHandle, String path); private static native long stat(long nativeHandle, String path); + + private static native OperatorInfo info(long nativeHandle); } diff --git a/bindings/java/src/main/java/org/apache/opendal/Capability.java b/bindings/java/src/main/java/org/apache/opendal/Capability.java new file mode 100644 index 000000000000..d13857624760 --- /dev/null +++ b/bindings/java/src/main/java/org/apache/opendal/Capability.java @@ -0,0 +1,270 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.opendal; + +import lombok.ToString; + +@ToString +public class Capability { + /** + * If operator supports stat. + */ + public final boolean stat; + /** + * If operator supports stat with if match. + */ + public final boolean statWithIfMatch; + /** + * If operator supports stat with if none match. + */ + public final boolean statWithIfNoneMatch; + + /** + * If operator supports read. + */ + public final boolean read; + /** + * If operator supports seek on returning reader. + */ + public final boolean readCanSeek; + /** + * If operator supports next on returning reader. + */ + public final boolean readCanNext; + /** + * If operator supports read with range. + */ + public final boolean readWithRange; + /** + * If operator supports read with if match. + */ + public final boolean readWithIfMatch; + /** + * If operator supports read with if none match. + */ + public final boolean readWithIfNoneMatch; + /** + * If operator supports read with override cache control. + */ + public final boolean readWithOverrideCacheControl; + /** + * if operator supports read with override content disposition. + */ + public final boolean readWithOverrideContentDisposition; + /** + * if operator supports read with override content type. + */ + public final boolean readWithOverrideContentType; + + /** + * If operator supports write. + */ + public final boolean write; + /** + * If operator supports write can be called in multi times. + */ + public final boolean writeCanMulti; + /** + * If operator supports write by append. + */ + public final boolean writeCanAppend; + /** + * If operator supports write with content type. + */ + public final boolean writeWithContentType; + /** + * If operator supports write with content disposition. + */ + public final boolean writeWithContentDisposition; + /** + * If operator supports write with cache control. + */ + public final boolean writeWithCacheControl; + /** + * write_multi_max_size is the max size that services support in write_multi. + * For example, AWS S3 supports 5GiB as max in write_multi. + */ + public final Long writeMultiMaxSize; + /** + * write_multi_min_size is the min size that services support in write_multi. + * For example, AWS S3 requires at least 5MiB in write_multi expect the last one. + */ + public final Long writeMultiMinSize; + /** + * write_multi_align_size is the align size that services required in write_multi. + * For example, Google GCS requires align size to 256KiB in write_multi. + */ + public final Long writeMultiAlignSize; + + /** + * If operator supports create dir. + */ + public final boolean createDir; + + /** + * If operator supports delete. + */ + public final boolean delete; + + /** + * If operator supports copy. + */ + public final boolean copy; + + /** + * If operator supports rename. + */ + public final boolean rename; + + /** + * If operator supports list. + */ + public final boolean list; + /** + * If backend supports list with limit. + */ + public final boolean listWithLimit; + /** + * If backend supports list with start after. + */ + public final boolean listWithStartAfter; + /** + * If backend support list with using slash as delimiter. + */ + public final boolean listWithDelimiterSlash; + /** + * If backend supports list without delimiter. + */ + public final boolean listWithoutDelimiter; + + /** + * If operator supports presign. + */ + public final boolean presign; + /** + * If operator supports presign read. + */ + public final boolean presignRead; + /** + * If operator supports presign stat. + */ + public final boolean presignStat; + /** + * If operator supports presign write. + */ + public final boolean presignWrite; + + /** + * If operator supports batch. + */ + public final boolean batch; + /** + * If operator supports batch delete. + */ + public final boolean batchDelete; + /** + * The max operations that operator supports in batch. + */ + public final Long batchMaxOperations; + + /** + * If operator supports blocking. + */ + public final boolean blocking; + + public Capability( + boolean stat, + boolean statWithIfMatch, + boolean statWithIfNoneMatch, + boolean read, + boolean readCanSeek, + boolean readCanNext, + boolean readWithRange, + boolean readWithIfMatch, + boolean readWithIfNoneMatch, + boolean readWithOverrideCacheControl, + boolean readWithOverrideContentDisposition, + boolean readWithOverrideContentType, + boolean write, + boolean writeCanMulti, + boolean writeCanAppend, + boolean writeWithContentType, + boolean writeWithContentDisposition, + boolean writeWithCacheControl, + Long writeMultiMaxSize, + Long writeMultiMinSize, + Long writeMultiAlignSize, + boolean createDir, + boolean delete, + boolean copy, + boolean rename, + boolean list, + boolean listWithLimit, + boolean listWithStartAfter, + boolean listWithDelimiterSlash, + boolean listWithoutDelimiter, + boolean presign, + boolean presignRead, + boolean presignStat, + boolean presignWrite, + boolean batch, + boolean batchDelete, + Long batchMaxOperations, + boolean blocking) { + this.stat = stat; + this.statWithIfMatch = statWithIfMatch; + this.statWithIfNoneMatch = statWithIfNoneMatch; + this.read = read; + this.readCanSeek = readCanSeek; + this.readCanNext = readCanNext; + this.readWithRange = readWithRange; + this.readWithIfMatch = readWithIfMatch; + this.readWithIfNoneMatch = readWithIfNoneMatch; + this.readWithOverrideCacheControl = readWithOverrideCacheControl; + this.readWithOverrideContentDisposition = readWithOverrideContentDisposition; + this.readWithOverrideContentType = readWithOverrideContentType; + this.write = write; + this.writeCanMulti = writeCanMulti; + this.writeCanAppend = writeCanAppend; + this.writeWithContentType = writeWithContentType; + this.writeWithContentDisposition = writeWithContentDisposition; + this.writeWithCacheControl = writeWithCacheControl; + this.writeMultiMaxSize = writeMultiMaxSize; + this.writeMultiMinSize = writeMultiMinSize; + this.writeMultiAlignSize = writeMultiAlignSize; + this.createDir = createDir; + this.delete = delete; + this.copy = copy; + this.rename = rename; + this.list = list; + this.listWithLimit = listWithLimit; + this.listWithStartAfter = listWithStartAfter; + this.listWithDelimiterSlash = listWithDelimiterSlash; + this.listWithoutDelimiter = listWithoutDelimiter; + this.presign = presign; + this.presignRead = presignRead; + this.presignStat = presignStat; + this.presignWrite = presignWrite; + this.batch = batch; + this.batchDelete = batchDelete; + this.batchMaxOperations = batchMaxOperations; + this.blocking = blocking; + } +} diff --git a/bindings/java/src/main/java/org/apache/opendal/Operator.java b/bindings/java/src/main/java/org/apache/opendal/Operator.java index c6206ef3c325..cdc09e34b193 100644 --- a/bindings/java/src/main/java/org/apache/opendal/Operator.java +++ b/bindings/java/src/main/java/org/apache/opendal/Operator.java @@ -142,6 +142,10 @@ public CompletableFuture read(String path) { return AsyncRegistry.take(requestId); } + public OperatorInfo info() { + return info(nativeHandle); + } + public CompletableFuture presignRead(String path, Duration duration) { final long requestId = presignRead(nativeHandle, path, duration.toNanos()); return AsyncRegistry.take(requestId); @@ -182,4 +186,6 @@ public CompletableFuture delete(String path) { private static native long presignWrite(long nativeHandle, String path, long duration); private static native long presignStat(long nativeHandle, String path, long duration); + + private static native OperatorInfo info(long nativeHandle); } diff --git a/bindings/java/src/main/java/org/apache/opendal/OperatorInfo.java b/bindings/java/src/main/java/org/apache/opendal/OperatorInfo.java new file mode 100644 index 000000000000..c170f33559cb --- /dev/null +++ b/bindings/java/src/main/java/org/apache/opendal/OperatorInfo.java @@ -0,0 +1,45 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.opendal; + +import lombok.NonNull; +import lombok.ToString; + +@ToString +public class OperatorInfo { + public final String scheme; + public final String root; + public final String name; + public final Capability fullCapability; + public final Capability nativeCapability; + + public OperatorInfo( + @NonNull String scheme, + @NonNull String root, + @NonNull String name, + @NonNull Capability fullCapability, + @NonNull Capability nativeCapability) { + this.scheme = scheme; + this.root = root; + this.name = name; + this.fullCapability = fullCapability; + this.nativeCapability = nativeCapability; + } +} diff --git a/bindings/java/src/operator.rs b/bindings/java/src/operator.rs index d0b3d938d198..58823e78111a 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::make_operator_info; use crate::make_presigned_request; use crate::Result; @@ -262,6 +263,28 @@ async fn do_delete(op: &mut Operator, path: String) -> Result<()> { Ok(op.delete(&path).await?) } +// # Safety +/// +/// This function should not be called before the Operator are ready. +#[no_mangle] +pub unsafe extern "system" fn Java_org_apache_opendal_Operator_info<'local>( + mut env: JNIEnv<'local>, + _: JClass, + op: *mut Operator, +) -> JObject<'local> { + intern_info(&mut env, op).unwrap_or_else(|e| { + e.throw(&mut env); + JObject::null() + }) +} + +fn intern_info<'local>(env: &mut JNIEnv<'local>, op: *mut Operator) -> Result> { + let op = unsafe { &mut *op }; + + let info = op.info(); + make_operator_info(env, info) +} + /// # Safety /// /// This function should not be called before the Operator are ready. diff --git a/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java new file mode 100644 index 000000000000..f98722040891 --- /dev/null +++ b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java @@ -0,0 +1,94 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.opendal; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.Map; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +public class OperatorInfoTest { + + @TempDir + private static Path tempDir; + + @Test + public void testBlockingOperatorInfo() { + Map conf = new HashMap<>(); + conf.put("root", tempDir.toString()); + try (BlockingOperator op = new BlockingOperator("fs", conf)) { + + OperatorInfo info = op.info(); + assertNotNull(info); + assertEquals("fs", info.scheme); + + Capability fullCapability = info.fullCapability; + assertNotNull(fullCapability); + + assertTrue(fullCapability.read); + assertTrue(fullCapability.write); + assertTrue(fullCapability.delete); + assertTrue(fullCapability.writeCanAppend); + + assertNull(fullCapability.writeMultiAlignSize); + assertNull(fullCapability.writeMultiMaxSize); + assertNull(fullCapability.writeMultiMinSize); + assertNull(fullCapability.batchMaxOperations); + + Capability nativeCapability = info.nativeCapability; + assertNotNull(nativeCapability); + } + } + + @Test + public void testOperatorInfo() { + Map conf = new HashMap<>(); + String root = "/opendal/"; + conf.put("root", root); + try (Operator op = new Operator("memory", conf)) { + + OperatorInfo info = op.info(); + assertNotNull(info); + assertEquals("memory", info.scheme); + assertEquals(root, info.root); + + Capability fullCapability = info.fullCapability; + assertNotNull(fullCapability); + + assertTrue(fullCapability.read); + assertTrue(fullCapability.write); + assertTrue(fullCapability.delete); + assertTrue(!fullCapability.writeCanAppend); + + assertNull(fullCapability.writeMultiAlignSize); + assertNull(fullCapability.writeMultiMaxSize); + assertNull(fullCapability.writeMultiMinSize); + assertNull(fullCapability.batchMaxOperations); + + Capability nativeCapability = info.nativeCapability; + assertNotNull(nativeCapability); + } + } +} From 025fe5c1459b6b291cd71b39c42d8d750784574b Mon Sep 17 00:00:00 2001 From: G-XD Date: Thu, 21 Sep 2023 18:05:17 +0800 Subject: [PATCH 2/3] feat(binding/java): cast usize to long --- bindings/java/src/lib.rs | 100 ++++++++---------- .../java/org/apache/opendal/Capability.java | 16 +-- .../org/apache/opendal/OperatorInfoTest.java | 16 +-- 3 files changed, 60 insertions(+), 72 deletions(-) diff --git a/bindings/java/src/lib.rs b/bindings/java/src/lib.rs index 9e90160d4981..cd039ef09190 100644 --- a/bindings/java/src/lib.rs +++ b/bindings/java/src/lib.rs @@ -175,62 +175,50 @@ fn make_operator_info<'a>(env: &mut JNIEnv<'a>, info: OperatorInfo) -> Result(env: &mut JNIEnv<'a>, cap: Capability) -> Result> { let capability_class = env.find_class("org/apache/opendal/Capability")?; - let write_multi_max_size = make_long(env, cap.write_multi_max_size)?; - let write_multi_min_size = make_long(env, cap.write_multi_min_size)?; - let write_multi_align_size = make_long(env, cap.write_multi_align_size)?; - let batch_max_operations = make_long(env, cap.batch_max_operations)?; - - let capability = env.new_object(capability_class, "(ZZZZZZZZZZZZZZZZZZLjava/lang/Long;Ljava/lang/Long;Ljava/lang/Long;ZZZZZZZZZZZZZZZLjava/lang/Long;Z)V", - &[ - JValue::Bool(cap.stat as jboolean), - JValue::Bool(cap.stat_with_if_match as jboolean), - JValue::Bool(cap.stat_with_if_none_match as jboolean), - JValue::Bool(cap.read as jboolean), - JValue::Bool(cap.read_can_seek as jboolean), - JValue::Bool(cap.read_can_next as jboolean), - JValue::Bool(cap.read_with_range as jboolean), - JValue::Bool(cap.read_with_if_match as jboolean), - JValue::Bool(cap.read_with_if_none_match as jboolean), - JValue::Bool(cap.read_with_override_cache_control as jboolean), - JValue::Bool(cap.read_with_override_content_disposition as jboolean), - JValue::Bool(cap.read_with_override_content_type as jboolean), - JValue::Bool(cap.write as jboolean), - JValue::Bool(cap.write_can_multi as jboolean), - JValue::Bool(cap.write_can_append as jboolean), - JValue::Bool(cap.write_with_content_type as jboolean), - JValue::Bool(cap.write_with_content_disposition as jboolean), - JValue::Bool(cap.write_with_cache_control as jboolean), - JValue::Object(&write_multi_max_size), - JValue::Object(&write_multi_min_size), - JValue::Object(&write_multi_align_size), - JValue::Bool(cap.create_dir as jboolean), - JValue::Bool(cap.delete as jboolean), - JValue::Bool(cap.copy as jboolean), - JValue::Bool(cap.rename as jboolean), - JValue::Bool(cap.list as jboolean), - JValue::Bool(cap.list_with_limit as jboolean), - JValue::Bool(cap.list_with_start_after as jboolean), - JValue::Bool(cap.list_with_delimiter_slash as jboolean), - JValue::Bool(cap.list_without_delimiter as jboolean), - JValue::Bool(cap.presign as jboolean), - JValue::Bool(cap.presign_read as jboolean), - JValue::Bool(cap.presign_stat as jboolean), - JValue::Bool(cap.presign_write as jboolean), - JValue::Bool(cap.batch as jboolean), - JValue::Bool(cap.batch_delete as jboolean), - JValue::Object(&batch_max_operations), - JValue::Bool(cap.blocking as jboolean), - ])?; + let capability = env.new_object( + capability_class, + "(ZZZZZZZZZZZZZZZZZZJJJZZZZZZZZZZZZZZZJZ)V", + &[ + JValue::Bool(cap.stat as jboolean), + JValue::Bool(cap.stat_with_if_match as jboolean), + JValue::Bool(cap.stat_with_if_none_match as jboolean), + JValue::Bool(cap.read as jboolean), + JValue::Bool(cap.read_can_seek as jboolean), + JValue::Bool(cap.read_can_next as jboolean), + JValue::Bool(cap.read_with_range as jboolean), + JValue::Bool(cap.read_with_if_match as jboolean), + JValue::Bool(cap.read_with_if_none_match as jboolean), + JValue::Bool(cap.read_with_override_cache_control as jboolean), + JValue::Bool(cap.read_with_override_content_disposition as jboolean), + JValue::Bool(cap.read_with_override_content_type as jboolean), + JValue::Bool(cap.write as jboolean), + JValue::Bool(cap.write_can_multi as jboolean), + JValue::Bool(cap.write_can_append as jboolean), + JValue::Bool(cap.write_with_content_type as jboolean), + JValue::Bool(cap.write_with_content_disposition as jboolean), + JValue::Bool(cap.write_with_cache_control as jboolean), + JValue::Long(cap.write_multi_max_size.map_or(-1, |v| v as jlong)), + JValue::Long(cap.write_multi_min_size.map_or(-1, |v| v as jlong)), + JValue::Long(cap.write_multi_align_size.map_or(-1, |v| v as jlong)), + JValue::Bool(cap.create_dir as jboolean), + JValue::Bool(cap.delete as jboolean), + JValue::Bool(cap.copy as jboolean), + JValue::Bool(cap.rename as jboolean), + JValue::Bool(cap.list as jboolean), + JValue::Bool(cap.list_with_limit as jboolean), + JValue::Bool(cap.list_with_start_after as jboolean), + JValue::Bool(cap.list_with_delimiter_slash as jboolean), + JValue::Bool(cap.list_without_delimiter as jboolean), + JValue::Bool(cap.presign as jboolean), + JValue::Bool(cap.presign_read as jboolean), + JValue::Bool(cap.presign_stat as jboolean), + JValue::Bool(cap.presign_write as jboolean), + JValue::Bool(cap.batch as jboolean), + JValue::Bool(cap.batch_delete as jboolean), + JValue::Long(cap.batch_max_operations.map_or(-1, |v| v as jlong)), + JValue::Bool(cap.blocking as jboolean), + ], + )?; Ok(capability) } - -fn make_long<'a>(env: &mut JNIEnv<'a>, value: Option) -> Result> { - let long_class = env.find_class("java/lang/Long")?; - - let result = match value { - Some(val) => env.new_object(long_class, "(J)V", &[JValue::Long(val as jlong)])?, - None => JObject::null(), - }; - Ok(result) -} diff --git a/bindings/java/src/main/java/org/apache/opendal/Capability.java b/bindings/java/src/main/java/org/apache/opendal/Capability.java index d13857624760..2291738bb38f 100644 --- a/bindings/java/src/main/java/org/apache/opendal/Capability.java +++ b/bindings/java/src/main/java/org/apache/opendal/Capability.java @@ -101,17 +101,17 @@ public class Capability { * write_multi_max_size is the max size that services support in write_multi. * For example, AWS S3 supports 5GiB as max in write_multi. */ - public final Long writeMultiMaxSize; + public final long writeMultiMaxSize; /** * write_multi_min_size is the min size that services support in write_multi. * For example, AWS S3 requires at least 5MiB in write_multi expect the last one. */ - public final Long writeMultiMinSize; + public final long writeMultiMinSize; /** * write_multi_align_size is the align size that services required in write_multi. * For example, Google GCS requires align size to 256KiB in write_multi. */ - public final Long writeMultiAlignSize; + public final long writeMultiAlignSize; /** * If operator supports create dir. @@ -182,7 +182,7 @@ public class Capability { /** * The max operations that operator supports in batch. */ - public final Long batchMaxOperations; + public final long batchMaxOperations; /** * If operator supports blocking. @@ -208,9 +208,9 @@ public Capability( boolean writeWithContentType, boolean writeWithContentDisposition, boolean writeWithCacheControl, - Long writeMultiMaxSize, - Long writeMultiMinSize, - Long writeMultiAlignSize, + long writeMultiMaxSize, + long writeMultiMinSize, + long writeMultiAlignSize, boolean createDir, boolean delete, boolean copy, @@ -226,7 +226,7 @@ public Capability( boolean presignWrite, boolean batch, boolean batchDelete, - Long batchMaxOperations, + long batchMaxOperations, boolean blocking) { this.stat = stat; this.statWithIfMatch = statWithIfMatch; diff --git a/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java index f98722040891..ff3ed075b372 100644 --- a/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java @@ -52,10 +52,10 @@ public void testBlockingOperatorInfo() { assertTrue(fullCapability.delete); assertTrue(fullCapability.writeCanAppend); - assertNull(fullCapability.writeMultiAlignSize); - assertNull(fullCapability.writeMultiMaxSize); - assertNull(fullCapability.writeMultiMinSize); - assertNull(fullCapability.batchMaxOperations); + assertEquals(fullCapability.writeMultiAlignSize, -1); + assertEquals(fullCapability.writeMultiMaxSize, -1); + assertEquals(fullCapability.writeMultiMinSize, -1); + assertEquals(fullCapability.batchMaxOperations, -1); Capability nativeCapability = info.nativeCapability; assertNotNull(nativeCapability); @@ -82,10 +82,10 @@ public void testOperatorInfo() { assertTrue(fullCapability.delete); assertTrue(!fullCapability.writeCanAppend); - assertNull(fullCapability.writeMultiAlignSize); - assertNull(fullCapability.writeMultiMaxSize); - assertNull(fullCapability.writeMultiMinSize); - assertNull(fullCapability.batchMaxOperations); + assertEquals(fullCapability.writeMultiAlignSize, -1); + assertEquals(fullCapability.writeMultiMaxSize, -1); + assertEquals(fullCapability.writeMultiMinSize, -1); + assertEquals(fullCapability.batchMaxOperations, -1); Capability nativeCapability = info.nativeCapability; assertNotNull(nativeCapability); From 734a22246422dab8ed8ba060e73ea8f9bc33c62b Mon Sep 17 00:00:00 2001 From: G-XD Date: Thu, 21 Sep 2023 18:51:03 +0800 Subject: [PATCH 3/3] chore(binding/java): del unused import --- .../java/src/test/java/org/apache/opendal/OperatorInfoTest.java | 1 - 1 file changed, 1 deletion(-) diff --git a/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java index ff3ed075b372..e4ea7786a217 100644 --- a/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java +++ b/bindings/java/src/test/java/org/apache/opendal/OperatorInfoTest.java @@ -21,7 +21,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import java.nio.file.Path; import java.util.HashMap;