diff --git a/experimental/s3-client-annotation-processor/build.gradle b/experimental/s3-client-annotation-processor/build.gradle index 319e46905..6ab6616bd 100644 --- a/experimental/s3-client-annotation-processor/build.gradle +++ b/experimental/s3-client-annotation-processor/build.gradle @@ -3,7 +3,7 @@ dependencies { implementation project(":kora-app-annotation-processor") testImplementation testFixtures(project(":annotation-processor-common")) - testImplementation project(":experimental:s3-client") + testImplementation project(":experimental:s3-client-kora") } apply from: "${project.rootDir}/gradle/in-test-generated.gradle" diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClassNames.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClassNames.java similarity index 58% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClassNames.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClassNames.java index 816ade7ea..d1e580459 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClassNames.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClassNames.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import com.palantir.javapoet.ArrayTypeName; import com.palantir.javapoet.ClassName; @@ -10,42 +10,42 @@ public class S3ClassNames { public static class Annotation { - public static final ClassName CLIENT = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Client"); - public static final ClassName BUCKET = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Bucket"); - public static final ClassName GET = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Get"); - public static final ClassName LIST = ClassName.get("io.koraframework.s3.client.annotation", "S3", "List"); - public static final ClassName PUT = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Put"); - public static final ClassName DELETE = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Delete"); - public static final ClassName HEAD = ClassName.get("io.koraframework.s3.client.annotation", "S3", "Head"); + public static final ClassName CLIENT = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Client"); + public static final ClassName BUCKET = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Bucket"); + public static final ClassName GET = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Get"); + public static final ClassName LIST = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "List"); + public static final ClassName PUT = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Put"); + public static final ClassName DELETE = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Delete"); + public static final ClassName HEAD = ClassName.get("io.koraframework.s3.client.kora.annotation", "S3", "Head"); public static final Set OPERATIONS = Set.of(GET, LIST, PUT, DELETE, HEAD); } - public static final ClassName CLIENT = ClassName.get("io.koraframework.s3.client", "S3Client"); - public static final ClassName AWS_CREDENTIALS = ClassName.get("io.koraframework.s3.client", "AwsCredentials"); - public static final ClassName CLIENT_FACTORY = ClassName.get("io.koraframework.s3.client", "S3ClientFactory"); - public static final ClassName CONFIG = ClassName.get("io.koraframework.s3.client", "S3ClientConfig"); - public static final ClassName CONFIG_WITH_CREDS = ClassName.get("io.koraframework.s3.client", "S3ClientConfigWithCredentials"); + public static final ClassName CLIENT = ClassName.get("io.koraframework.s3.client.kora", "S3Client"); + public static final ClassName S3_CREDENTIALS = ClassName.get("io.koraframework.s3.client.kora", "S3Credentials"); + public static final ClassName CLIENT_FACTORY = ClassName.get("io.koraframework.s3.client.kora", "S3ClientFactory"); + public static final ClassName CONFIG = ClassName.get("io.koraframework.s3.client.kora", "S3ClientConfig"); + public static final ClassName CONFIG_WITH_CREDS = ClassName.get("io.koraframework.s3.client.kora", "S3ClientConfigWithCredentials"); public static final ClassName CONTENT_WRITER = CLIENT.nestedClass("ContentWriter"); - public static final ClassName PUT_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "PutObjectArgs"); - public static final ClassName GET_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "GetObjectArgs"); - public static final ClassName DELETE_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "DeleteObjectArgs"); - public static final ClassName HEAD_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "HeadObjectArgs"); - public static final ClassName LIST_OBJECTS_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "ListObjectsArgs"); - public static final ClassName CREATE_MULTIPART_UPLOAD_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "CreateMultipartUploadArgs"); - public static final ClassName COMPLETE_MULTIPART_UPLOAD_ARGS = ClassName.get("io.koraframework.s3.client.model.request", "CompleteMultipartUploadArgs"); + public static final ClassName PUT_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "PutObjectArgs"); + public static final ClassName GET_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "GetObjectArgs"); + public static final ClassName DELETE_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "DeleteObjectArgs"); + public static final ClassName HEAD_OBJECT_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "HeadObjectArgs"); + public static final ClassName LIST_OBJECTS_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "ListObjectsArgs"); + public static final ClassName CREATE_MULTIPART_UPLOAD_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "CreateMultipartUploadArgs"); + public static final ClassName COMPLETE_MULTIPART_UPLOAD_ARGS = ClassName.get("io.koraframework.s3.client.kora.model.request", "CompleteMultipartUploadArgs"); public static final Set ARGS = Set.of(PUT_OBJECT_ARGS, GET_OBJECT_ARGS, DELETE_OBJECT_ARGS, HEAD_OBJECT_ARGS, LIST_OBJECTS_ARGS); - public static final ClassName GET_OBJECT_RESULT = ClassName.get("io.koraframework.s3.client.model.response", "GetObjectResult"); - public static final ClassName HEAD_OBJECT_RESULT = ClassName.get("io.koraframework.s3.client.model.response", "HeadObjectResult"); - public static final ClassName LIST_BUCKET_RESULT = ClassName.get("io.koraframework.s3.client.model.response", "ListBucketResult"); - public static final ClassName UPLOADED_PART = ClassName.get("io.koraframework.s3.client.model.response", "UploadedPart"); + public static final ClassName GET_OBJECT_RESULT = ClassName.get("io.koraframework.s3.client.kora.model.response", "GetObjectResult"); + public static final ClassName HEAD_OBJECT_RESULT = ClassName.get("io.koraframework.s3.client.kora.model.response", "HeadObjectResult"); + public static final ClassName LIST_BUCKET_RESULT = ClassName.get("io.koraframework.s3.client.kora.model.response", "ListBucketResult"); + public static final ClassName UPLOADED_PART = ClassName.get("io.koraframework.s3.client.kora.model.response", "UploadedPart"); public static final ClassName LIST_BUCKET_RESULT_ITEM = LIST_BUCKET_RESULT.nestedClass("ListBucketItem"); - public static final ClassName UNKNOWN_EXCEPTION = ClassName.get("io.koraframework.s3.client.exception", "S3ClientUnknownException"); + public static final ClassName UNKNOWN_EXCEPTION = ClassName.get("io.koraframework.s3.client.kora.exception", "S3ClientUnknownException"); public static final Set BODY_TYPES = Set.of( ArrayTypeName.of(TypeName.BYTE), diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessor.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessor.java similarity index 87% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessor.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessor.java index df5b6befc..f8ef3de82 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessor.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessor.java @@ -1,12 +1,12 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import com.palantir.javapoet.ClassName; import com.palantir.javapoet.JavaFile; import io.koraframework.annotation.processor.common.AbstractKoraProcessor; import io.koraframework.annotation.processor.common.ProcessingErrorException; -import io.koraframework.s3.client.annotation.processor.gen.BucketsConfigGenerator; -import io.koraframework.s3.client.annotation.processor.gen.ClientGenerator; -import io.koraframework.s3.client.annotation.processor.gen.ModuleGenerator; +import io.koraframework.s3.client.kora.annotation.processor.gen.BucketsConfigGenerator; +import io.koraframework.s3.client.kora.annotation.processor.gen.ClientGenerator; +import io.koraframework.s3.client.kora.annotation.processor.gen.ModuleGenerator; import javax.annotation.processing.RoundEnvironment; import javax.lang.model.element.TypeElement; diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientUtils.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientUtils.java similarity index 95% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientUtils.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientUtils.java index bfb4a79b8..788dff356 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/S3ClientUtils.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientUtils.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import com.palantir.javapoet.TypeName; import org.jspecify.annotations.Nullable; @@ -61,7 +61,7 @@ public static VariableElement credentialsParameter(ExecutableElement method) { VariableElement foundParam = null; for (var param : method.getParameters()) { var typeName = TypeName.get(param.asType()); - if (S3ClassNames.AWS_CREDENTIALS.equals(typeName)) { + if (S3ClassNames.S3_CREDENTIALS.equals(typeName)) { if (foundParam != null) { throw new ProcessingErrorException("Multiple AwsCredentials parameters found", method, null); } diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/BucketsConfigGenerator.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/BucketsConfigGenerator.java similarity index 91% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/BucketsConfigGenerator.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/BucketsConfigGenerator.java index 0699f655f..85cca1059 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/BucketsConfigGenerator.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/BucketsConfigGenerator.java @@ -1,12 +1,12 @@ -package io.koraframework.s3.client.annotation.processor.gen; +package io.koraframework.s3.client.kora.annotation.processor.gen; import com.palantir.javapoet.*; import io.koraframework.annotation.processor.common.AnnotationUtils; import io.koraframework.annotation.processor.common.CommonClassNames; import io.koraframework.annotation.processor.common.NameUtils; -import io.koraframework.s3.client.annotation.processor.S3ClassNames; -import io.koraframework.s3.client.annotation.processor.S3ClientAnnotationProcessor; -import io.koraframework.s3.client.annotation.processor.S3ClientUtils; +import io.koraframework.s3.client.kora.annotation.processor.S3ClassNames; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientAnnotationProcessor; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientUtils; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.Modifier; diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ClientGenerator.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ClientGenerator.java similarity index 98% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ClientGenerator.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ClientGenerator.java index 7cff4d8a0..ae33bacc3 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ClientGenerator.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ClientGenerator.java @@ -1,13 +1,13 @@ -package io.koraframework.s3.client.annotation.processor.gen; +package io.koraframework.s3.client.kora.annotation.processor.gen; import com.palantir.javapoet.*; import io.koraframework.annotation.processor.common.AnnotationUtils; import io.koraframework.annotation.processor.common.CommonUtils; import io.koraframework.annotation.processor.common.NameUtils; import io.koraframework.annotation.processor.common.ProcessingErrorException; -import io.koraframework.s3.client.annotation.processor.S3ClassNames; -import io.koraframework.s3.client.annotation.processor.S3ClientAnnotationProcessor; -import io.koraframework.s3.client.annotation.processor.S3ClientUtils; +import io.koraframework.s3.client.kora.annotation.processor.S3ClassNames; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientAnnotationProcessor; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientUtils; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.*; @@ -31,7 +31,7 @@ public static TypeSpec generate(ProcessingEnvironment processingEnv, TypeElement var configType = credsRequired ? S3ClassNames.CONFIG_WITH_CREDS : S3ClassNames.CONFIG; - var b = CommonUtils.extendsKeepAop(s3client, NameUtils.generatedType(s3client, "ClientImpl")) + var b = CommonUtils.extendsKeepAop(s3client, NameUtils.generatedType(s3client, "S3ClientImpl")) .addAnnotation(AnnotationUtils.generated(S3ClientAnnotationProcessor.class)) .addField(S3ClassNames.CLIENT, "client", Modifier.PRIVATE, Modifier.FINAL) .addField(configType, "config", Modifier.PRIVATE, Modifier.FINAL); @@ -358,7 +358,7 @@ private static CodeBlock generateKey(ExecutableElement method, AnnotationMirror .filter(p -> { var parameterTypeName = TypeName.get(p.asType()); return !AnnotationUtils.isAnnotationPresent(p, S3ClassNames.Annotation.BUCKET) - && !S3ClassNames.AWS_CREDENTIALS.equals(parameterTypeName) + && !S3ClassNames.S3_CREDENTIALS.equals(parameterTypeName) && !S3ClassNames.ARGS.contains(parameterTypeName) && !S3ClassNames.BODY_TYPES.contains(parameterTypeName) ; diff --git a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ModuleGenerator.java b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ModuleGenerator.java similarity index 91% rename from experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ModuleGenerator.java rename to experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ModuleGenerator.java index 30f6f92f0..ed91e3eb7 100644 --- a/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/annotation/processor/gen/ModuleGenerator.java +++ b/experimental/s3-client-annotation-processor/src/main/java/io/koraframework/s3/client/kora/annotation/processor/gen/ModuleGenerator.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.annotation.processor.gen; +package io.koraframework.s3.client.kora.annotation.processor.gen; import com.palantir.javapoet.ClassName; import com.palantir.javapoet.MethodSpec; @@ -7,9 +7,9 @@ import io.koraframework.annotation.processor.common.AnnotationUtils; import io.koraframework.annotation.processor.common.CommonClassNames; import io.koraframework.annotation.processor.common.NameUtils; -import io.koraframework.s3.client.annotation.processor.S3ClassNames; -import io.koraframework.s3.client.annotation.processor.S3ClientAnnotationProcessor; -import io.koraframework.s3.client.annotation.processor.S3ClientUtils; +import io.koraframework.s3.client.kora.annotation.processor.S3ClassNames; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientAnnotationProcessor; +import io.koraframework.s3.client.kora.annotation.processor.S3ClientUtils; import javax.annotation.processing.ProcessingEnvironment; import javax.lang.model.element.ElementKind; @@ -21,8 +21,8 @@ public class ModuleGenerator { public static TypeSpec generate(ProcessingEnvironment processingEnv, TypeElement s3client) { var packageName = processingEnv.getElementUtils().getPackageOf(s3client).getQualifiedName().toString(); var bucketsType = ClassName.get(packageName, NameUtils.generatedType(s3client, "BucketsConfig")); - var clientType = ClassName.get(packageName, NameUtils.generatedType(s3client, "ClientImpl")); - var b = TypeSpec.interfaceBuilder(NameUtils.generatedType(s3client, "Module")) + var clientType = ClassName.get(packageName, NameUtils.generatedType(s3client, "S3ClientImpl")); + var b = TypeSpec.interfaceBuilder(NameUtils.generatedType(s3client, "S3Module")) .addModifiers(Modifier.PUBLIC) .addAnnotation(CommonClassNames.module) .addAnnotation(AnnotationUtils.generated(S3ClientAnnotationProcessor.class)) diff --git a/experimental/s3-client-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/experimental/s3-client-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor index 939ec198f..cf4cadd73 100644 --- a/experimental/s3-client-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor +++ b/experimental/s3-client-annotation-processor/src/main/resources/META-INF/services/javax.annotation.processing.Processor @@ -1 +1 @@ -io.koraframework.s3.client.annotation.processor.S3ClientAnnotationProcessor +io.koraframework.s3.client.kora.annotation.processor.S3ClientAnnotationProcessor diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessorTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessorTest.java deleted file mode 100644 index 3c7060bbc..000000000 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ClientAnnotationProcessorTest.java +++ /dev/null @@ -1,5 +0,0 @@ -package io.koraframework.s3.client.annotation.processor; - -class S3ClientAnnotationProcessorTest { - -} diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/AbstractS3ClientTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/AbstractS3ClientTest.java similarity index 68% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/AbstractS3ClientTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/AbstractS3ClientTest.java index 171b76d7a..ad7434b6c 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/AbstractS3ClientTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/AbstractS3ClientTest.java @@ -1,10 +1,10 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import io.koraframework.annotation.processor.common.AbstractAnnotationProcessorTest; import io.koraframework.aop.annotation.processor.AopAnnotationProcessor; -import io.koraframework.s3.client.S3Client; -import io.koraframework.s3.client.S3ClientConfigWithCredentials; -import io.koraframework.s3.client.S3ClientFactory; +import io.koraframework.s3.client.kora.S3Client; +import io.koraframework.s3.client.kora.S3ClientConfigWithCredentials; +import io.koraframework.s3.client.kora.S3ClientFactory; import org.intellij.lang.annotations.Language; import org.mockito.Mockito; @@ -21,12 +21,12 @@ protected String commonImports() { import java.util.Iterator; import java.util.Collection; import java.util.Optional; - import io.koraframework.s3.client.annotation.*; - import io.koraframework.s3.client.annotation.S3.*; - import io.koraframework.s3.client.model.request.*; - import io.koraframework.s3.client.model.response.*; - import io.koraframework.s3.client.*; - import io.koraframework.s3.client.S3Client.*; + import io.koraframework.s3.client.kora.annotation.*; + import io.koraframework.s3.client.kora.annotation.S3.*; + import io.koraframework.s3.client.kora.model.request.*; + import io.koraframework.s3.client.kora.model.response.*; + import io.koraframework.s3.client.kora.*; + import io.koraframework.s3.client.kora.S3Client.*; """; } @@ -41,6 +41,6 @@ protected AbstractAnnotationProcessorTest.TestObject compile(@Language("java") S args.add(clientFactory); args.add(config); args.addAll(List.of(addArgs)); - return new AbstractAnnotationProcessorTest.TestObject(loadClass("$Client_ClientImpl"), args); + return new AbstractAnnotationProcessorTest.TestObject(loadClass("$Client_S3ClientImpl"), args); } } diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessorTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessorTest.java new file mode 100644 index 000000000..6bd72f14a --- /dev/null +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ClientAnnotationProcessorTest.java @@ -0,0 +1,5 @@ +package io.koraframework.s3.client.kora.annotation.processor; + +class S3ClientAnnotationProcessorTest { + +} diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3DeleteTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3DeleteTest.java similarity index 89% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3DeleteTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3DeleteTest.java index f7d04f11e..8141dc273 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3DeleteTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3DeleteTest.java @@ -1,9 +1,9 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; +import io.koraframework.s3.client.kora.S3Credentials; import org.junit.jupiter.api.Test; import io.koraframework.config.common.factory.MapConfigFactory; -import io.koraframework.s3.client.AwsCredentials; -import io.koraframework.s3.client.model.request.DeleteObjectArgs; +import io.koraframework.s3.client.kora.model.request.DeleteObjectArgs; import java.util.Map; @@ -61,11 +61,11 @@ public void testDeleteWithAwsCredentials() throws Exception { @S3.Bucket(".bucket") public interface Client { @S3.Delete - void deleteWithCreds(AwsCredentials creds, String key); + void deleteWithCreds(S3Credentials creds, String key); } """, newGeneratedObject("$Client_BucketsConfig", bucketConfig)); - var creds = AwsCredentials.of("test", "test"); + var creds = S3Credentials.of("test", "test"); client.invoke("deleteWithCreds", creds, "key"); verify(s3Client).deleteObject(same(creds), eq("bucket_value"), eq("key"), isNull()); diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3GetTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3GetTest.java similarity index 91% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3GetTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3GetTest.java index 28b4cac68..542098887 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3GetTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3GetTest.java @@ -1,12 +1,12 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; +import io.koraframework.s3.client.kora.S3Credentials; import org.junit.jupiter.api.Test; import io.koraframework.config.common.factory.MapConfigFactory; import io.koraframework.http.common.body.HttpBodyInput; -import io.koraframework.s3.client.AwsCredentials; -import io.koraframework.s3.client.model.request.GetObjectArgs; -import io.koraframework.s3.client.model.response.GetObjectResult; +import io.koraframework.s3.client.kora.model.request.GetObjectArgs; +import io.koraframework.s3.client.kora.model.response.GetObjectResult; import java.io.ByteArrayInputStream; import java.util.Map; @@ -83,12 +83,12 @@ public void testGetWithAwsCredentials() throws Exception { public interface Client { @S3.Get @Nullable - GetObjectResult getWithCreds(AwsCredentials creds, String key); + GetObjectResult getWithCreds(S3Credentials creds, String key); } """, newGeneratedObject("$Client_BucketsConfig", bucketConfig)); var getObjectResult = mock(GetObjectResult.class); - var creds = AwsCredentials.of("test", "test"); + var creds = S3Credentials.of("test", "test"); when(s3Client.getObject(same(creds), eq("bucket_value"), eq("key"), isNull(), eq(false))).thenReturn(getObjectResult); var result = client.invoke("getWithCreds", creds, "key"); @@ -101,7 +101,7 @@ public interface Client { @Test public void testGetWithGetObjectArgsParam() throws Exception { var client = this.compile(""" - import io.koraframework.s3.client.model.request.GetObjectArgs;@S3.Client + import io.koraframework.s3.client.kora.model.request.GetObjectArgs;@S3.Client public interface Client { @S3.Get GetObjectResult getWithArgs(@S3.Bucket String bucket, String key, GetObjectArgs args); diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3HeadTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3HeadTest.java similarity index 88% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3HeadTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3HeadTest.java index d18a901ce..2f213383a 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3HeadTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3HeadTest.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import org.junit.jupiter.api.Test; import io.koraframework.http.common.header.HttpHeaders; -import io.koraframework.s3.client.model.response.HeadObjectResult; +import io.koraframework.s3.client.kora.model.response.HeadObjectResult; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; import static org.mockito.ArgumentMatchers.*; diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ListTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ListTest.java similarity index 81% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ListTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ListTest.java index 8d4b76962..37f2e6df8 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3ListTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3ListTest.java @@ -1,10 +1,10 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import org.assertj.core.api.Assertions; import org.junit.jupiter.api.Test; -import io.koraframework.s3.client.AwsCredentials; -import io.koraframework.s3.client.model.request.ListObjectsArgs; -import io.koraframework.s3.client.model.response.ListBucketResult; +import io.koraframework.s3.client.kora.S3Credentials; +import io.koraframework.s3.client.kora.model.request.ListObjectsArgs; +import io.koraframework.s3.client.kora.model.response.ListBucketResult; import java.util.Iterator; import java.util.List; @@ -20,11 +20,11 @@ public void testList() throws Exception { @S3.Client public interface Client { @S3.List - List getWithPrefix(AwsCredentials creds, @Bucket String bucket, String prefix); + List getWithPrefix(S3Credentials creds, @Bucket String bucket, String prefix); } """); - var creds = AwsCredentials.of("test", "test"); + var creds = S3Credentials.of("test", "test"); var list = List.of(new ListBucketResult.ListBucketItem("test", "test1", "etag", null, null, null, 1L, null, null)); var listBucketResult = new ListBucketResult(null, 1, null, list); @@ -45,11 +45,11 @@ public void testListReturnsListBucketResultWithConstPrefix() throws Exception { @S3.Client public interface Client { @S3.List("const-") - ListBucketResult listConst(AwsCredentials creds, @Bucket String bucket); + ListBucketResult listConst(S3Credentials creds, @Bucket String bucket); } """); - var creds = AwsCredentials.of("a", "b"); + var creds = S3Credentials.of("a", "b"); var items = List.of(new ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 10L, null, null)); var res = new ListBucketResult(null, 1, null, items); @@ -66,14 +66,14 @@ public interface Client { @Test public void testIteratorStringLazyPages() { var client = this.compile(""" - import io.koraframework.s3.client.model.request.ListObjectsArgs;@S3.Client + @S3.Client public interface Client { @S3.List - Iterator iteratorStrings(AwsCredentials creds, @Bucket String bucket, ListObjectsArgs args); + Iterator iteratorStrings(S3Credentials creds, @Bucket String bucket, ListObjectsArgs args); } """); - var creds = AwsCredentials.of("x", "y"); + var creds = S3Credentials.of("x", "y"); var item1 = new ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 1L, null, null); var item2 = new ListBucketResult.ListBucketItem("b", "k2", "etag", null, null, null, 2L, null, null); @@ -94,14 +94,14 @@ public interface Client { @Test public void testIteratorItemsLazyPages() { var client = this.compile(""" - import io.koraframework.s3.client.model.request.ListObjectsArgs;@S3.Client + @S3.Client public interface Client { @S3.List - Iterator iteratorItems(AwsCredentials creds, @Bucket String bucket, ListObjectsArgs args); + Iterator iteratorItems(S3Credentials creds, @Bucket String bucket, ListObjectsArgs args); } """); - var creds = AwsCredentials.of("x", "y"); + var creds = S3Credentials.of("x", "y"); var item1 = new ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 1L, null, null); var item2 = new ListBucketResult.ListBucketItem("b", "k2", "etag", null, null, null, 2L, null, null); @@ -125,11 +125,11 @@ public void testListItemsMappingWithTemplatePrefix() throws Exception { @S3.Client public interface Client { @S3.List("pre-{prefix}") - List items(AwsCredentials creds, @Bucket String bucket, String prefix); + List items(S3Credentials creds, @Bucket String bucket, String prefix); } """); - var creds = AwsCredentials.of("u", "v"); + var creds = S3Credentials.of("u", "v"); var items = List.of(new ListBucketResult.ListBucketItem("b", "item-key", "etag", null, null, null, 5L, null, null)); var res = new ListBucketResult(null, 1, null, items); diff --git a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3PutTest.java b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3PutTest.java similarity index 93% rename from experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3PutTest.java rename to experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3PutTest.java index 003b85431..e2cb5e0cd 100644 --- a/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/annotation/processor/S3PutTest.java +++ b/experimental/s3-client-annotation-processor/src/test/java/io/koraframework/s3/client/kora/annotation/processor/S3PutTest.java @@ -1,10 +1,10 @@ -package io.koraframework.s3.client.annotation.processor; +package io.koraframework.s3.client.kora.annotation.processor; import org.junit.jupiter.api.Test; -import io.koraframework.s3.client.$S3ClientConfig_UploadConfig_ConfigValueExtractor; -import io.koraframework.s3.client.S3Client; -import io.koraframework.s3.client.model.response.UploadedPart; +import io.koraframework.s3.client.kora.$S3ClientConfig_UploadConfig_ConfigValueExtractor; +import io.koraframework.s3.client.kora.S3Client; +import io.koraframework.s3.client.kora.model.response.UploadedPart; import java.io.ByteArrayInputStream; import java.nio.ByteBuffer; @@ -61,7 +61,7 @@ public interface Client { @Test public void testPutWithContentWriter() throws Exception { var client = this.compile(""" - @S3.Client + import io.koraframework.s3.client.kora.S3Client;@S3.Client public interface Client { @S3.Put String put(@S3.Bucket String bucket, String key, S3Client.ContentWriter writer); diff --git a/experimental/s3-client/build.gradle b/experimental/s3-client-kora/build.gradle similarity index 100% rename from experimental/s3-client/build.gradle rename to experimental/s3-client-kora/build.gradle diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/KoraS3ClientModule.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/KoraS3ClientModule.java new file mode 100644 index 000000000..38271eb1a --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/KoraS3ClientModule.java @@ -0,0 +1,54 @@ +package io.koraframework.s3.client.kora; + +import io.koraframework.common.DefaultComponent; +import io.koraframework.common.Tag; +import io.koraframework.config.common.ConfigValue; +import io.koraframework.config.common.extractor.ConfigValueExtractionException; +import io.koraframework.config.common.extractor.ConfigValueExtractor; +import io.koraframework.http.client.common.HttpClient; +import io.koraframework.s3.client.kora.impl.KoraS3Client; +import io.koraframework.s3.client.kora.telemetry.DefaultS3ClientTelemetryFactory; +import io.koraframework.s3.client.kora.telemetry.S3ClientTelemetryFactory; +import io.micrometer.core.instrument.MeterRegistry; +import io.opentelemetry.api.trace.Tracer; +import org.jspecify.annotations.Nullable; + +public interface KoraS3ClientModule { + + default S3ClientTelemetryFactory defaultKoraS3ClientTelemetryFactory(@Nullable Tracer tracer, + @Nullable MeterRegistry meterRegistry) { + return new DefaultS3ClientTelemetryFactory(tracer, meterRegistry); + } + + @Tag(S3Client.class) + @DefaultComponent + default HttpClient defaultKoraS3httpClient(HttpClient client) { + return client; + } + + default S3ClientFactory defaultKoraS3ClientFactory(@Tag(S3Client.class) HttpClient client, + S3ClientTelemetryFactory telemetryFactory) { + return config -> { + var telemetry = telemetryFactory.get(config.telemetry()); + return new KoraS3Client(client, config, telemetry); + }; + } + + default ConfigValueExtractor koraS3CredentialsValueExtractor() { + return src -> { + if (src instanceof ConfigValue.NullValue) { + return null; + } + var configObject = src.asObject(); + var accessKey = configObject.get("accessKey"); + if (accessKey.isNull()) { + throw ConfigValueExtractionException.missingValue(accessKey); + } + var secretKey = configObject.get("secretKey"); + if (secretKey.isNull()) { + throw ConfigValueExtractionException.missingValue(secretKey); + } + return S3Credentials.of(accessKey.asString(), secretKey.asString()); + }; + } +} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3Client.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Client.java similarity index 71% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/S3Client.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Client.java index d8476f8b9..702c3bfd2 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3Client.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Client.java @@ -1,9 +1,9 @@ -package io.koraframework.s3.client; +package io.koraframework.s3.client.kora; +import io.koraframework.s3.client.kora.exception.S3ClientException; +import io.koraframework.s3.client.kora.model.request.*; +import io.koraframework.s3.client.kora.model.response.*; import org.jspecify.annotations.Nullable; -import io.koraframework.s3.client.exception.S3ClientException; -import io.koraframework.s3.client.model.request.*; -import io.koraframework.s3.client.model.response.*; import java.io.Closeable; import java.io.IOException; @@ -20,23 +20,23 @@ public interface S3Client { * @param bucket The bucket name containing the object. * @param key Key of the object to get. * @return object metadata or null if required is false and object is not found - * @throws io.koraframework.s3.client.exception.S3ClientResponseException on 404 if required is true + * @throws io.koraframework.s3.client.kora.exception.S3ClientResponseException on 404 if required is true * @see HeadObject */ @Nullable - HeadObjectResult headObject(AwsCredentials credentials, String bucket, String key, @Nullable HeadObjectArgs args, boolean required) throws S3ClientException; + HeadObjectResult headObject(S3Credentials credentials, String bucket, String key, @Nullable HeadObjectArgs args, boolean required) throws S3ClientException; /** * @see #headObject */ - default HeadObjectResult headObject(AwsCredentials credentials, String bucket, String key) throws S3ClientException { + default HeadObjectResult headObject(S3Credentials credentials, String bucket, String key) throws S3ClientException { return Objects.requireNonNull(this.headObject(credentials, bucket, key, null, true)); } /** * @see #headObject */ - default HeadObjectResult headObject(AwsCredentials credentials, String bucket, String key, @Nullable HeadObjectArgs args) throws S3ClientException { + default HeadObjectResult headObject(S3Credentials credentials, String bucket, String key, @Nullable HeadObjectArgs args) throws S3ClientException { return Objects.requireNonNull(this.headObject(credentials, bucket, key, null, true)); } @@ -44,7 +44,7 @@ default HeadObjectResult headObject(AwsCredentials credentials, String bucket, S * @see #headObject */ @Nullable - default HeadObjectResult headObjectOptional(AwsCredentials credentials, String bucket, String key) throws S3ClientException { + default HeadObjectResult headObjectOptional(S3Credentials credentials, String bucket, String key) throws S3ClientException { return this.headObject(credentials, bucket, key, null, false); } @@ -57,26 +57,26 @@ default HeadObjectResult headObjectOptional(AwsCredentials credentials, String b * @see GetObject */ @Nullable - GetObjectResult getObject(AwsCredentials credentials, String bucket, String key, @Nullable GetObjectArgs args, boolean required); + GetObjectResult getObject(S3Credentials credentials, String bucket, String key, @Nullable GetObjectArgs args, boolean required); /** * @see #getObject */ - default GetObjectResult getObject(AwsCredentials credentials, String bucket, String key, @Nullable GetObjectArgs args) { + default GetObjectResult getObject(S3Credentials credentials, String bucket, String key, @Nullable GetObjectArgs args) { return Objects.requireNonNull(this.getObject(credentials, bucket, key, args, true)); } /** * @see #getObject */ - default GetObjectResult getObject(AwsCredentials credentials, String bucket, String key) { + default GetObjectResult getObject(S3Credentials credentials, String bucket, String key) { return Objects.requireNonNull(this.getObject(credentials, bucket, key, null, true)); } /** * @see #getObject */ - default GetObjectResult getObjectOptional(AwsCredentials credentials, String bucket, String key) { + default GetObjectResult getObjectOptional(S3Credentials credentials, String bucket, String key) { return this.getObject(credentials, bucket, key, null, false); } @@ -89,12 +89,12 @@ default GetObjectResult getObjectOptional(AwsCredentials credentials, String buc * @param key Key name of the object to delete. * @see DeleteObject */ - void deleteObject(AwsCredentials credentials, String bucket, String key, @Nullable DeleteObjectArgs args) throws S3ClientException; + void deleteObject(S3Credentials credentials, String bucket, String key, @Nullable DeleteObjectArgs args) throws S3ClientException; /** * @see #deleteObject */ - default void deleteObject(AwsCredentials credentials, String bucket, String key) throws S3ClientException { + default void deleteObject(S3Credentials credentials, String bucket, String key) throws S3ClientException { this.deleteObject(credentials, bucket, key, null); } @@ -111,7 +111,7 @@ default void deleteObject(AwsCredentials credentials, String bucket, String key) * @param keys The objects to delete. * @see DeleteObjects */ - void deleteObjects(AwsCredentials credentials, String bucket, List keys) throws S3ClientException; + void deleteObjects(S3Credentials credentials, String bucket, List keys) throws S3ClientException; /** @@ -125,12 +125,12 @@ default void deleteObject(AwsCredentials credentials, String bucket, String key) * @return the ETag of the uploaded object * @see PutObject */ - String putObject(AwsCredentials credentials, String bucket, String key, @Nullable PutObjectArgs args, byte[] data, int off, int len) throws S3ClientException; + String putObject(S3Credentials credentials, String bucket, String key, @Nullable PutObjectArgs args, byte[] data, int off, int len) throws S3ClientException; /** - * @see #putObject(AwsCredentials, String, String, PutObjectArgs, byte[], int, int) + * @see #putObject(S3Credentials, String, String, PutObjectArgs, byte[], int, int) */ - default String putObject(AwsCredentials credentials, String bucket, String key, byte[] data, int off, int len) throws S3ClientException { + default String putObject(S3Credentials credentials, String bucket, String key, byte[] data, int off, int len) throws S3ClientException { return this.putObject(credentials, bucket, key, null, data, off, len); } @@ -143,12 +143,12 @@ default String putObject(AwsCredentials credentials, String bucket, String key, * @return the ETag of the uploaded object * @see PutObject */ - String putObject(AwsCredentials credentials, String bucket, String key, @Nullable PutObjectArgs args, ContentWriter contentWriter) throws S3ClientException; + String putObject(S3Credentials credentials, String bucket, String key, @Nullable PutObjectArgs args, ContentWriter contentWriter) throws S3ClientException; /** - * @see #putObject(AwsCredentials, String, String, PutObjectArgs, ContentWriter) + * @see #putObject(S3Credentials, String, String, PutObjectArgs, ContentWriter) */ - default String putObject(AwsCredentials credentials, String bucket, String key, ContentWriter contentWriter) throws S3ClientException { + default String putObject(S3Credentials credentials, String bucket, String key, ContentWriter contentWriter) throws S3ClientException { return this.putObject(credentials, bucket, key, null, contentWriter); } @@ -164,7 +164,7 @@ default String putObject(AwsCredentials credentials, String bucket, String key, * @param bucket The name of the bucket to which the multipart upload was initiated. * @see ListMultipartUploads */ - ListMultipartUploadsResult listMultipartUploads(AwsCredentials credentials, String bucket, @Nullable ListMultipartUploadsArgs args) throws S3ClientException; + ListMultipartUploadsResult listMultipartUploads(S3Credentials credentials, String bucket, @Nullable ListMultipartUploadsArgs args) throws S3ClientException; /** * Returns some or all (up to 1,000) of the objects in a bucket with each request. @@ -172,12 +172,12 @@ default String putObject(AwsCredentials credentials, String bucket, String key, * For more information about listing objects, see Listing object keys programmatically in the Amazon S3 User Guide. * To get a list of your buckets, see ListBuckets. */ - ListBucketResult listObjectsV2(AwsCredentials credentials, String bucket, @Nullable ListObjectsArgs args); + ListBucketResult listObjectsV2(S3Credentials credentials, String bucket, @Nullable ListObjectsArgs args); /** - * @see #listObjectsV2(AwsCredentials, String, ListObjectsArgs) + * @see #listObjectsV2(S3Credentials, String, ListObjectsArgs) */ - Iterator listObjectsV2Iterator(AwsCredentials credentials, String bucket, @Nullable ListObjectsArgs args); + Iterator listObjectsV2Iterator(S3Credentials credentials, String bucket, @Nullable ListObjectsArgs args); /** * This action initiates a multipart upload and returns an upload ID. @@ -191,12 +191,12 @@ default String putObject(AwsCredentials credentials, String bucket, String key, * @return ID for the initiated multipart upload. * @see createMultipartUpload */ - String createMultipartUpload(AwsCredentials credentials, String bucket, String key, @Nullable CreateMultipartUploadArgs args) throws S3ClientException; + String createMultipartUpload(S3Credentials credentials, String bucket, String key, @Nullable CreateMultipartUploadArgs args) throws S3ClientException; /** * @see #createMultipartUpload */ - default String createMultipartUpload(AwsCredentials credentials, String bucket, String key) throws S3ClientException { + default String createMultipartUpload(S3Credentials credentials, String bucket, String key) throws S3ClientException { return this.createMultipartUpload(credentials, bucket, key, null); } @@ -214,12 +214,12 @@ default String createMultipartUpload(AwsCredentials credentials, String bucket, * @return Entity tag for the uploaded object. * @see UploadPart */ - UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, @Nullable UploadPartArgs args, byte[] data, int off, int len) throws S3ClientException; + UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, @Nullable UploadPartArgs args, byte[] data, int off, int len) throws S3ClientException; /** - * @see #uploadPart(AwsCredentials, String, String, String, int, UploadPartArgs, byte[], int, int) + * @see #uploadPart(S3Credentials, String, String, String, int, UploadPartArgs, byte[], int, int) */ - default UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, byte[] data, int off, int len) throws S3ClientException { + default UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, byte[] data, int off, int len) throws S3ClientException { return this.uploadPart(credentials, bucket, key, uploadId, partNumber, null, data, off, len); } @@ -234,12 +234,12 @@ default UploadedPart uploadPart(AwsCredentials credentials, String bucket, Strin * @return Entity tag for the uploaded object. * @see UploadPart */ - UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, @Nullable UploadPartArgs args, ContentWriter contentWriter) throws S3ClientException; + UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, @Nullable UploadPartArgs args, ContentWriter contentWriter) throws S3ClientException; /** - * @see #uploadPart(AwsCredentials, String, String, String, int, UploadPartArgs, ContentWriter) + * @see #uploadPart(S3Credentials, String, String, String, int, UploadPartArgs, ContentWriter) */ - default UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, ContentWriter contentWriter) throws S3ClientException { + default UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, ContentWriter contentWriter) throws S3ClientException { return this.uploadPart(credentials, bucket, key, uploadId, partNumber, null, contentWriter); } @@ -255,9 +255,9 @@ default UploadedPart uploadPart(AwsCredentials credentials, String bucket, Strin * @param uploadId Upload ID identifying the multipart upload whose parts are being listed. * @see ListParts */ - ListPartsResult listParts(AwsCredentials credentials, String bucket, String key, String uploadId, @Nullable ListPartsArgs args) throws S3ClientException; + ListPartsResult listParts(S3Credentials credentials, String bucket, String key, String uploadId, @Nullable ListPartsArgs args) throws S3ClientException; - default ListPartsResult listParts(AwsCredentials credentials, String bucket, String key, String uploadId, @Nullable Integer maxParts, @Nullable Integer partNumberMarker) throws S3ClientException { + default ListPartsResult listParts(S3Credentials credentials, String bucket, String key, String uploadId, @Nullable Integer maxParts, @Nullable Integer partNumberMarker) throws S3ClientException { return this.listParts(credentials, bucket, key, uploadId, new ListPartsArgs() .setMaxParts(maxParts) .setPartNumberMarker(partNumberMarker) @@ -276,12 +276,12 @@ default ListPartsResult listParts(AwsCredentials credentials, String bucket, Str * @param uploadId Upload ID that identifies the multipart upload. * @see AbortMultipartUpload */ - void abortMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId, @Nullable AbortMultipartUploadArgs args) throws S3ClientException; + void abortMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId, @Nullable AbortMultipartUploadArgs args) throws S3ClientException; /** - * @see #abortMultipartUpload(AwsCredentials, String, String, String, AbortMultipartUploadArgs) + * @see #abortMultipartUpload(S3Credentials, String, String, String, AbortMultipartUploadArgs) */ - default void abortMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId) throws S3ClientException { + default void abortMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId) throws S3ClientException { this.abortMultipartUpload(credentials, bucket, key, uploadId, null); } @@ -295,12 +295,12 @@ default void abortMultipartUpload(AwsCredentials credentials, String bucket, Str * @return the ETag of the uploaded object * @see CompleteMultipartUpload */ - String completeMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId, List parts, @Nullable CompleteMultipartUploadArgs args) throws S3ClientException; + String completeMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId, List parts, @Nullable CompleteMultipartUploadArgs args) throws S3ClientException; /** * @see #completeMultipartUpload */ - default String completeMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId, List parts) throws S3ClientException { + default String completeMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId, List parts) throws S3ClientException { return this.completeMultipartUpload(credentials, bucket, key, uploadId, parts, null); } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfig.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfig.java similarity index 92% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfig.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfig.java index a638e49a4..a4b8d470b 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfig.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfig.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client; +package io.koraframework.s3.client.kora; import io.koraframework.common.util.Size; import io.koraframework.config.common.annotation.ConfigValueExtractor; -import io.koraframework.s3.client.telemetry.S3ClientTelemetryConfig; +import io.koraframework.s3.client.kora.telemetry.S3ClientTelemetryConfig; import java.time.Duration; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfigWithCredentials.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfigWithCredentials.java similarity index 69% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfigWithCredentials.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfigWithCredentials.java index 1ddad420e..be0116d21 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientConfigWithCredentials.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientConfigWithCredentials.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client; +package io.koraframework.s3.client.kora; import io.koraframework.config.common.annotation.ConfigValueExtractor; @ConfigValueExtractor public interface S3ClientConfigWithCredentials extends S3ClientConfig { - AwsCredentials credentials(); + S3Credentials credentials(); } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientFactory.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientFactory.java similarity index 66% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientFactory.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientFactory.java index 8ea861fef..f967d5281 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientFactory.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3ClientFactory.java @@ -1,5 +1,6 @@ -package io.koraframework.s3.client; +package io.koraframework.s3.client.kora; public interface S3ClientFactory { + S3Client create(S3ClientConfig config); } diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Credentials.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Credentials.java new file mode 100644 index 000000000..a89ee8134 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/S3Credentials.java @@ -0,0 +1,14 @@ +package io.koraframework.s3.client.kora; + +import io.koraframework.s3.client.kora.impl.S3RequestSigner; + +public interface S3Credentials { + + String accessKey(); + + String secretKey(); + + static S3Credentials of(String accessKey, String secretKey) { + return new S3RequestSigner(accessKey, secretKey); + } +} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/annotation/S3.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/annotation/S3.java similarity index 84% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/annotation/S3.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/annotation/S3.java index ccaadb971..e97c104cb 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/annotation/S3.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/annotation/S3.java @@ -1,14 +1,14 @@ -package io.koraframework.s3.client.annotation; - -import io.koraframework.s3.client.AwsCredentials; -import io.koraframework.s3.client.S3ClientConfig; -import io.koraframework.s3.client.exception.S3ClientNoSuchKeyException; -import io.koraframework.s3.client.model.request.DeleteObjectArgs; -import io.koraframework.s3.client.model.request.GetObjectArgs; -import io.koraframework.s3.client.model.request.HeadObjectArgs; -import io.koraframework.s3.client.model.request.PutObjectArgs; -import io.koraframework.s3.client.model.response.GetObjectResult; -import io.koraframework.s3.client.model.response.HeadObjectResult; +package io.koraframework.s3.client.kora.annotation; + +import io.koraframework.s3.client.kora.S3ClientConfig; +import io.koraframework.s3.client.kora.S3Credentials; +import io.koraframework.s3.client.kora.exception.S3ClientNoSuchKeyException; +import io.koraframework.s3.client.kora.model.request.DeleteObjectArgs; +import io.koraframework.s3.client.kora.model.request.GetObjectArgs; +import io.koraframework.s3.client.kora.model.request.HeadObjectArgs; +import io.koraframework.s3.client.kora.model.request.PutObjectArgs; +import io.koraframework.s3.client.kora.model.response.GetObjectResult; +import io.koraframework.s3.client.kora.model.response.HeadObjectResult; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; @@ -74,7 +74,7 @@ /** * Marks get operation in a client interface.
* Possible return values are {@link GetObjectResult} and byte[].
- * Possible arguments are path template parameters, {@link AwsCredentials}, {@link S3.Bucket} annotated string and {@link GetObjectArgs}
+ * Possible arguments are path template parameters, {@link S3Credentials}, {@link S3.Bucket} annotated string and {@link GetObjectArgs}
* If no object found method will return null if marked with @Nullable and throw {@link S3ClientNoSuchKeyException} otherwize. */ @Target({ElementType.METHOD}) @@ -102,7 +102,7 @@ /** * Marks head operation in a client interface.
* Possible return type is {@link HeadObjectResult}.
- * Possible arguments are path template parameters, {@link AwsCredentials}, {@link S3.Bucket} annotated string and {@link HeadObjectArgs}
+ * Possible arguments are path template parameters, {@link S3Credentials}, {@link S3.Bucket} annotated string and {@link HeadObjectArgs}
* If no object found method will return null if marked with @Nullable and throw {@link S3ClientNoSuchKeyException} otherwise. */ @Target({ElementType.METHOD}) @@ -133,7 +133,7 @@ * This operation enumerates objects in a bucket using an optional prefix or a fully specified set of list arguments. * Possible return types include a paged result model ListBucketResult, List<String>, Iterator<String>, * List<ListBucketResult.ListBucketItem>, Iterator<ListBucketResult.ListBucketItem>. - * Possible method arguments are path template parameters, {@link AwsCredentials}, {@link S3.Bucket} annotated string + * Possible method arguments are path template parameters, {@link S3Credentials}, {@link S3.Bucket} annotated string * and a ListObjectsArgs argument that encapsulates list options (prefix, delimiter, maxKeys, continuationToken, etc.). * When returning an iterator the implementation will lazily fetch subsequent pages. */ @@ -169,7 +169,7 @@ /** * Marks put (upload) operation in a client interface.
* Marked method should use void or string as return type, string represents returned ETag.
- * Possible arguments are path template parameters, {@link AwsCredentials}, {@link S3.Bucket} annotated string, {@link PutObjectArgs} + * Possible arguments are path template parameters, {@link S3Credentials}, {@link S3.Bucket} annotated string, {@link PutObjectArgs} * and a request body. Supported body types include byte[], java.nio.ByteBuffer, java.io.InputStream and a ContentWriter provided by the client.
* InputStream body will lead to multipart upload with buffer size specified in {@link S3ClientConfig.UploadConfig#partSize()}. */ @@ -198,7 +198,7 @@ /** * Marks delete operation in a client interface.
* Marked method should use void as return type.
- * Possible arguments are path template parameters, {@link AwsCredentials}, {@link S3.Bucket} annotated string and {@link DeleteObjectArgs}
+ * Possible arguments are path template parameters, {@link S3Credentials}, {@link S3.Bucket} annotated string and {@link DeleteObjectArgs}
*/ @Target({ElementType.METHOD}) @Retention(RetentionPolicy.CLASS) diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientDeleteException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientDeleteException.java new file mode 100644 index 000000000..cf90d97ba --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientDeleteException.java @@ -0,0 +1,26 @@ +package io.koraframework.s3.client.kora.exception; + +import io.koraframework.s3.client.kora.impl.xml.DeleteObjectsResult; + +import java.util.List; +import java.util.stream.Collectors; + +public class S3ClientDeleteException extends S3ClientException { + + private final List errors; + + public S3ClientDeleteException(List errors) { + this.errors = errors; + } + + public List getErrors() { + return errors; + } + + @Override + public String getMessage() { + return "Delete failed for keyes due to: " + errors.stream() + .map(e -> "- Failed with code '" + e.code() + "' due to: " + e.message()) + .collect(Collectors.joining("\n", "\n", "")); + } +} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientErrorException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientErrorException.java similarity index 95% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientErrorException.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientErrorException.java index e10356698..55503a516 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientErrorException.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientErrorException.java @@ -1,8 +1,9 @@ -package io.koraframework.s3.client.exception; +package io.koraframework.s3.client.kora.exception; import org.jspecify.annotations.Nullable; public class S3ClientErrorException extends S3ClientResponseException { + private final String errorCode; private final String errorMessage; @Nullable diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientException.java similarity index 79% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientException.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientException.java index 051b59f53..aac840a43 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientException.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientException.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.exception; +package io.koraframework.s3.client.kora.exception; public abstract class S3ClientException extends RuntimeException { - public S3ClientException() { - } + + public S3ClientException() {} public S3ClientException(String message) { super(message); diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientNoSuchKeyException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientNoSuchKeyException.java similarity index 85% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientNoSuchKeyException.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientNoSuchKeyException.java index 9f837752d..7bf9453bf 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientNoSuchKeyException.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientNoSuchKeyException.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.exception; +package io.koraframework.s3.client.kora.exception; import org.jspecify.annotations.Nullable; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientResponseException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientResponseException.java similarity index 92% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientResponseException.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientResponseException.java index b8565d0d2..b244aee89 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientResponseException.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientResponseException.java @@ -1,6 +1,7 @@ -package io.koraframework.s3.client.exception; +package io.koraframework.s3.client.kora.exception; public class S3ClientResponseException extends S3ClientException { + private final int httpCode; public S3ClientResponseException(int httpCode) { diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientUnknownException.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientUnknownException.java similarity index 79% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientUnknownException.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientUnknownException.java index 2531156f1..b2533254d 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientUnknownException.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/exception/S3ClientUnknownException.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.exception; +package io.koraframework.s3.client.kora.exception; public final class S3ClientUnknownException extends S3ClientException { - public S3ClientUnknownException() { - } + + public S3ClientUnknownException() {} public S3ClientUnknownException(String message) { super(message); diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/DigestUtils.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/DigestUtils.java similarity index 95% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/DigestUtils.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/DigestUtils.java index 09c29a276..e70d65b25 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/DigestUtils.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/DigestUtils.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl; +package io.koraframework.s3.client.kora.impl; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -9,7 +9,9 @@ import java.util.Base64; import java.util.HexFormat; -public class DigestUtils { +public final class DigestUtils { + + private DigestUtils() {} public static MessageDigest md5() { try { diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/KnownSizeAwsChunkedHttpBody.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KnownSizeAwsChunkedHttpBody.java similarity index 79% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/KnownSizeAwsChunkedHttpBody.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KnownSizeAwsChunkedHttpBody.java index 1da991d62..eb83ace25 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/KnownSizeAwsChunkedHttpBody.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KnownSizeAwsChunkedHttpBody.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.impl; +package io.koraframework.s3.client.kora.impl; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.body.HttpBodyOutput; -import io.koraframework.s3.client.S3Client; +import io.koraframework.s3.client.kora.S3Client; +import org.jspecify.annotations.Nullable; import java.io.IOException; import java.io.OutputStream; @@ -12,7 +12,7 @@ import java.time.ZonedDateTime; import java.util.Base64; -class KnownSizeAwsChunkedHttpBody implements HttpBodyOutput { +final class KnownSizeAwsChunkedHttpBody implements HttpBodyOutput { // ;chunk-signature=b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9\r\n\r\n private static final int AWS_CHUNK_SUFFIX_SIZE = 85; // 0;chunk-signature=b6c6ea8a5354eaf15b3cb7646744f4275b71ea724fed81ceb9323e279d449df9\r\n\r\n @@ -21,7 +21,7 @@ class KnownSizeAwsChunkedHttpBody implements HttpBodyOutput { // x-amz-trailer-signature:63bddb248ad2590c92712055f51b8e78ab024eead08276b24f010b0efd74843f private static final int SHA256_TRAILER_SIZE = 159; - private final AwsRequestSigner signer; + private final S3RequestSigner signer; private final S3Client.ContentWriter contentWriter; private final String contentType; private final long contentLength; @@ -40,12 +40,12 @@ static long calculateFullBodyLength(long uploadChunkSize, String uploadChunkSize var trailer = sha256Base64 == null ? SHA256_TRAILER_SIZE : 0; return fullChunks * fullChunkSize - + lastChunkSize - + trailer - + AWS_CHUNK_ZERO_HEADER_SIZE; + + lastChunkSize + + trailer + + AWS_CHUNK_ZERO_HEADER_SIZE; } - public KnownSizeAwsChunkedHttpBody(AwsRequestSigner signer, String region, int uploadChunkSize, String contentType, String rqSignature, S3Client.ContentWriter contentWriter, @Nullable String sha256Base64) { + public KnownSizeAwsChunkedHttpBody(S3RequestSigner signer, String region, int uploadChunkSize, String contentType, String rqSignature, S3Client.ContentWriter contentWriter, @Nullable String sha256Base64) { this.region = region; this.signer = signer; this.contentWriter = contentWriter; @@ -150,74 +150,74 @@ public void close() throws IOException { private String processChunk(String previousSignature, byte[] buf, int read, OutputStream os) throws IOException { - var amzDate = this.date.format(AwsRequestSigner.AMZ_DATE_FORMAT); - var signerDate = this.date.format(AwsRequestSigner.SIGNER_DATE_FORMAT); + var amzDate = this.date.format(S3RequestSigner.AMZ_DATE_FORMAT); + var signerDate = this.date.format(S3RequestSigner.SIGNER_DATE_FORMAT); var scope = signerDate + "/" + this.region + "/s3/aws4_request"; var chunkContentSha = DigestUtils.sha256(buf, 0, read).hex(); var stringToSign = "AWS4-HMAC-SHA256-PAYLOAD" + "\n" - + amzDate + "\n" - + scope + "\n" - + previousSignature + "\n" - + AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX + "\n" - + chunkContentSha; + + amzDate + "\n" + + scope + "\n" + + previousSignature + "\n" + + S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX + "\n" + + chunkContentSha; var signature = this.signer.awsSign(this.region, signerDate, stringToSign); os.write(Integer.toHexString(read).getBytes(StandardCharsets.US_ASCII)); os.write(";chunk-signature=".getBytes(StandardCharsets.US_ASCII)); os.write(signature.getBytes(StandardCharsets.US_ASCII)); - os.write(AwsRequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); os.write(buf, 0, read); - os.write(AwsRequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); return signature; } private String processFinalChunk(String previousSignature, OutputStream os) throws IOException { - var amzDate = this.date.format(AwsRequestSigner.AMZ_DATE_FORMAT); - var signerDate = this.date.format(AwsRequestSigner.SIGNER_DATE_FORMAT); + var amzDate = this.date.format(S3RequestSigner.AMZ_DATE_FORMAT); + var signerDate = this.date.format(S3RequestSigner.SIGNER_DATE_FORMAT); var scope = signerDate + "/" + this.region + "/s3/aws4_request"; var stringToSign = "AWS4-HMAC-SHA256-PAYLOAD" + "\n" - + amzDate + "\n" - + scope + "\n" - + previousSignature + "\n" - + AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX + "\n" - + AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX; + + amzDate + "\n" + + scope + "\n" + + previousSignature + "\n" + + S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX + "\n" + + S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX; var signature = this.signer.awsSign(this.region, signerDate, stringToSign); os.write("0".getBytes(StandardCharsets.US_ASCII)); os.write(";chunk-signature=".getBytes(StandardCharsets.US_ASCII)); os.write(signature.getBytes(StandardCharsets.US_ASCII)); - os.write(AwsRequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); return signature; } private String processTrailer(String previousSignature, String sha256, OutputStream os) throws IOException { - var amzDate = this.date.format(AwsRequestSigner.AMZ_DATE_FORMAT); - var signerDate = this.date.format(AwsRequestSigner.SIGNER_DATE_FORMAT); + var amzDate = this.date.format(S3RequestSigner.AMZ_DATE_FORMAT); + var signerDate = this.date.format(S3RequestSigner.SIGNER_DATE_FORMAT); var scope = signerDate + "/" + this.region + "/s3/aws4_request"; var trailerBytes = ("x-amz-checksum-sha256:" + sha256 + "\n").getBytes(StandardCharsets.US_ASCII); var chunkContentSha = DigestUtils.sha256(trailerBytes, 0, trailerBytes.length).hex(); var stringToSign = "AWS4-HMAC-SHA256-TRAILER" + "\n" - + amzDate + "\n" - + scope + "\n" - + previousSignature + "\n" - + chunkContentSha; + + amzDate + "\n" + + scope + "\n" + + previousSignature + "\n" + + chunkContentSha; var signature = this.signer.awsSign(this.region, signerDate, stringToSign); os.write(trailerBytes); - os.write(AwsRequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); os.write("x-amz-trailer-signature:".getBytes(StandardCharsets.US_ASCII)); os.write(signature.getBytes(StandardCharsets.US_ASCII)); - os.write(AwsRequestSigner.CLRF_BYTES); - os.write(AwsRequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); + os.write(S3RequestSigner.CLRF_BYTES); return signature; } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/S3ClientImpl.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KoraS3Client.java similarity index 84% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/S3ClientImpl.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KoraS3Client.java index 36c51dfce..5c866d514 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/S3ClientImpl.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/KoraS3Client.java @@ -1,6 +1,5 @@ -package io.koraframework.s3.client.impl; +package io.koraframework.s3.client.kora.impl; -import org.jspecify.annotations.Nullable; import io.koraframework.common.telemetry.Observation; import io.koraframework.http.client.common.HttpClient; import io.koraframework.http.client.common.request.HttpClientRequest; @@ -8,18 +7,19 @@ import io.koraframework.http.common.body.HttpBody; import io.koraframework.http.common.body.HttpBodyInput; import io.koraframework.http.common.header.HttpHeaders; -import io.koraframework.s3.client.AwsCredentials; -import io.koraframework.s3.client.S3Client; -import io.koraframework.s3.client.S3ClientConfig; -import io.koraframework.s3.client.exception.*; -import io.koraframework.s3.client.impl.xml.*; -import io.koraframework.s3.client.model.request.*; -import io.koraframework.s3.client.model.response.*; -import io.koraframework.s3.client.model.response.ListBucketResult; -import io.koraframework.s3.client.model.response.ListMultipartUploadsResult; -import io.koraframework.s3.client.model.response.ListMultipartUploadsResult.Upload; -import io.koraframework.s3.client.model.response.ListPartsResult; -import io.koraframework.s3.client.telemetry.S3ClientTelemetry; +import io.koraframework.s3.client.kora.S3Client; +import io.koraframework.s3.client.kora.S3ClientConfig; +import io.koraframework.s3.client.kora.S3Credentials; +import io.koraframework.s3.client.kora.exception.*; +import io.koraframework.s3.client.kora.impl.xml.*; +import io.koraframework.s3.client.kora.model.request.*; +import io.koraframework.s3.client.kora.model.response.*; +import io.koraframework.s3.client.kora.model.response.ListBucketResult; +import io.koraframework.s3.client.kora.model.response.ListMultipartUploadsResult; +import io.koraframework.s3.client.kora.model.response.ListMultipartUploadsResult.Upload; +import io.koraframework.s3.client.kora.model.response.ListPartsResult; +import io.koraframework.s3.client.kora.telemetry.S3ClientTelemetry; +import org.jspecify.annotations.Nullable; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -30,22 +30,23 @@ import java.time.format.DateTimeFormatter; import java.util.*; -public class S3ClientImpl implements S3Client { +public class KoraS3Client implements S3Client { + private final S3ClientTelemetry telemetry; private final HttpClient httpClient; private final S3ClientConfig config; private final UriHelper uriHelper; - public S3ClientImpl(HttpClient httpClient, S3ClientConfig config, S3ClientTelemetry telemetry) { + public KoraS3Client(HttpClient httpClient, S3ClientConfig config, S3ClientTelemetry telemetry) { this.httpClient = httpClient; this.config = config; - this.uriHelper = new UriHelper(config); this.telemetry = telemetry; + this.uriHelper = new UriHelper(config); } @Nullable @Override - public HeadObjectResult headObject(AwsCredentials credentials, String bucket, String key, @Nullable HeadObjectArgs args, boolean required) throws S3ClientException { + public HeadObjectResult headObject(S3Credentials credentials, String bucket, String key, @Nullable HeadObjectArgs args, boolean required) throws S3ClientException { var observation = this.telemetry.observe("HeadObject", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -61,15 +62,15 @@ public HeadObjectResult headObject(AwsCredentials credentials, String bucket, St args.writeHeaders(headers); } var uri = this.uriHelper.uri(bucket, key, queryString); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "HEAD", uri, queryMap, headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "HEAD", uri, queryMap, headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("HEAD", uri, "/{bucket}/{object}", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request)) { @@ -108,7 +109,7 @@ public HeadObjectResult headObject(AwsCredentials credentials, String bucket, St @Nullable @Override - public GetObjectResult getObject(AwsCredentials credentials, String bucket, String key, @Nullable GetObjectArgs args, boolean required) { + public GetObjectResult getObject(S3Credentials credentials, String bucket, String key, @Nullable GetObjectArgs args, boolean required) { var observation = this.telemetry.observe("GetObject", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -124,15 +125,15 @@ public GetObjectResult getObject(AwsCredentials credentials, String bucket, Stri args.writeHeaders(headers); } var uri = this.uriHelper.uri(bucket, key, queryString); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryMap, headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryMap, headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("GET", uri, "/{bucket}/{object}", headers, HttpBody.empty(), this.config.requestTimeout()); try { @@ -168,7 +169,7 @@ public GetObjectResult getObject(AwsCredentials credentials, String bucket, Stri @Override - public void deleteObject(AwsCredentials credentials, String bucket, String key, @Nullable DeleteObjectArgs args) throws S3ClientException { + public void deleteObject(S3Credentials credentials, String bucket, String key, @Nullable DeleteObjectArgs args) throws S3ClientException { var observation = this.telemetry.observe("DeleteObject", bucket); observation.observeKey(key); Observation.scoped(observation) @@ -184,15 +185,15 @@ public void deleteObject(AwsCredentials credentials, String bucket, String key, args.writeHeaders(headers); } var uri = this.uriHelper.uri(bucket, key, queryString); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "DELETE", uri, queryMap, headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "DELETE", uri, queryMap, headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("DELETE", uri, "/{bucket}/{key}", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request); @@ -219,7 +220,7 @@ public void deleteObject(AwsCredentials credentials, String bucket, String key, } @Override - public void deleteObjects(AwsCredentials credentials, String bucket, List keys) throws S3ClientException { + public void deleteObjects(S3Credentials credentials, String bucket, List keys) throws S3ClientException { var observation = this.telemetry.observe("DeleteObjects", bucket); Observation.scoped(observation) .run(() -> { @@ -230,9 +231,9 @@ public void deleteObjects(AwsCredentials credentials, String bucket, List(Map.of("delete", "true")), Map.of("content-md5", bodyMd5), payloadSha256); @@ -271,7 +272,7 @@ public void deleteObjects(AwsCredentials credentials, String bucket, List listObjectsV2Iterator(AwsCredentials credentials, String bucket, @Nullable ListObjectsArgs args) { + public Iterator listObjectsV2Iterator(S3Credentials credentials, String bucket, @Nullable ListObjectsArgs args) { if (args == null) { args = new ListObjectsArgs(); args.maxKeys = 1000; @@ -438,7 +439,7 @@ public ListBucketResult.ListBucketItem next() { } - private ListBucketResult listInternal(AwsCredentials credentials, String bucket, @Nullable ListObjectsArgs args) { + private ListBucketResult listInternal(S3Credentials credentials, String bucket, @Nullable ListObjectsArgs args) { var observation = this.telemetry.observe("ListObjectsV2", bucket); return Observation.scoped(observation) .call(() -> { @@ -459,15 +460,15 @@ private ListBucketResult listInternal(AwsCredentials credentials, String bucket, } var uri = this.uriHelper.uri(bucket, "", pathBuilder.toString()); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryParameters, headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryParameters, headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("GET", uri, "/{bucket}?list", headers, HttpBody.empty(), this.config.requestTimeout()); @@ -478,7 +479,7 @@ private ListBucketResult listInternal(AwsCredentials credentials, String bucket, if (rs.code() == 200) { try (var is = body.asInputStream()) { var bytes = is.readAllBytes(); - var listResult = io.koraframework.s3.client.impl.xml.ListBucketResult.fromXml(new ByteArrayInputStream(bytes)); + var listResult = io.koraframework.s3.client.kora.impl.xml.ListBucketResult.fromXml(new ByteArrayInputStream(bytes)); var result = new ArrayList(listResult.contents() == null ? 0 : listResult.contents().size()); if (listResult.contents() != null) for (var content : listResult.contents()) { var accessor = DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(content.lastModified()); @@ -520,7 +521,7 @@ private ListBucketResult listInternal(AwsCredentials credentials, String bucket, @Override - public String createMultipartUpload(AwsCredentials credentials, String bucket, String key, @Nullable CreateMultipartUploadArgs args) throws S3ClientException { + public String createMultipartUpload(S3Credentials credentials, String bucket, String key, @Nullable CreateMultipartUploadArgs args) throws S3ClientException { var observation = this.telemetry.observe("CreateMultipartUpload", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -532,10 +533,10 @@ public String createMultipartUpload(AwsCredentials credentials, String bucket, S args.writeHeaders(headers); } var uri = this.uriHelper.uri(bucket, key, "uploads=true"); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "POST", uri, new TreeMap<>(Map.of("uploads", "true")), headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "POST", uri, new TreeMap<>(Map.of("uploads", "true")), headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.add("x-amz-checksum-algorithm", "SHA256"); headers.add("x-amz-checksum-type", "COMPOSITE"); @@ -543,7 +544,7 @@ public String createMultipartUpload(AwsCredentials credentials, String bucket, S headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("POST", uri, "/{bucket}?uploads=true", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request); @@ -555,7 +556,7 @@ public String createMultipartUpload(AwsCredentials credentials, String bucket, S observation.observeUploadId(result.uploadId()); return result.uploadId(); } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; @@ -569,15 +570,15 @@ public String createMultipartUpload(AwsCredentials credentials, String bucket, S } @Override - public void abortMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId, @Nullable AbortMultipartUploadArgs args) throws S3ClientException { + public void abortMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId, @Nullable AbortMultipartUploadArgs args) throws S3ClientException { var observation = this.telemetry.observe("AbortMultipartUpload", bucket); observation.observeKey(key); Observation.scoped(observation) .run(() -> { var uri = this.uriHelper.uri(bucket, key, "uploadId=" + uploadId); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); var headersMap = new HashMap(); var headers = HttpHeaders.of(); @@ -585,11 +586,11 @@ public void abortMultipartUpload(AwsCredentials credentials, String bucket, Stri args.writeHeaders(headers); args.writeHeaders(headers); } - var signature = signer.processRequest(this.config.region(), "s3", "DELETE", uri, new TreeMap<>(Map.of("uploadId", uploadId)), headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + var signature = signer.processRequest(this.config.region(), "s3", "DELETE", uri, new TreeMap<>(Map.of("uploadId", uploadId)), headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("DELETE", uri, "/{bucket}/{key}?uploadId={uploadId}", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request); @@ -599,7 +600,7 @@ public void abortMultipartUpload(AwsCredentials credentials, String bucket, Stri if (rs.code() == HttpURLConnection.HTTP_NO_CONTENT) { return; } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; @@ -613,7 +614,7 @@ public void abortMultipartUpload(AwsCredentials credentials, String bucket, Stri } @Override - public String completeMultipartUpload(AwsCredentials credentials, String bucket, String key, String uploadId, List parts, @Nullable CompleteMultipartUploadArgs args) throws S3ClientException { + public String completeMultipartUpload(S3Credentials credentials, String bucket, String key, String uploadId, List parts, @Nullable CompleteMultipartUploadArgs args) throws S3ClientException { var observation = this.telemetry.observe("CompleteMultipartUpload", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -634,9 +635,9 @@ public String completeMultipartUpload(AwsCredentials credentials, String bucket, var xml = completeRequest.toXml(); var sha256 = DigestUtils.sha256(xml, 0, xml.length).hex(); var uri = this.uriHelper.uri(bucket, key, "uploadId=" + uploadId); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); var completeSize = Long.toString(parts.stream().mapToLong(UploadedPart::size).sum()); var headers = HttpHeaders.of(); var headersMap = new HashMap(); @@ -663,7 +664,7 @@ public String completeMultipartUpload(AwsCredentials credentials, String bucket, var result = CompleteMultipartUploadResult.fromXml(body.asInputStream()); return result.etag(); } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; @@ -677,7 +678,7 @@ public String completeMultipartUpload(AwsCredentials credentials, String bucket, } @Override - public ListMultipartUploadsResult listMultipartUploads(AwsCredentials credentials, String bucket, @Nullable ListMultipartUploadsArgs args) throws S3ClientException { + public ListMultipartUploadsResult listMultipartUploads(S3Credentials credentials, String bucket, @Nullable ListMultipartUploadsArgs args) throws S3ClientException { var observation = this.telemetry.observe("ListMultipartUploads", bucket); return Observation.scoped(observation) .call(() -> { @@ -696,15 +697,15 @@ public ListMultipartUploadsResult listMultipartUploads(AwsCredentials credential queryMap.putAll(args.toQueryMap()); } var uri = this.uriHelper.uri(bucket, "", query.toString()); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryMap, Map.of(), AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryMap, Map.of(), S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("GET", uri, "/{bucket}/{object}", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request)) { @@ -712,7 +713,7 @@ public ListMultipartUploadsResult listMultipartUploads(AwsCredentials credential observation.observeAwsRequestId(amxRequestId); observation.observeAwsExtendedId(rs.headers().getFirst("x-amz-id-2")); if (rs.code() == HttpURLConnection.HTTP_OK) { - var xml = io.koraframework.s3.client.impl.xml.ListMultipartUploadsResult.fromXml(rs.body().asInputStream()); + var xml = io.koraframework.s3.client.kora.impl.xml.ListMultipartUploadsResult.fromXml(rs.body().asInputStream()); var uploads = new ArrayList(); for (var upload : xml.uploads()) { uploads.add(new Upload( @@ -728,7 +729,7 @@ public ListMultipartUploadsResult listMultipartUploads(AwsCredentials credential ); } try (var body = rs.body()) { - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } } catch (S3ClientException e) { observation.observeError(e); @@ -744,7 +745,7 @@ public ListMultipartUploadsResult listMultipartUploads(AwsCredentials credential } @Override - public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, UploadPartArgs args, byte[] data, int off, int len) throws S3ClientException { + public UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, UploadPartArgs args, byte[] data, int off, int len) throws S3ClientException { var observation = this.telemetry.observe("UploadPart", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -767,9 +768,9 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String queryParams.put("uploadId", uploadId); var uri = this.uriHelper.uri(bucket, key, "partNumber=" + partNumber + "&uploadId=" + uploadId); var httpBody = HttpBody.of(ByteBuffer.wrap(data, off, len)); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); var signature = signer.processRequest(this.config.region(), "s3", "PUT", uri, queryParams, headersMap, sha256Hex); headers.set("x-amz-date", signature.amzDate()); @@ -790,7 +791,7 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String null, null, null, null, sha256Base64, etag, partNumber, len ); } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; @@ -804,7 +805,7 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String } @Override - public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String key, String uploadId, int partNumber, UploadPartArgs args, ContentWriter contentWriter) throws S3ClientException { + public UploadedPart uploadPart(S3Credentials credentials, String bucket, String key, String uploadId, int partNumber, UploadPartArgs args, ContentWriter contentWriter) throws S3ClientException { var observation = this.telemetry.observe("UploadPart", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -829,9 +830,9 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String queryParams.put("partNumber", Integer.toString(partNumber)); queryParams.put("uploadId", uploadId); var uri = this.uriHelper.uri(bucket, key, "partNumber=" + partNumber + "&uploadId=" + uploadId); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); var signature = signer.processRequest(this.config.region(), "s3", "PUT", uri, queryParams, headersMap, payloadSha256Hex); @@ -860,7 +861,7 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String null, null, null, null, httpBody.sha256(), etag, partNumber, len ); } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; @@ -874,7 +875,7 @@ public UploadedPart uploadPart(AwsCredentials credentials, String bucket, String } @Override - public ListPartsResult listParts(AwsCredentials credentials, String bucket, String key, String uploadId, @Nullable ListPartsArgs args) throws S3ClientException { + public ListPartsResult listParts(S3Credentials credentials, String bucket, String key, String uploadId, @Nullable ListPartsArgs args) throws S3ClientException { var observation = this.telemetry.observe("ListParts", bucket); observation.observeKey(key); return Observation.scoped(observation) @@ -892,15 +893,15 @@ public ListPartsResult listParts(AwsCredentials credentials, String bucket, Stri queryParams.putAll(args.toQueryMap()); } var uri = this.uriHelper.uri(bucket, key, query.toString()); - var signer = credentials instanceof AwsRequestSigner s + var signer = credentials instanceof S3RequestSigner s ? s - : new AwsRequestSigner(credentials.accessKey(), credentials.secretKey()); - var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryParams, headersMap, AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + : new S3RequestSigner(credentials.accessKey(), credentials.secretKey()); + var signature = signer.processRequest(this.config.region(), "s3", "GET", uri, queryParams, headersMap, S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); headers.set("x-amz-date", signature.amzDate()); headers.set("authorization", signature.authorization()); headers.set("host", uri.getAuthority()); - headers.set("x-amz-content-sha256", AwsRequestSigner.EMPTY_PAYLOAD_SHA256_HEX); + headers.set("x-amz-content-sha256", S3RequestSigner.EMPTY_PAYLOAD_SHA256_HEX); var request = HttpClientRequest.of("GET", uri, "/{bucket}/{key}?uploadId={uploadId}", headers, HttpBody.empty(), this.config.requestTimeout()); try (var rs = this.httpClient.execute(request); @@ -908,7 +909,7 @@ public ListPartsResult listParts(AwsCredentials credentials, String bucket, Stri observation.observeAwsRequestId(rs.headers().getFirst("X-Amz-Request-Id")); observation.observeAwsExtendedId(rs.headers().getFirst("x-amz-id-2")); if (rs.code() == HttpURLConnection.HTTP_OK) { - var listPartsResult = io.koraframework.s3.client.impl.xml.ListPartsResult.fromXml(body.asInputStream()); + var listPartsResult = io.koraframework.s3.client.kora.impl.xml.ListPartsResult.fromXml(body.asInputStream()); observation.observeUploadId(listPartsResult.uploadId()); var parts = new ArrayList(listPartsResult.parts().size()); for (var part : listPartsResult.parts()) { @@ -930,7 +931,7 @@ public ListPartsResult listParts(AwsCredentials credentials, String bucket, Stri parts ); } - throw S3ClientImpl.parseS3Exception(rs, body); + throw KoraS3Client.parseS3Exception(rs, body); } catch (S3ClientException e) { observation.observeError(e); throw e; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/AwsRequestSigner.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/S3RequestSigner.java similarity index 88% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/AwsRequestSigner.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/S3RequestSigner.java index 94f4afd94..523cf90dd 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/AwsRequestSigner.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/S3RequestSigner.java @@ -1,6 +1,6 @@ -package io.koraframework.s3.client.impl; +package io.koraframework.s3.client.kora.impl; -import io.koraframework.s3.client.AwsCredentials; +import io.koraframework.s3.client.kora.S3Credentials; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; @@ -13,7 +13,7 @@ import java.time.format.DateTimeFormatter; import java.util.*; -public final class AwsRequestSigner implements AwsCredentials { +public final class S3RequestSigner implements S3Credentials { public static final String EMPTY_PAYLOAD_SHA256_HEX = "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"; public static final SortedMap EMPTY_QUERY = Collections.unmodifiableSortedMap(new TreeMap<>()); public static final ZoneId UTC = ZoneId.of("Z"); @@ -25,7 +25,7 @@ public final class AwsRequestSigner implements AwsCredentials { private final String secretKey; private final Mac secretKeyMac; - public AwsRequestSigner(String accessKey, String secretKey) { + public S3RequestSigner(String accessKey, String secretKey) { this.accessKey = accessKey; this.secretKey = secretKey; @@ -65,8 +65,8 @@ public SignRequestResult processRequest(String region, String service, String me if (additionalHeaders.isEmpty()) { signedHeaders = "host;x-amz-content-sha256;x-amz-date"; canonicalHeadersStr = "host:" + uri.getAuthority() + "\n" - + "x-amz-content-sha256:" + payloadSha256Hex + "\n" - + "x-amz-date:" + amzDate + "\n"; + + "x-amz-content-sha256:" + payloadSha256Hex + "\n" + + "x-amz-date:" + amzDate + "\n"; } else { var headers = new TreeMap(); headers.put("host", uri.getAuthority()); @@ -102,11 +102,11 @@ public SignRequestResult processRequest(String region, String service, String me // SignedHeaders + '\n' + // HexEncode(Hash(RequestPayload)) var canonicalRequest = method + "\n" - + uri.getPath() + "\n" - + canonicalQueryStr + "\n" - + canonicalHeadersStr + "\n" - + signedHeaders + "\n" - + payloadSha256Hex; + + uri.getPath() + "\n" + + canonicalQueryStr + "\n" + + canonicalHeadersStr + "\n" + + signedHeaders + "\n" + + payloadSha256Hex; var signerDate = date.format(SIGNER_DATE_FORMAT); @@ -114,9 +114,9 @@ public SignRequestResult processRequest(String region, String service, String me var canonicalRequestHash = DigestUtils.sha256(canonicalRequest).hex(); var stringToSign = "AWS4-HMAC-SHA256" + "\n" - + amzDate + "\n" - + scope + "\n" - + canonicalRequestHash; + + amzDate + "\n" + + scope + "\n" + + canonicalRequestHash; var signature = this.awsSign(region, signerDate, stringToSign); var authorization = "AWS4-HMAC-SHA256 Credential=" + accessKey + "/" + scope + ", SignedHeaders=" + signedHeaders + ", Signature=" + signature; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/UriHelper.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/UriHelper.java similarity index 92% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/UriHelper.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/UriHelper.java index 1c4b68442..9a8449f03 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/UriHelper.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/UriHelper.java @@ -1,14 +1,15 @@ -package io.koraframework.s3.client.impl; +package io.koraframework.s3.client.kora.impl; +import io.koraframework.s3.client.kora.S3ClientConfig; import org.jspecify.annotations.Nullable; -import io.koraframework.s3.client.S3ClientConfig; import java.net.URI; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.util.Objects; -public class UriHelper { +final class UriHelper { + private final S3ClientConfig.AddressStyle addressStyle; private final String scheme; private final String endpoint; @@ -69,7 +70,6 @@ private String encode(String str) { if (str == null) { return ""; } - return URLEncoder.encode(str, StandardCharsets.UTF_8 - ); + return URLEncoder.encode(str, StandardCharsets.UTF_8); } } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadRequest.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadRequest.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadRequest.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadRequest.java index f83f9d04d..74dad0861 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadRequest.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadRequest.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; @@ -57,7 +57,7 @@ void writeXml(OutputStream os) throws IOException, XMLStreamException { xml.writeAttribute("xmlns", "http://s3.amazonaws.com/doc/2006-03-01/"); for (var part : this.parts) { xml.writeStartElement("Part"); - if (part.checksumCRC32() != null) { + if (part.checksumCRC32() != null) { xml.writeStartElement("ChecksumCRC32"); xml.writeCharacters(part.checksumCRC32()); xml.writeEndElement(); diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResult.java similarity index 95% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResult.java index 1bbea6cdb..32fc1d6ed 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResultSaxHandler.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResultSaxHandler.java index 6b8af1bcb..c4440e672 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/CompleteMultipartUploadResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/CompleteMultipartUploadResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsRequest.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsRequest.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsRequest.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsRequest.java index 3c46aca02..696d5470d 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsRequest.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsRequest.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import javax.xml.stream.XMLOutputFactory; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResult.java similarity index 60% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResult.java index f0fe96e10..c6f6ed9e1 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; @@ -10,14 +10,16 @@ import java.util.List; public record DeleteObjectsResult(List deleted, List errors) { - public record Deleted(@Nullable Boolean deleteMarker, @Nullable String deleteMarkerVersionId, String key, @Nullable String versionId) {} - - public record Error( - String code, - String key, - String message, - @Nullable String versionId - ) {} + + public record Deleted(@Nullable Boolean deleteMarker, + @Nullable String deleteMarkerVersionId, + String key, + @Nullable String versionId) {} + + public record Error(String code, + String key, + String message, + @Nullable String versionId) {} public static DeleteObjectsResult fromXml(InputStream is) throws ParserConfigurationException, SAXException, IOException { diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResultSaxHandler.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResultSaxHandler.java index 236b109f5..0da93c412 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/DeleteObjectsResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/DeleteObjectsResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResult.java similarity index 94% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResult.java index 65f65681e..ba0d8cbea 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResultSaxHandler.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResultSaxHandler.java index bbd11bc6c..70dc7ab9e 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/InitiateMultipartUploadResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/InitiateMultipartUploadResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResult.java similarity index 95% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResult.java index d134cc4a6..fce17bab7 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResultSaxHandler.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResultSaxHandler.java index 92664455a..f0ef1823f 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListBucketResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListBucketResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResult.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResult.java index 654254ed6..e0b1e9a73 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResultSaxHandler.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResultSaxHandler.java index 3d65b9214..951e13adf 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListMultipartUploadsResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListMultipartUploadsResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; import org.xml.sax.Attributes; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResult.java similarity index 98% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResult.java index e3463a634..1cf5c14ff 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResult.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; /* diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResultSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResultSaxHandler.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResultSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResultSaxHandler.java index e773fe087..fd804847d 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/ListPartsResultSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/ListPartsResultSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3Error.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3Error.java similarity index 93% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3Error.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3Error.java index 01960c5bd..2261cf57f 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3Error.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3Error.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.jspecify.annotations.Nullable; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3ErrorSaxHandler.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3ErrorSaxHandler.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3ErrorSaxHandler.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3ErrorSaxHandler.java index 1cf45b444..a1149669d 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/impl/xml/S3ErrorSaxHandler.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/impl/xml/S3ErrorSaxHandler.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.impl.xml; +package io.koraframework.s3.client.kora.impl.xml; import org.xml.sax.Attributes; import org.xml.sax.SAXException; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/Range.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/Range.java similarity index 97% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/Range.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/Range.java index 433a17e25..64d39f3e3 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/Range.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/Range.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.model; +package io.koraframework.s3.client.kora.model; /** @@ -7,6 +7,7 @@ * @see rfc9110 */ public sealed interface Range { + String toRangeValue(); /** diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/AbortMultipartUploadArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/AbortMultipartUploadArgs.java similarity index 98% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/AbortMultipartUploadArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/AbortMultipartUploadArgs.java index f472d970d..82c42a3f1 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/AbortMultipartUploadArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/AbortMultipartUploadArgs.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; import io.koraframework.http.common.header.MutableHttpHeaders; import org.jspecify.annotations.Nullable; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CompleteMultipartUploadArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CompleteMultipartUploadArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CompleteMultipartUploadArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CompleteMultipartUploadArgs.java index e6a9d7eeb..a24c9d8f3 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CompleteMultipartUploadArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CompleteMultipartUploadArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; @@ -48,7 +48,6 @@ public class CompleteMultipartUploadArgs { * The server-side encryption (SSE) customer managed key. * This parameter is needed only when the object was created using a checksum algorithm. * For more information, see Protecting data using SSE-C keys in the Amazon S3 User Guide. - * */ @Nullable public String sseCustomerKey; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CreateMultipartUploadArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CreateMultipartUploadArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CreateMultipartUploadArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CreateMultipartUploadArgs.java index 19c926070..50a9fc31e 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/CreateMultipartUploadArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/CreateMultipartUploadArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/DeleteObjectArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/DeleteObjectArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/DeleteObjectArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/DeleteObjectArgs.java index 222184ca6..51a496dd1 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/DeleteObjectArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/DeleteObjectArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.SortedMap; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/GetObjectArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/GetObjectArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/GetObjectArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/GetObjectArgs.java index 19f89a886..55e9808eb 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/GetObjectArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/GetObjectArgs.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; -import io.koraframework.s3.client.model.Range; +import io.koraframework.s3.client.kora.model.Range; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.SortedMap; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/HeadObjectArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/HeadObjectArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/HeadObjectArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/HeadObjectArgs.java index f470e1708..6ecbb214b 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/HeadObjectArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/HeadObjectArgs.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; -import io.koraframework.s3.client.model.Range; +import io.koraframework.s3.client.kora.model.Range; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.SortedMap; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListMultipartUploadsArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListMultipartUploadsArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListMultipartUploadsArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListMultipartUploadsArgs.java index 241ee3cf0..6fc8e7611 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListMultipartUploadsArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListMultipartUploadsArgs.java @@ -1,8 +1,8 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.SortedMap; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListObjectsArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListObjectsArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListObjectsArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListObjectsArgs.java index 2169e8791..f36a095db 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListObjectsArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListObjectsArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListPartsArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListPartsArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListPartsArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListPartsArgs.java index c5402d084..99bc5def7 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/ListPartsArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/ListPartsArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; import java.util.SortedMap; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/PutObjectArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/PutObjectArgs.java similarity index 99% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/PutObjectArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/PutObjectArgs.java index 6a557e7b3..88d9c25c8 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/PutObjectArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/PutObjectArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/UploadPartArgs.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/UploadPartArgs.java similarity index 98% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/UploadPartArgs.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/UploadPartArgs.java index c9ef7f52f..2242e10fc 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/request/UploadPartArgs.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/request/UploadPartArgs.java @@ -1,7 +1,7 @@ -package io.koraframework.s3.client.model.request; +package io.koraframework.s3.client.kora.model.request; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.MutableHttpHeaders; +import org.jspecify.annotations.Nullable; import java.util.Map; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResult.java similarity index 81% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResult.java index b3e9b9882..efb937511 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResult.java @@ -1,8 +1,9 @@ -package io.koraframework.s3.client.model.response; +package io.koraframework.s3.client.kora.model.response; import io.koraframework.http.client.common.response.HttpClientResponse; public interface GetObjectResult extends HttpClientResponse { + record ContentRange(long firstPosition, long lastPosition, long completeLength) {} ContentRange contentRange(); diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResultImpl.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResultImpl.java similarity index 94% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResultImpl.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResultImpl.java index 7938026a8..300da4a4d 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/GetObjectResultImpl.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/GetObjectResultImpl.java @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.model.response; +package io.koraframework.s3.client.kora.model.response; import io.koraframework.http.client.common.response.HttpClientResponse; import io.koraframework.http.common.body.HttpBodyInput; @@ -7,6 +7,7 @@ import java.io.IOException; public class GetObjectResultImpl implements GetObjectResult { + private final HttpClientResponse rs; public GetObjectResultImpl(HttpClientResponse rs) { @@ -71,4 +72,9 @@ public ContentRange contentRange() { return new ContentRange(firstPosition, lastPosition, completeLength); } + + @Override + public String toString() { + return rs.toString(); + } } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/HeadObjectResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/HeadObjectResult.java similarity index 92% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/HeadObjectResult.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/HeadObjectResult.java index 37820253f..a98ea02ad 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/HeadObjectResult.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/HeadObjectResult.java @@ -1,12 +1,13 @@ -package io.koraframework.s3.client.model.response; +package io.koraframework.s3.client.kora.model.response; -import org.jspecify.annotations.Nullable; import io.koraframework.http.common.header.HttpHeaders; +import org.jspecify.annotations.Nullable; import java.time.Instant; import java.time.format.DateTimeFormatter; public record HeadObjectResult(String bucket, String key, long size, HttpHeaders headers) { + public String etag() { return headers.getFirst("ETag"); } diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListBucketResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListBucketResult.java new file mode 100644 index 000000000..5628a9690 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListBucketResult.java @@ -0,0 +1,25 @@ +package io.koraframework.s3.client.kora.model.response; + +import org.jspecify.annotations.Nullable; + +import java.time.Instant; +import java.util.List; + +public record ListBucketResult(@Nullable List commonPrefixes, + int keyCount, + @Nullable String nextContinuationToken, + List items) { + + public record ListBucketItem(String bucket, + String key, + String etag, + String checksumType, + String checksumAlgorithm, + Instant lastModified, + long size, + @Nullable String storageClass, + @Nullable ListBucketItemOwner owner) {} + + public record ListBucketItemOwner(String displayName, + String id) {} +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListMultipartUploadsResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListMultipartUploadsResult.java new file mode 100644 index 000000000..82dbe6d68 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListMultipartUploadsResult.java @@ -0,0 +1,13 @@ +package io.koraframework.s3.client.kora.model.response; + +import org.jspecify.annotations.Nullable; + +import java.time.Instant; +import java.util.List; + +public record ListMultipartUploadsResult(@Nullable String nextKeyMarker, + @Nullable String nextUploadIdMarker, + List uploads) { + + public record Upload(String key, String uploadId, Instant initiated) {} +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListPartsResult.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListPartsResult.java new file mode 100644 index 000000000..c8287649b --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/ListPartsResult.java @@ -0,0 +1,9 @@ +package io.koraframework.s3.client.kora.model.response; + +import java.util.List; + +public record ListPartsResult(Integer partNumberMarker, + Integer nextPartNumberMarker, + boolean truncated, + List parts) { +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/UploadedPart.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/UploadedPart.java new file mode 100644 index 000000000..ac2df5f40 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/model/response/UploadedPart.java @@ -0,0 +1,13 @@ +package io.koraframework.s3.client.kora.model.response; + +import org.jspecify.annotations.Nullable; + +public record UploadedPart(@Nullable String checksumCRC32, + @Nullable String checksumCRC32C, + @Nullable String checksumCRC64NVME, + @Nullable String checksumSHA1, + @Nullable String checksumSHA256, + String eTag, + int partNumber, + long size) { +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientObservation.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientObservation.java new file mode 100644 index 000000000..f928568ee --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientObservation.java @@ -0,0 +1,115 @@ +package io.koraframework.s3.client.kora.telemetry; + +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import io.micrometer.core.instrument.Timer; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.StatusCode; +import io.opentelemetry.semconv.ErrorAttributes; +import io.opentelemetry.semconv.incubating.AwsIncubatingAttributes; +import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes; +import org.jspecify.annotations.Nullable; +import org.slf4j.Logger; + +import java.util.concurrent.TimeUnit; + +public class DefaultS3ClientObservation implements S3ClientObservation { + + private final long startedRequest = System.nanoTime(); + + protected final String bucket; + protected final String operation; + protected final S3ClientTelemetryConfig config; + protected final Span span; + protected final Logger logger; + protected final Meter.MeterProvider duration; + + @Nullable + protected String awsKey; + @Nullable + protected String uploadId; + @Nullable + protected String requestId; + @Nullable + protected String extendedRequestId; + @Nullable + private Throwable error; + + public DefaultS3ClientObservation(String bucket, + String operation, + S3ClientTelemetryConfig config, + Span span, + Logger logger, + Meter.MeterProvider duration) { + this.operation = operation; + this.bucket = bucket; + this.config = config; + this.span = span; + this.logger = logger; + this.duration = duration; + } + + @Override + public void observeKey(String key) { + this.awsKey = key; + this.span.setAttribute(AwsIncubatingAttributes.AWS_S3_KEY, key); + } + + @Override + public void observeUploadId(String uploadId) { + this.uploadId = uploadId; + this.span.setAttribute(AwsIncubatingAttributes.AWS_S3_UPLOAD_ID, uploadId); + } + + @Override + public void observeAwsRequestId(@Nullable String amxRequestId) { + this.requestId = amxRequestId; + this.span.setAttribute(AwsIncubatingAttributes.AWS_REQUEST_ID, amxRequestId); + } + + @Override + public void observeAwsExtendedId(@Nullable String amxRequestId) { + this.extendedRequestId = amxRequestId; + this.span.setAttribute(AwsIncubatingAttributes.AWS_EXTENDED_REQUEST_ID, amxRequestId); + } + + @Override + public Span span() { + return this.span; + } + + @Override + public void observeError(Throwable e) { + this.span.recordException(e); + this.span.setStatus(StatusCode.ERROR); + this.error = e; + } + + @Override + public void end() { + var errorValue = (error == null) ? "" : this.error.getClass().getCanonicalName(); + + if (error == null) { + this.span.setStatus(StatusCode.OK); + this.logger.debug("KoraS3Client completed operation '{}' on bucket: {}", operation, bucket); + } else { + this.span.setStatus(StatusCode.ERROR, errorValue); + this.span.recordException(error); + this.logger.warn("KoraS3Client failed operation '{}' on bucket '{}' due to: {}", operation, bucket, error.getMessage()); + } + + if (config.metrics().enabled()) { + var took = System.nanoTime() - this.startedRequest; + var meter = this.duration.withTags(Tags.of( + Tag.of(RpcIncubatingAttributes.RPC_METHOD.getKey(), operation), + Tag.of(AwsIncubatingAttributes.AWS_S3_BUCKET.getKey(), bucket), + Tag.of(ErrorAttributes.ERROR_TYPE.getKey(), errorValue) + )); + + meter.record(took, TimeUnit.NANOSECONDS); + } + + this.span.end(); + } +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetry.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetry.java new file mode 100644 index 000000000..c63ebe8e5 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetry.java @@ -0,0 +1,77 @@ +package io.koraframework.s3.client.kora.telemetry; + +import io.micrometer.core.instrument.*; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.api.trace.SpanBuilder; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.semconv.incubating.AwsIncubatingAttributes; +import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.slf4j.helpers.NOPLogger; + +import java.util.ArrayList; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; + +public class DefaultS3ClientTelemetry implements S3ClientTelemetry { + + protected final ConcurrentMap requestDurationCache = new ConcurrentHashMap<>(); + + protected final S3ClientTelemetryConfig config; + protected final Tracer tracer; + protected final MeterRegistry meterRegistry; + protected final Logger logger; + protected final Meter.MeterProvider requestDurationMeter; + + public DefaultS3ClientTelemetry(S3ClientTelemetryConfig config, + Tracer tracer, + MeterRegistry meterRegistry) { + this.config = config; + this.tracer = tracer; + this.meterRegistry = meterRegistry; + + this.requestDurationMeter = tags -> + requestDurationCache.computeIfAbsent(Tags.of(tags), _ -> createMetricClientDuration() + .tags((Iterable) tags) + .register(this.meterRegistry)); + + var logger = LoggerFactory.getLogger(S3ClientTelemetry.class); + this.logger = this.config.logging().enabled() && logger.isWarnEnabled() + ? logger + : NOPLogger.NOP_LOGGER; + } + + @Override + public S3ClientObservation observe(String operation, String bucket) { + var span = this.config.tracing().enabled() + ? createSpan(operation, bucket).startSpan() + : Span.getInvalid(); + + logger.debug("KoraS3Client starting S3 operation '{}' on bucket: {}", operation, bucket); + return new DefaultS3ClientObservation(bucket, operation, config, span, logger, requestDurationMeter); + } + + protected Timer.Builder createMetricClientDuration() { + var staticTags = new ArrayList(1 + this.config.metrics().tags().size()); + staticTags.add(Tag.of(RpcIncubatingAttributes.RPC_SYSTEM.getKey(), "s3-kora")); + for (var e : this.config.metrics().tags().entrySet()) { + staticTags.add(Tag.of(e.getKey(), e.getValue())); + } + + return Timer.builder("rpc.client.duration") + .serviceLevelObjectives(this.config.metrics().slo()) + .tags(staticTags); + } + + protected SpanBuilder createSpan(String operation, String bucket) { + var span = this.tracer.spanBuilder("S3." + operation) + .setAttribute(RpcIncubatingAttributes.RPC_SYSTEM, "s3") + .setAttribute(RpcIncubatingAttributes.RPC_METHOD, operation) + .setAttribute(AwsIncubatingAttributes.AWS_S3_BUCKET, bucket); + for (var entry : this.config.tracing().attributes().entrySet()) { + span.setAttribute(entry.getKey(), entry.getValue()); + } + return span; + } +} diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetryFactory.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetryFactory.java new file mode 100644 index 000000000..0fda0e27c --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/DefaultS3ClientTelemetryFactory.java @@ -0,0 +1,37 @@ +package io.koraframework.s3.client.kora.telemetry; + +import io.micrometer.core.instrument.MeterRegistry; +import io.micrometer.core.instrument.composite.CompositeMeterRegistry; +import io.opentelemetry.api.trace.Tracer; +import io.opentelemetry.api.trace.TracerProvider; +import org.jspecify.annotations.Nullable; + +public final class DefaultS3ClientTelemetryFactory implements S3ClientTelemetryFactory { + + private static final Tracer NOOP_TRACER = TracerProvider.noop().get("s3-client-kora-telemetry"); + private static final MeterRegistry NOOP_METER_REGISTRY = new CompositeMeterRegistry(); + + @Nullable + private final Tracer tracer; + @Nullable + private final MeterRegistry meterRegistry; + + public DefaultS3ClientTelemetryFactory(@Nullable Tracer tracer, + @Nullable MeterRegistry meterRegistry) { + this.tracer = tracer; + this.meterRegistry = meterRegistry; + } + + @Override + public S3ClientTelemetry get(S3ClientTelemetryConfig config) { + var tracerEnabled = this.tracer != null && config.tracing().enabled(); + var metricEnabled = this.meterRegistry != null && config.metrics().enabled(); + if (!tracerEnabled && !metricEnabled && !config.logging().enabled()) { + return NoopS3ClientTelemetry.INSTANCE; + } + + var tracer = tracerEnabled ? this.tracer : NOOP_TRACER; + var meterRegistry = metricEnabled ? this.meterRegistry : NOOP_METER_REGISTRY; + return new DefaultS3ClientTelemetry(config, tracer, meterRegistry); + } +} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientObservation.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientObservation.java similarity index 78% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientObservation.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientObservation.java index f22a0b025..88796765b 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientObservation.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientObservation.java @@ -1,10 +1,13 @@ -package io.koraframework.s3.client.telemetry; +package io.koraframework.s3.client.kora.telemetry; import io.opentelemetry.api.trace.Span; -public class NoopS3ClientObservation implements S3ClientObservation { +public final class NoopS3ClientObservation implements S3ClientObservation { + public static final S3ClientObservation INSTANCE = new NoopS3ClientObservation(); + private NoopS3ClientObservation() {} + @Override public void observeKey(String key) { diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientTelemetry.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientTelemetry.java similarity index 58% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientTelemetry.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientTelemetry.java index b16b7e02b..506e300ec 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/NoopS3ClientTelemetry.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/NoopS3ClientTelemetry.java @@ -1,8 +1,11 @@ -package io.koraframework.s3.client.telemetry; +package io.koraframework.s3.client.kora.telemetry; + +public final class NoopS3ClientTelemetry implements S3ClientTelemetry { -public class NoopS3ClientTelemetry implements S3ClientTelemetry { public static final NoopS3ClientTelemetry INSTANCE = new NoopS3ClientTelemetry(); + private NoopS3ClientTelemetry() {} + @Override public S3ClientObservation observe(String operation, String bucket) { return NoopS3ClientObservation.INSTANCE; diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientObservation.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientObservation.java similarity index 87% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientObservation.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientObservation.java index c6ee39118..f44c6549a 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientObservation.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientObservation.java @@ -1,9 +1,10 @@ -package io.koraframework.s3.client.telemetry; +package io.koraframework.s3.client.kora.telemetry; -import org.jspecify.annotations.Nullable; import io.koraframework.common.telemetry.Observation; +import org.jspecify.annotations.Nullable; public interface S3ClientObservation extends Observation { + void observeKey(String key); void observeUploadId(String uploadId); diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetry.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetry.java similarity index 67% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetry.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetry.java index 8b5a16869..8bf41ac77 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetry.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetry.java @@ -1,6 +1,6 @@ -package io.koraframework.s3.client.telemetry; +package io.koraframework.s3.client.kora.telemetry; public interface S3ClientTelemetry { - S3ClientObservation observe(String operation, String bucket); + S3ClientObservation observe(String operation, String bucket); } diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryConfig.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryConfig.java similarity index 93% rename from experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryConfig.java rename to experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryConfig.java index c59c9b3c1..d98253bc3 100644 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryConfig.java +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryConfig.java @@ -1,10 +1,11 @@ -package io.koraframework.s3.client.telemetry; +package io.koraframework.s3.client.kora.telemetry; import io.koraframework.config.common.annotation.ConfigValueExtractor; import io.koraframework.telemetry.common.TelemetryConfig; @ConfigValueExtractor public interface S3ClientTelemetryConfig extends TelemetryConfig { + @Override S3ClientLogConfig logging(); diff --git a/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryFactory.java b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryFactory.java new file mode 100644 index 000000000..8404bf3d8 --- /dev/null +++ b/experimental/s3-client-kora/src/main/java/io/koraframework/s3/client/kora/telemetry/S3ClientTelemetryFactory.java @@ -0,0 +1,6 @@ +package io.koraframework.s3.client.kora.telemetry; + +public interface S3ClientTelemetryFactory { + + S3ClientTelemetry get(S3ClientTelemetryConfig config); +} diff --git a/experimental/s3-client/src/test/java/io/koraframework/s3/client/S3ClientTest.java b/experimental/s3-client-kora/src/test/java/io/koraframework/s3/client/S3ClientTest.java similarity index 95% rename from experimental/s3-client/src/test/java/io/koraframework/s3/client/S3ClientTest.java rename to experimental/s3-client-kora/src/test/java/io/koraframework/s3/client/S3ClientTest.java index 8ec7540ce..0fed39487 100644 --- a/experimental/s3-client/src/test/java/io/koraframework/s3/client/S3ClientTest.java +++ b/experimental/s3-client-kora/src/test/java/io/koraframework/s3/client/S3ClientTest.java @@ -1,5 +1,8 @@ package io.koraframework.s3.client; +import io.koraframework.s3.client.kora.S3Client; +import io.koraframework.s3.client.kora.S3ClientConfig; +import io.koraframework.s3.client.kora.S3Credentials; import io.minio.GetObjectArgs; import io.minio.MakeBucketArgs; import io.minio.MinioClient; @@ -12,16 +15,16 @@ import org.testcontainers.images.builder.Transferable; import org.testcontainers.utility.DockerImageName; import io.koraframework.http.client.ok.OkHttpClient; -import io.koraframework.s3.client.exception.S3ClientDeleteException; -import io.koraframework.s3.client.exception.S3ClientErrorException; -import io.koraframework.s3.client.exception.S3ClientNoSuchKeyException; -import io.koraframework.s3.client.exception.S3ClientResponseException; -import io.koraframework.s3.client.impl.S3ClientImpl; -import io.koraframework.s3.client.impl.xml.DeleteObjectsResult; -import io.koraframework.s3.client.model.Range; -import io.koraframework.s3.client.model.request.ListObjectsArgs; -import io.koraframework.s3.client.model.response.ListBucketResult; -import io.koraframework.s3.client.telemetry.NoopS3ClientTelemetry; +import io.koraframework.s3.client.kora.exception.S3ClientDeleteException; +import io.koraframework.s3.client.kora.exception.S3ClientErrorException; +import io.koraframework.s3.client.kora.exception.S3ClientNoSuchKeyException; +import io.koraframework.s3.client.kora.exception.S3ClientResponseException; +import io.koraframework.s3.client.kora.impl.KoraS3Client; +import io.koraframework.s3.client.kora.impl.xml.DeleteObjectsResult; +import io.koraframework.s3.client.kora.model.Range; +import io.koraframework.s3.client.kora.model.request.ListObjectsArgs; +import io.koraframework.s3.client.kora.model.response.ListBucketResult; +import io.koraframework.s3.client.kora.telemetry.NoopS3ClientTelemetry; import java.io.ByteArrayInputStream; import java.io.IOException; @@ -49,8 +52,8 @@ class S3ClientTest { .build(); static MinioClient minioClient; - AwsCredentials credentials = AwsCredentials.of("minioadmin", "minioadmin"); - AwsCredentials invalidCredentials = AwsCredentials.of("test", "test"); + S3Credentials credentials = S3Credentials.of("minioadmin", "minioadmin"); + S3Credentials invalidCredentials = S3Credentials.of("test", "test"); S3ClientConfig config; @BeforeAll @@ -85,7 +88,7 @@ void setUp() { S3Client s3Client() { var httpClient = new OkHttpClient(ok); - return new S3ClientImpl(httpClient, config, NoopS3ClientTelemetry.INSTANCE); + return new KoraS3Client(httpClient, config, NoopS3ClientTelemetry.INSTANCE); } @Nested @@ -174,7 +177,7 @@ void testInvalidAccessKey() { @Test void testInvalidSecretKey() { - assertThatThrownBy(() -> s3Client().getObject(AwsCredentials.of("minioadmin", "test"), "test", UUID.randomUUID().toString(), null, true)) + assertThatThrownBy(() -> s3Client().getObject(S3Credentials.of("minioadmin", "test"), "test", UUID.randomUUID().toString(), null, true)) .isInstanceOf(S3ClientErrorException.class) .hasFieldOrPropertyWithValue("errorCode", "SignatureDoesNotMatch") .hasFieldOrPropertyWithValue("errorMessage", "The request signature we calculated does not match the signature you provided. Check your key and signing method."); @@ -239,7 +242,7 @@ void testGetRange() throws Exception { .contentType("text/plain") .stream(new ByteArrayInputStream(content), content.length, -1) .build()); - var args = new io.koraframework.s3.client.model.request.GetObjectArgs(); + var args = new io.koraframework.s3.client.kora.model.request.GetObjectArgs(); try (var object = s3Client().getObject(credentials, "test", key, args.setRange(Range.fromTo(1, 5)), true)) { assertThat(object).isNotNull(); assertThat(object.contentRange().completeLength()).isEqualTo(content.length); @@ -420,7 +423,7 @@ void testDeleteObjectsWithError() throws Exception { .stream(new ByteArrayInputStream(content), content.length, -1) .build()); try { - assertThatThrownBy(() -> s3Client().deleteObjects(AwsCredentials.of("testDeleteObjectsWithError", "testDeleteObjectsWithError"), "test", List.of(key1, key2))) + assertThatThrownBy(() -> s3Client().deleteObjects(S3Credentials.of("testDeleteObjectsWithError", "testDeleteObjectsWithError"), "test", List.of(key1, key2))) .isInstanceOf(S3ClientDeleteException.class) .asInstanceOf(InstanceOfAssertFactories.throwable(S3ClientDeleteException.class)) .extracting(S3ClientDeleteException::getErrors, InstanceOfAssertFactories.list(DeleteObjectsResult.Error.class)) diff --git a/experimental/s3-client-symbol-processor/build.gradle b/experimental/s3-client-symbol-processor/build.gradle index 71f6c1bbf..a24866ba5 100644 --- a/experimental/s3-client-symbol-processor/build.gradle +++ b/experimental/s3-client-symbol-processor/build.gradle @@ -8,7 +8,7 @@ dependencies { implementation libs.kotlinpoet implementation libs.kotlinpoet.ksp - testImplementation project(":experimental:s3-client") + testImplementation project(":experimental:s3-client-kora") testImplementation project(":internal:test-logging") testImplementation testFixtures(project(":symbol-processor-common")) testImplementation(libs.kotlin.stdlib.lib) diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClassNames.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClassNames.kt new file mode 100644 index 000000000..b36f764cb --- /dev/null +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClassNames.kt @@ -0,0 +1,50 @@ +package io.koraframework.s3.client.kora.symbol.processor +import com.squareup.kotlinpoet.ClassName +import com.squareup.kotlinpoet.asClassName +import com.squareup.kotlinpoet.asTypeName +import java.io.InputStream +import java.nio.ByteBuffer + +object S3ClassNames { + object Annotation { + val client = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Client") + val bucket = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Bucket") + val get = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Get") + val list = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "List") + val put = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Put") + val delete = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Delete") + val head = ClassName("io.koraframework.s3.client.kora.annotation", "S3", "Head") + val operations = setOf(get, list, put, delete, head) + } + + val client = ClassName("io.koraframework.s3.client.kora", "S3Client") + val s3Credentials = ClassName("io.koraframework.s3.client.kora", "S3Credentials") + val clientFactory = ClassName("io.koraframework.s3.client.kora", "S3ClientFactory") + val config = ClassName("io.koraframework.s3.client.kora", "S3ClientConfig") + val configWithCreds = ClassName("io.koraframework.s3.client.kora", "S3ClientConfigWithCredentials") + + val contentWriter: ClassName = client.nestedClass("ContentWriter") + + val putObjectArgs = ClassName("io.koraframework.s3.client.kora.model.request", "PutObjectArgs") + val getObjectArgs = ClassName("io.koraframework.s3.client.kora.model.request", "GetObjectArgs") + val deleteObjectArgs = ClassName("io.koraframework.s3.client.kora.model.request", "DeleteObjectArgs") + val headObjectArgs = ClassName("io.koraframework.s3.client.kora.model.request", "HeadObjectArgs") + val listObjectsArgs = ClassName("io.koraframework.s3.client.kora.model.request", "ListObjectsArgs") + val createMultipartUploadArgs = ClassName("io.koraframework.s3.client.kora.model.request", "CreateMultipartUploadArgs") + val completeMultipartUploadArgs = ClassName("io.koraframework.s3.client.kora.model.request", "CompleteMultipartUploadArgs") + val args = setOf(putObjectArgs, getObjectArgs, deleteObjectArgs, headObjectArgs, listObjectsArgs) + val getObjectResult = ClassName("io.koraframework.s3.client.kora.model.response", "GetObjectResult") + val headObjectResult = ClassName("io.koraframework.s3.client.kora.model.response", "HeadObjectResult") + val listBucketResult = ClassName("io.koraframework.s3.client.kora.model.response", "ListBucketResult") + val uploadedPart = ClassName("io.koraframework.s3.client.kora.model.response", "UploadedPart") + val listBucketResultItem: ClassName = listBucketResult.nestedClass("ListBucketItem") + + val unknownException = ClassName("io.koraframework.s3.client.kora.exception", "S3ClientUnknownException") + + val bodyTypes = setOf( + ByteArray::class.asTypeName(), + ByteBuffer::class.asTypeName(), + InputStream::class.asClassName(), + contentWriter + ) +} diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProcessor.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProcessor.kt similarity index 86% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProcessor.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProcessor.kt index 9d34b61d5..c4d891820 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProcessor.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProcessor.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor +package io.koraframework.s3.client.kora.symbol.processor import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.processing.SymbolProcessorEnvironment @@ -7,9 +7,9 @@ import com.google.devtools.ksp.symbol.KSClassDeclaration import com.squareup.kotlinpoet.FileSpec import com.squareup.kotlinpoet.ksp.writeTo import io.koraframework.ksp.common.BaseSymbolProcessor -import io.koraframework.s3.client.symbol.processor.gen.BucketsConfigGenerator -import io.koraframework.s3.client.symbol.processor.gen.ClientGenerator -import io.koraframework.s3.client.symbol.processor.gen.ModuleGenerator +import io.koraframework.s3.client.kora.symbol.processor.gen.BucketsConfigGenerator +import io.koraframework.s3.client.kora.symbol.processor.gen.ClientGenerator +import io.koraframework.s3.client.kora.symbol.processor.gen.ModuleGenerator import java.io.IOException diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProvider.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProvider.kt similarity index 84% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProvider.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProvider.kt index a2895614b..46d7f1f57 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientSymbolProvider.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientSymbolProvider.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor +package io.koraframework.s3.client.kora.symbol.processor import com.google.devtools.ksp.processing.SymbolProcessorEnvironment import com.google.devtools.ksp.processing.SymbolProcessorProvider diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientUtils.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientUtils.kt similarity index 91% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientUtils.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientUtils.kt index 2dede6723..c7e4bdc78 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClientUtils.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/S3ClientUtils.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor +package io.koraframework.s3.client.kora.symbol.processor import com.google.devtools.ksp.symbol.KSClassDeclaration import com.google.devtools.ksp.symbol.KSFunctionDeclaration @@ -57,9 +57,9 @@ object S3ClientUtils { var foundParam: KSValueParameter? = null for (param in method.parameters) { val typeName = param.type.resolve().toTypeName() - if (S3ClassNames.awsCredentials == typeName) { + if (S3ClassNames.s3Credentials == typeName) { if (foundParam != null) { - throw ProcessingErrorException("Multiple AwsCredentials parameters found", method) + throw ProcessingErrorException("Multiple S3Credentials parameters found", method) } foundParam = param } diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/BucketsConfigGenerator.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/BucketsConfigGenerator.kt similarity index 91% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/BucketsConfigGenerator.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/BucketsConfigGenerator.kt index f57f4e77f..75b8e7614 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/BucketsConfigGenerator.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/BucketsConfigGenerator.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor.gen +package io.koraframework.s3.client.kora.symbol.processor.gen import com.google.devtools.ksp.symbol.KSClassDeclaration import com.squareup.kotlinpoet.* @@ -7,8 +7,8 @@ import io.koraframework.ksp.common.AnnotationUtils.findValueNoDefault import io.koraframework.ksp.common.CommonClassNames import io.koraframework.ksp.common.KspCommonUtils.generated import io.koraframework.ksp.common.generatedClassName -import io.koraframework.s3.client.symbol.processor.S3ClassNames -import io.koraframework.s3.client.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClassNames object BucketsConfigGenerator { diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ClientGenerator.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ClientGenerator.kt similarity index 98% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ClientGenerator.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ClientGenerator.kt index 9cfafbfaf..a30567e99 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ClientGenerator.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ClientGenerator.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor.gen +package io.koraframework.s3.client.kora.symbol.processor.gen import com.google.devtools.ksp.processing.Resolver import com.google.devtools.ksp.symbol.KSAnnotation @@ -21,8 +21,8 @@ import io.koraframework.ksp.common.KspCommonUtils.generated import io.koraframework.ksp.common.KspCommonUtils.resolveToUnderlying import io.koraframework.ksp.common.exception.ProcessingErrorException import io.koraframework.ksp.common.generatedClassName -import io.koraframework.s3.client.symbol.processor.S3ClassNames -import io.koraframework.s3.client.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClassNames import java.io.IOException import java.io.InputStream import java.nio.ByteBuffer @@ -41,7 +41,7 @@ object ClientGenerator { S3ClassNames.configWithCreds else S3ClassNames.config - val b = s3client.extendsKeepAop(s3client.generatedClassName("ClientImpl"), resolver) + val b = s3client.extendsKeepAop(s3client.generatedClassName("S3ClientImpl"), resolver) .generated(ClientGenerator::class) .addProperty( PropertySpec.Companion.builder("client", S3ClassNames.client, KModifier.PRIVATE) @@ -375,7 +375,7 @@ object ClientGenerator { val keyMapping = annotation.findValueNoDefault("value") val parameters = function.parameters.filter { val parameterTypeName = it.type.resolve().toTypeName() - !it.isAnnotationPresent(S3ClassNames.Annotation.bucket) && parameterTypeName != S3ClassNames.awsCredentials && !S3ClassNames.args.contains(parameterTypeName) && !S3ClassNames.bodyTypes.contains( + !it.isAnnotationPresent(S3ClassNames.Annotation.bucket) && parameterTypeName != S3ClassNames.s3Credentials && !S3ClassNames.args.contains(parameterTypeName) && !S3ClassNames.bodyTypes.contains( parameterTypeName ) } diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ModuleGenerator.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ModuleGenerator.kt similarity index 93% rename from experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ModuleGenerator.kt rename to experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ModuleGenerator.kt index 6378288ed..862dcb0a4 100644 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/gen/ModuleGenerator.kt +++ b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/kora/symbol/processor/gen/ModuleGenerator.kt @@ -1,4 +1,4 @@ -package io.koraframework.s3.client.symbol.processor.gen +package io.koraframework.s3.client.kora.symbol.processor.gen import com.google.devtools.ksp.symbol.KSClassDeclaration import com.squareup.kotlinpoet.ClassName @@ -12,16 +12,16 @@ import io.koraframework.ksp.common.CommonClassNames import io.koraframework.ksp.common.KotlinPoetUtils.controlFlow import io.koraframework.ksp.common.KspCommonUtils.generated import io.koraframework.ksp.common.generatedClassName -import io.koraframework.s3.client.symbol.processor.S3ClassNames -import io.koraframework.s3.client.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClientUtils +import io.koraframework.s3.client.kora.symbol.processor.S3ClassNames object ModuleGenerator { fun generate(s3client: KSClassDeclaration): TypeSpec { val packageName = s3client.packageName.asString() val bucketsType = ClassName(packageName, s3client.generatedClassName("BucketsConfig")) - val clientType = ClassName(packageName, s3client.generatedClassName("ClientImpl")) - val b: TypeSpec.Builder = interfaceBuilder(s3client.generatedClassName("Module")) + val clientType = ClassName(packageName, s3client.generatedClassName("S3ClientImpl")) + val b: TypeSpec.Builder = interfaceBuilder(s3client.generatedClassName("S3Module")) .generated(ModuleGenerator::class) .addAnnotation(CommonClassNames.module) diff --git a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClassNames.kt b/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClassNames.kt deleted file mode 100644 index 33099b99b..000000000 --- a/experimental/s3-client-symbol-processor/src/main/kotlin/io/koraframework/s3/client/symbol/processor/S3ClassNames.kt +++ /dev/null @@ -1,50 +0,0 @@ -package io.koraframework.s3.client.symbol.processor -import com.squareup.kotlinpoet.ClassName -import com.squareup.kotlinpoet.asClassName -import com.squareup.kotlinpoet.asTypeName -import java.io.InputStream -import java.nio.ByteBuffer - -object S3ClassNames { - object Annotation { - val client = ClassName("io.koraframework.s3.client.annotation", "S3", "Client") - val bucket = ClassName("io.koraframework.s3.client.annotation", "S3", "Bucket") - val get = ClassName("io.koraframework.s3.client.annotation", "S3", "Get") - val list = ClassName("io.koraframework.s3.client.annotation", "S3", "List") - val put = ClassName("io.koraframework.s3.client.annotation", "S3", "Put") - val delete = ClassName("io.koraframework.s3.client.annotation", "S3", "Delete") - val head = ClassName("io.koraframework.s3.client.annotation", "S3", "Head") - val operations = setOf(get, list, put, delete, head) - } - - val client = ClassName("io.koraframework.s3.client", "S3Client") - val awsCredentials = ClassName("io.koraframework.s3.client", "AwsCredentials") - val clientFactory = ClassName("io.koraframework.s3.client", "S3ClientFactory") - val config = ClassName("io.koraframework.s3.client", "S3ClientConfig") - val configWithCreds = ClassName("io.koraframework.s3.client", "S3ClientConfigWithCredentials") - - val contentWriter: ClassName = client.nestedClass("ContentWriter") - - val putObjectArgs = ClassName("io.koraframework.s3.client.model.request", "PutObjectArgs") - val getObjectArgs = ClassName("io.koraframework.s3.client.model.request", "GetObjectArgs") - val deleteObjectArgs = ClassName("io.koraframework.s3.client.model.request", "DeleteObjectArgs") - val headObjectArgs = ClassName("io.koraframework.s3.client.model.request", "HeadObjectArgs") - val listObjectsArgs = ClassName("io.koraframework.s3.client.model.request", "ListObjectsArgs") - val createMultipartUploadArgs = ClassName("io.koraframework.s3.client.model.request", "CreateMultipartUploadArgs") - val completeMultipartUploadArgs = ClassName("io.koraframework.s3.client.model.request", "CompleteMultipartUploadArgs") - val args = setOf(putObjectArgs, getObjectArgs, deleteObjectArgs, headObjectArgs, listObjectsArgs) - val getObjectResult = ClassName("io.koraframework.s3.client.model.response", "GetObjectResult") - val headObjectResult = ClassName("io.koraframework.s3.client.model.response", "HeadObjectResult") - val listBucketResult = ClassName("io.koraframework.s3.client.model.response", "ListBucketResult") - val uploadedPart = ClassName("io.koraframework.s3.client.model.response", "UploadedPart") - val listBucketResultItem: ClassName = listBucketResult.nestedClass("ListBucketItem") - - val unknownException = ClassName("io.koraframework.s3.client.exception", "S3ClientUnknownException") - - val bodyTypes = setOf( - ByteArray::class.asTypeName(), - ByteBuffer::class.asTypeName(), - InputStream::class.asClassName(), - contentWriter - ) -} diff --git a/experimental/s3-client-symbol-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider b/experimental/s3-client-symbol-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider index fcb6ef54a..cb7916af3 100644 --- a/experimental/s3-client-symbol-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider +++ b/experimental/s3-client-symbol-processor/src/main/resources/META-INF/services/com.google.devtools.ksp.processing.SymbolProcessorProvider @@ -1 +1 @@ -io.koraframework.s3.client.symbol.processor.S3ClientSymbolProvider +io.koraframework.s3.client.kora.symbol.processor.S3ClientSymbolProvider diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/AbstractS3ClientTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/AbstractS3ClientTest.kt index b73882d09..271a1c407 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/AbstractS3ClientTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/AbstractS3ClientTest.kt @@ -1,10 +1,10 @@ -package io.koraframework.s3.client.symbol.processor +package io.koraframework.s3.client.kora.symbol.processor import com.google.devtools.ksp.processing.SymbolProcessorProvider import io.koraframework.ksp.common.AbstractSymbolProcessorTest -import io.koraframework.s3.client.S3Client -import io.koraframework.s3.client.S3ClientConfigWithCredentials -import io.koraframework.s3.client.S3ClientFactory +import io.koraframework.s3.client.kora.S3Client +import io.koraframework.s3.client.kora.S3ClientConfigWithCredentials +import io.koraframework.s3.client.kora.S3ClientFactory import org.intellij.lang.annotations.Language import org.mockito.Answers import org.mockito.Mockito @@ -15,12 +15,12 @@ abstract class AbstractS3ClientTest : AbstractSymbolProcessorTest() { return super.commonImports() + """ import java.nio.ByteBuffer import java.io.InputStream - import io.koraframework.s3.client.annotation.* - import io.koraframework.s3.client.annotation.S3.* - import io.koraframework.s3.client.model.request.* - import io.koraframework.s3.client.model.response.* - import io.koraframework.s3.client.* - import io.koraframework.s3.client.S3Client.* + import io.koraframework.s3.client.kora.annotation.* + import io.koraframework.s3.client.kora.annotation.S3.* + import io.koraframework.s3.client.kora.model.request.* + import io.koraframework.s3.client.kora.model.response.* + import io.koraframework.s3.client.kora.* + import io.koraframework.s3.client.kora.S3Client.* """.trimIndent() } @@ -35,6 +35,6 @@ abstract class AbstractS3ClientTest : AbstractSymbolProcessorTest() { args.add(clientFactory) args.add(config) args.addAll(addArgs.map { if (it is GeneratedObject<*>) it() else it }) - return newObject("\$Client_ClientImpl", *args.toTypedArray()) + return newObject("\$Client_S3ClientImpl", *args.toTypedArray()) } } diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3DeleteTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3DeleteTest.kt index 1005df4d4..a609a1469 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3DeleteTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3DeleteTest.kt @@ -3,8 +3,9 @@ package io.koraframework.s3.client.symbol.processor import org.junit.jupiter.api.Test import org.mockito.Mockito.* import io.koraframework.config.common.factory.MapConfigFactory -import io.koraframework.s3.client.AwsCredentials -import io.koraframework.s3.client.model.request.DeleteObjectArgs +import io.koraframework.s3.client.kora.S3Credentials +import io.koraframework.s3.client.kora.model.request.DeleteObjectArgs +import io.koraframework.s3.client.kora.symbol.processor.AbstractS3ClientTest internal class S3DeleteTest : AbstractS3ClientTest() { @@ -54,7 +55,7 @@ internal class S3DeleteTest : AbstractS3ClientTest() { } @Test - fun testDeleteWithAwsCredentials() { + fun testDeleteWithS3Credentials() { val bucketConfig = MapConfigFactory.fromMap( mapOf( "Client" to mapOf( @@ -68,13 +69,13 @@ internal class S3DeleteTest : AbstractS3ClientTest() { @S3.Bucket(".bucket") interface Client { @S3.Delete - fun deleteWithCreds(creds: AwsCredentials, key: String) + fun deleteWithCreds(creds: S3Credentials, key: String) } """.trimIndent(), newGenerated("\$Client_BucketsConfig", bucketConfig) ) - val creds = AwsCredentials.of("test", "test") + val creds = S3Credentials.of("test", "test") client.invoke("deleteWithCreds", creds, "key") verify(s3Client).deleteObject(same(creds), eq("bucket_value"), eq("key"), isNull()) diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3GetTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3GetTest.kt index bd21379ea..6be281039 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3GetTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3GetTest.kt @@ -6,9 +6,10 @@ import org.mockito.ArgumentMatchers.* import org.mockito.Mockito.* import io.koraframework.config.common.factory.MapConfigFactory import io.koraframework.http.common.body.HttpBodyInput -import io.koraframework.s3.client.AwsCredentials -import io.koraframework.s3.client.model.request.GetObjectArgs -import io.koraframework.s3.client.model.response.GetObjectResult +import io.koraframework.s3.client.kora.S3Credentials +import io.koraframework.s3.client.kora.model.request.GetObjectArgs +import io.koraframework.s3.client.kora.model.response.GetObjectResult +import io.koraframework.s3.client.kora.symbol.processor.AbstractS3ClientTest import java.io.ByteArrayInputStream @@ -104,7 +105,7 @@ internal class S3GetTest : AbstractS3ClientTest() { } @Test - fun testGetWithAwsCredentials() { + fun testGetWithS3Credentials() { val bucketConfig = MapConfigFactory.fromMap( mapOf( "Client" to mapOf( @@ -118,14 +119,14 @@ internal class S3GetTest : AbstractS3ClientTest() { @S3.Bucket(".bucket") interface Client { @S3.Get - fun getWithCreds(creds: AwsCredentials, key: String): GetObjectResult? + fun getWithCreds(creds: S3Credentials, key: String): GetObjectResult? } """.trimIndent(), newGenerated("\$Client_BucketsConfig", bucketConfig) ) val getObjectResult = mock(GetObjectResult::class.java) - val creds = AwsCredentials.of("test", "test") + val creds = S3Credentials.of("test", "test") `when`( s3Client.getObject( same(creds), diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3HeadTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3HeadTest.kt index 58a524031..5f6de9abf 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3HeadTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3HeadTest.kt @@ -6,7 +6,8 @@ import org.mockito.ArgumentMatchers.* import org.mockito.Mockito.verify import org.mockito.Mockito.`when` import io.koraframework.http.common.header.HttpHeaders -import io.koraframework.s3.client.model.response.HeadObjectResult +import io.koraframework.s3.client.kora.model.response.HeadObjectResult +import io.koraframework.s3.client.kora.symbol.processor.AbstractS3ClientTest class S3HeadTest : AbstractS3ClientTest() { @Test diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3ListTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3ListTest.kt index 72348e6ef..22088707a 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3ListTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3ListTest.kt @@ -4,9 +4,10 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.mockito.ArgumentMatchers.* import org.mockito.Mockito.* -import io.koraframework.s3.client.AwsCredentials -import io.koraframework.s3.client.model.request.ListObjectsArgs -import io.koraframework.s3.client.model.response.ListBucketResult +import io.koraframework.s3.client.kora.S3Credentials +import io.koraframework.s3.client.kora.model.request.ListObjectsArgs +import io.koraframework.s3.client.kora.model.response.ListBucketResult +import io.koraframework.s3.client.kora.symbol.processor.AbstractS3ClientTest class S3ListTest : AbstractS3ClientTest() { @@ -18,13 +19,13 @@ class S3ListTest : AbstractS3ClientTest() { @S3.Client interface Client { @S3.List - fun getWithPrefix(creds: AwsCredentials, @Bucket bucket: String, prefix: String): List + fun getWithPrefix(creds: S3Credentials, @Bucket bucket: String, prefix: String): List } """.trimIndent() ) - val creds = AwsCredentials.of("test", "test") + val creds = S3Credentials.of("test", "test") val list = listOf(ListBucketResult.ListBucketItem("test", "test1", "etag", null, null, null, 1L, null, null)) val listBucketResult = ListBucketResult(null, 1, null, list) @@ -54,13 +55,13 @@ class S3ListTest : AbstractS3ClientTest() { @S3.Client public interface Client { @S3.List("const-") - fun listConst(creds: AwsCredentials, @Bucket bucket: String): ListBucketResult + fun listConst(creds: S3Credentials, @Bucket bucket: String): ListBucketResult } """.trimIndent() ) - val creds = AwsCredentials.of("a", "b") + val creds = S3Credentials.of("a", "b") val items = listOf(ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 10L, null, null)) val res = ListBucketResult(null, 1, null, items) @@ -88,13 +89,13 @@ class S3ListTest : AbstractS3ClientTest() { @S3.Client interface Client { @S3.List - fun iteratorStrings(creds: AwsCredentials, @Bucket bucket: String, args: ListObjectsArgs): Iterator + fun iteratorStrings(creds: S3Credentials, @Bucket bucket: String, args: ListObjectsArgs): Iterator } """.trimIndent() ) - val creds = AwsCredentials.of("x", "y") + val creds = S3Credentials.of("x", "y") val item1 = ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 1L, null, null) val item2 = ListBucketResult.ListBucketItem("b", "k2", "etag", null, null, null, 2L, null, null) @@ -114,7 +115,7 @@ class S3ListTest : AbstractS3ClientTest() { assertThat(it!!.next()).isEqualTo("k1") assertThat(it.next()).isEqualTo("k2") - verify(s3Client).listObjectsV2Iterator(same(creds), eq("bucket"), any()) + verify(s3Client).listObjectsV2Iterator(same(creds), eq("bucket"), any()) reset(s3Client) } @@ -125,12 +126,12 @@ class S3ListTest : AbstractS3ClientTest() { @S3.Client interface Client { @S3.List - fun iteratorItems(creds: AwsCredentials, @Bucket bucket: String, args: ListObjectsArgs): Iterator + fun iteratorItems(creds: S3Credentials, @Bucket bucket: String, args: ListObjectsArgs): Iterator } """.trimIndent() ) - val creds = AwsCredentials.of("x", "y") + val creds = S3Credentials.of("x", "y") val item1 = ListBucketResult.ListBucketItem("b", "k1", "etag", null, null, null, 1L, null, null) val item2 = ListBucketResult.ListBucketItem("b", "k2", "etag", null, null, null, 2L, null, null) @@ -162,12 +163,12 @@ class S3ListTest : AbstractS3ClientTest() { @S3.Client interface Client { @S3.List("pre-{prefix}") - fun items(creds: AwsCredentials, @Bucket bucket: String, prefix: String): List + fun items(creds: S3Credentials, @Bucket bucket: String, prefix: String): List } """.trimIndent() ) - val creds = AwsCredentials.of("u", "v") + val creds = S3Credentials.of("u", "v") val items = listOf(ListBucketResult.ListBucketItem("b", "item-key", "etag", null, null, null, 5L, null, null)) val res = ListBucketResult(null, 1, null, items) diff --git a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3PutTest.kt b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3PutTest.kt index b7f6d1804..984f01024 100644 --- a/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3PutTest.kt +++ b/experimental/s3-client-symbol-processor/src/test/kotlin/io/koraframework/s3/client/symbol/processor/S3PutTest.kt @@ -4,9 +4,10 @@ import org.assertj.core.api.Assertions.assertThat import org.junit.jupiter.api.Test import org.mockito.ArgumentMatchers.* import org.mockito.Mockito.* -import io.koraframework.s3.client.`$S3ClientConfig_UploadConfig_ConfigValueExtractor` -import io.koraframework.s3.client.S3Client -import io.koraframework.s3.client.model.response.UploadedPart +import io.koraframework.s3.client.kora.`$S3ClientConfig_UploadConfig_ConfigValueExtractor` +import io.koraframework.s3.client.kora.S3Client +import io.koraframework.s3.client.kora.model.response.UploadedPart +import io.koraframework.s3.client.kora.symbol.processor.AbstractS3ClientTest import java.io.ByteArrayInputStream import java.nio.ByteBuffer import java.nio.charset.StandardCharsets diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/AwsCredentials.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/AwsCredentials.java deleted file mode 100644 index 7f82d9dda..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/AwsCredentials.java +++ /dev/null @@ -1,13 +0,0 @@ -package io.koraframework.s3.client; - -import io.koraframework.s3.client.impl.AwsRequestSigner; - -public interface AwsCredentials { - String accessKey(); - - String secretKey(); - - static AwsCredentials of(String accessKey, String secretKey) { - return new AwsRequestSigner(accessKey, secretKey); - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientModule.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientModule.java deleted file mode 100644 index 01c9fdf30..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/S3ClientModule.java +++ /dev/null @@ -1,46 +0,0 @@ -package io.koraframework.s3.client; - -import io.micrometer.core.instrument.MeterRegistry; -import io.opentelemetry.api.trace.Tracer; -import org.jspecify.annotations.Nullable; -import io.koraframework.config.common.ConfigValue; -import io.koraframework.config.common.extractor.ConfigValueExtractionException; -import io.koraframework.config.common.extractor.ConfigValueExtractor; -import io.koraframework.http.client.common.HttpClient; -import io.koraframework.s3.client.impl.S3ClientImpl; -import io.koraframework.s3.client.telemetry.DefaultS3ClientTelemetryFactory; -import io.koraframework.s3.client.telemetry.S3ClientTelemetryFactory; - -public interface S3ClientModule { - default S3ClientTelemetryFactory defaultS3ClientTelemetryFactory(@Nullable Tracer tracer, @Nullable MeterRegistry meterRegistry) { - return new DefaultS3ClientTelemetryFactory(tracer, meterRegistry); - } - - default S3ClientFactory defaultS3ClientFactory(HttpClient client, S3ClientTelemetryFactory telemetryFactory) { - return config -> { - var telemetry = telemetryFactory.get(config); - return new S3ClientImpl(client, config, telemetry); - }; - } - - default ConfigValueExtractor awsCredentialsConfigValueExtractor() { - return src -> { - if (src instanceof ConfigValue.NullValue) { - return null; - } - var configObject = src.asObject(); - var accessKey = configObject.get("accessKey"); - if (accessKey.isNull()) { - throw ConfigValueExtractionException.missingValue(accessKey); - } - var secretKey = configObject.get("secretKey"); - if (secretKey.isNull()) { - throw ConfigValueExtractionException.missingValue(secretKey); - } - return AwsCredentials.of( - accessKey.asString(), - secretKey.asString() - ); - }; - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientDeleteException.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientDeleteException.java deleted file mode 100644 index 99e3bfbd8..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/exception/S3ClientDeleteException.java +++ /dev/null @@ -1,17 +0,0 @@ -package io.koraframework.s3.client.exception; - -import io.koraframework.s3.client.impl.xml.DeleteObjectsResult; - -import java.util.List; - -public class S3ClientDeleteException extends S3ClientException { - private final List errors; - - public S3ClientDeleteException(List errors) { - this.errors = errors; - } - - public List getErrors() { - return errors; - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListBucketResult.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListBucketResult.java deleted file mode 100644 index e5eb88f1c..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListBucketResult.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.koraframework.s3.client.model.response; - -import org.jspecify.annotations.Nullable; - -import java.time.Instant; -import java.util.List; - -public record ListBucketResult(@Nullable List commonPrefixes, int keyCount, @Nullable String nextContinuationToken, List items) { - - public record ListBucketItem( - String bucket, String key, String etag, String checksumType, String checksumAlgorithm, Instant lastModified, long size, @Nullable String storageClass, @Nullable ListBucketItemOwner owner - ) {} - - public record ListBucketItemOwner(String displayName, String id) {} -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListMultipartUploadsResult.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListMultipartUploadsResult.java deleted file mode 100644 index acc49bc13..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListMultipartUploadsResult.java +++ /dev/null @@ -1,15 +0,0 @@ -package io.koraframework.s3.client.model.response; - -import org.jspecify.annotations.Nullable; - -import java.time.Instant; -import java.util.List; - -public record ListMultipartUploadsResult( - @Nullable String nextKeyMarker, - @Nullable String nextUploadIdMarker, - List uploads) { - - public record Upload(String key, String uploadId, Instant initiated) {} - -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListPartsResult.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListPartsResult.java deleted file mode 100644 index 740ceb3be..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/ListPartsResult.java +++ /dev/null @@ -1,6 +0,0 @@ -package io.koraframework.s3.client.model.response; - -import java.util.List; - -public record ListPartsResult(Integer partNumberMarker, Integer nextPartNumberMarker, boolean truncated, List parts) { -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/UploadedPart.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/UploadedPart.java deleted file mode 100644 index a4cbffc61..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/model/response/UploadedPart.java +++ /dev/null @@ -1,20 +0,0 @@ -package io.koraframework.s3.client.model.response; - -import org.jspecify.annotations.Nullable; - -public record UploadedPart( - @Nullable - String checksumCRC32, - @Nullable - String checksumCRC32C, - @Nullable - String checksumCRC64NVME, - @Nullable - String checksumSHA1, - @Nullable - String checksumSHA256, - String eTag, - int partNumber, - long size -) { -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientObservation.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientObservation.java deleted file mode 100644 index 4b6e636ea..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientObservation.java +++ /dev/null @@ -1,69 +0,0 @@ -package io.koraframework.s3.client.telemetry; - -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.Timer; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.StatusCode; -import io.opentelemetry.semconv.ErrorAttributes; -import io.opentelemetry.semconv.incubating.AwsIncubatingAttributes; -import org.jspecify.annotations.Nullable; - -import java.util.concurrent.TimeUnit; - -public class DefaultS3ClientObservation implements S3ClientObservation { - private final long start = System.nanoTime(); - private final Span span; - private final Meter.MeterProvider duration; - private Throwable error; - - public DefaultS3ClientObservation(Span span, Meter.MeterProvider duration) { - this.span = span; - this.duration = duration; - } - - @Override - public void observeKey(String key) { - span.setAttribute(AwsIncubatingAttributes.AWS_S3_KEY, key); - } - - @Override - public void observeUploadId(String uploadId) { - span.setAttribute(AwsIncubatingAttributes.AWS_S3_UPLOAD_ID, uploadId); - } - - @Override - public void observeAwsRequestId(@Nullable String amxRequestId) { - span.setAttribute(AwsIncubatingAttributes.AWS_REQUEST_ID, amxRequestId); - } - - @Override - public void observeAwsExtendedId(@Nullable String amxRequestId) { - span.setAttribute(AwsIncubatingAttributes.AWS_EXTENDED_REQUEST_ID, amxRequestId); - } - - @Override - public Span span() { - return this.span; - } - - @Override - public void observeError(Throwable e) { - this.span.recordException(e); - this.span.setStatus(StatusCode.ERROR); - this.error = e; - } - - @Override - public void end() { - var took = System.nanoTime() - this.start; - if (this.error == null) { - this.span.setStatus(StatusCode.OK); - this.duration.withTag(ErrorAttributes.ERROR_TYPE.getKey(), "") - .record(took, TimeUnit.NANOSECONDS); - } else { - this.duration.withTag(ErrorAttributes.ERROR_TYPE.getKey(), this.error.getClass().getCanonicalName()) - .record(took, TimeUnit.NANOSECONDS); - } - this.span.end(); - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetry.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetry.java deleted file mode 100644 index 5940bd696..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetry.java +++ /dev/null @@ -1,65 +0,0 @@ -package io.koraframework.s3.client.telemetry; - -import io.micrometer.core.instrument.Meter; -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.Tags; -import io.micrometer.core.instrument.Timer; -import io.opentelemetry.api.trace.Span; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.semconv.incubating.AwsIncubatingAttributes; -import io.opentelemetry.semconv.incubating.RpcIncubatingAttributes; -import io.koraframework.s3.client.S3ClientConfig; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -public class DefaultS3ClientTelemetry implements S3ClientTelemetry { - protected final S3ClientConfig config; - protected final Tracer tracer; - protected final MeterRegistry meterRegistry; - protected final ConcurrentMap durationCache = new ConcurrentHashMap<>(); - - public DefaultS3ClientTelemetry(S3ClientConfig config, Tracer tracer, MeterRegistry meterRegistry) { - this.config = config; - this.tracer = tracer; - this.meterRegistry = meterRegistry; - } - - @Override - public S3ClientObservation observe(String operation, String bucket) { - var span = this.createSpan(operation, bucket); - var duration = this.createDuration(operation, bucket); - - return new DefaultS3ClientObservation(span, duration); - } - - protected Meter.MeterProvider createDuration(String operation, String bucket) { - return tags -> durationCache.computeIfAbsent(Tags.of(tags), t -> { - var builder = Timer.builder("rpc.client.duration") - .serviceLevelObjectives(this.config.telemetry().metrics().slo()) - .tag(RpcIncubatingAttributes.RPC_SYSTEM.getKey(), "raws-api") - .tag(RpcIncubatingAttributes.RPC_METHOD.getKey(), operation) - .tag(AwsIncubatingAttributes.AWS_S3_BUCKET.getKey(), bucket) - .tags(t); - for (var tag : this.config.telemetry().metrics().tags().entrySet()) { - builder.tag(tag.getValue(), tag.getValue()); - } - - return builder.register(this.meterRegistry); - }); - } - - protected Span createSpan(String operation, String bucket) { - if (!this.config.telemetry().tracing().enabled()) { - return Span.getInvalid(); - } - var span = this.tracer.spanBuilder("S3." + operation) - .setAttribute(RpcIncubatingAttributes.RPC_SYSTEM, "aws-api") - .setAttribute(RpcIncubatingAttributes.RPC_METHOD, operation) - .setAttribute(AwsIncubatingAttributes.AWS_S3_BUCKET, bucket); - for (var entry : this.config.telemetry().tracing().attributes().entrySet()) { - span.setAttribute(entry.getKey(), entry.getValue()); - } - return span.startSpan(); - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetryFactory.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetryFactory.java deleted file mode 100644 index ba4d34c23..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/DefaultS3ClientTelemetryFactory.java +++ /dev/null @@ -1,36 +0,0 @@ -package io.koraframework.s3.client.telemetry; - -import io.micrometer.core.instrument.MeterRegistry; -import io.micrometer.core.instrument.composite.CompositeMeterRegistry; -import io.opentelemetry.api.trace.Tracer; -import io.opentelemetry.api.trace.TracerProvider; -import org.jspecify.annotations.Nullable; -import io.koraframework.s3.client.S3ClientConfig; - -public class DefaultS3ClientTelemetryFactory implements S3ClientTelemetryFactory { - @Nullable - private final Tracer tracer; - @Nullable - private final MeterRegistry meterRegistry; - - public DefaultS3ClientTelemetryFactory(@Nullable Tracer tracer, @Nullable MeterRegistry meterRegistry) { - this.tracer = tracer; - this.meterRegistry = meterRegistry; - } - - @Override - public S3ClientTelemetry get(S3ClientConfig s3Config) { - var telemetryConfig = s3Config.telemetry(); - if (!telemetryConfig.logging().enabled() && !telemetryConfig.metrics().enabled() && !telemetryConfig.tracing().enabled()) { - return NoopS3ClientTelemetry.INSTANCE; - } - var tracer = this.tracer == null || !telemetryConfig.tracing().enabled() - ? TracerProvider.noop().get("s3-client-telemetry") - : this.tracer; - var meterRegistry = this.meterRegistry == null || !telemetryConfig.metrics().enabled() - ? new CompositeMeterRegistry() - : this.meterRegistry; - - return new DefaultS3ClientTelemetry(s3Config, tracer, meterRegistry); - } -} diff --git a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryFactory.java b/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryFactory.java deleted file mode 100644 index b72b51cb5..000000000 --- a/experimental/s3-client/src/main/java/io/koraframework/s3/client/telemetry/S3ClientTelemetryFactory.java +++ /dev/null @@ -1,7 +0,0 @@ -package io.koraframework.s3.client.telemetry; - -import io.koraframework.s3.client.S3ClientConfig; - -public interface S3ClientTelemetryFactory { - S3ClientTelemetry get(S3ClientConfig config); -} diff --git a/settings.gradle b/settings.gradle index 73b2d12e2..32968eb21 100644 --- a/settings.gradle +++ b/settings.gradle @@ -98,7 +98,7 @@ include( 'mapstruct:mapstruct-ksp-extension', 'experimental:s3-client-annotation-processor', 'experimental:s3-client-symbol-processor', - 'experimental:s3-client', + 'experimental:s3-client-kora', 'experimental:camunda-engine-bpmn', 'experimental:camunda-rest-undertow', 'experimental:camunda-zeebe-worker',