diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/after/src/main/java/foo/bar/S3Transforms.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/after/src/main/java/foo/bar/S3Transforms.java index f8a83e2e89b..1e8941e06da 100644 --- a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/after/src/main/java/foo/bar/S3Transforms.java +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/after/src/main/java/foo/bar/S3Transforms.java @@ -16,12 +16,15 @@ package foo.bar; import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams; +import com.amazonaws.services.s3.model.SSECustomerKey; import java.io.ByteArrayInputStream; import java.io.InputStream; import java.net.URL; import java.util.Date; import software.amazon.awssdk.core.async.AsyncRequestBody; import software.amazon.awssdk.services.s3.S3Client; +import software.amazon.awssdk.services.s3.model.AccessControlPolicy; import software.amazon.awssdk.services.s3.model.GeneratePresignedUrlRequest; import software.amazon.awssdk.services.s3.model.HeadObjectResponse; import software.amazon.awssdk.services.s3.model.PutObjectRequest; @@ -32,33 +35,49 @@ public class S3Transforms { void upload_streamWithLiteralLength(S3TransferManager tm, String bucket, String key) { HeadObjectResponse metadata = HeadObjectResponse.builder() - .build(); + .build(); InputStream inputStream = new ByteArrayInputStream(("HelloWorld").getBytes()); PutObjectRequest requestWithStreamAndLiteralLength = PutObjectRequest.builder().bucket(bucket).key(key).websiteRedirectLocation("location").contentLength(333L) - .build(); + .build(); /*AWS SDK for Java v2 migration: When using InputStream to upload with TransferManager, you must specify Content-Length and ExecutorService.*/tm.upload(UploadRequest.builder().putObjectRequest(requestWithStreamAndLiteralLength).requestBody(AsyncRequestBody.fromInputStream(inputStream, 333, newExecutorServiceVariableToDefine)).build()); } void upload_streamWithAssignedLength(S3TransferManager tm, String bucket, String key) { HeadObjectResponse metadata = HeadObjectResponse.builder() - .build(); + .build(); long contentLen = 777; InputStream inputStream = new ByteArrayInputStream(("HelloWorld").getBytes()); PutObjectRequest requestWithStreamAndAssignedLength = PutObjectRequest.builder().bucket(bucket).key(key).websiteRedirectLocation("location").contentLength(contentLen) - .build(); + .build(); /*AWS SDK for Java v2 migration: When using InputStream to upload with TransferManager, you must specify Content-Length and ExecutorService.*/tm.upload(UploadRequest.builder().putObjectRequest(requestWithStreamAndAssignedLength).requestBody(AsyncRequestBody.fromInputStream(inputStream, contentLen, newExecutorServiceVariableToDefine)).build()); } void upload_streamWithoutLength(S3TransferManager tm, String bucket, String key) { InputStream inputStream = new ByteArrayInputStream(("HelloWorld").getBytes()); PutObjectRequest requestWithStreamAndNoLength = PutObjectRequest.builder().bucket(bucket).key(key).websiteRedirectLocation("location") - .build(); + .build(); /*AWS SDK for Java v2 migration: When using InputStream to upload with TransferManager, you must specify Content-Length and ExecutorService.*/tm.upload(UploadRequest.builder().putObjectRequest(requestWithStreamAndNoLength).requestBody(AsyncRequestBody.fromInputStream(inputStream, -1L, newExecutorServiceVariableToDefine)).build()); } + void putObjectRequest_unsupportedSetters() { + SSECustomerKey sseCustomerKey = new SSECustomerKey("val"); + SSEAwsKeyManagementParams sseParams = new SSEAwsKeyManagementParams(); + AccessControlPolicy accessControlList = AccessControlPolicy.builder() + .build(); + + PutObjectRequest request = /*AWS SDK for Java v2 migration: Transform for PutObjectRequest setter accessControlList is not supported, please manually migrate your code to use the v2 setters: acl, grantReadACP, grantWriteACP - https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/PutObjectRequest.Builder.html#acl(java.lang.String)*/ +/*AWS SDK for Java v2 migration: Transform for PutObjectRequest setter sseCustomerKey is not supported, please manually migrate your code to use the v2 setters: sseCustomerKey, sseCustomerKeyMD5 - https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/PutObjectRequest.Builder.html#sseCustomerKey(java.lang.String)*/ +/*AWS SDK for Java v2 migration: Transform for PutObjectRequest setter sseAwsKeyManagementParam is not supported, please manually migrate your code to use the v2 setters: ssekmsKeyId, serverSideEncryption, sseCustomerAlgorithm - https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model/PutObjectRequest.Builder.html#ssekmsKeyId(java.lang.String)*/ +PutObjectRequest.builder().bucket("bucket").key("key").websiteRedirectLocation("location") + .sseCustomerKey(sseCustomerKey) + .sseAwsKeyManagementParams(sseParams) + .accessControlList(accessControlList) + .build(); + } + void objectmetadata_unsupportedSetters(Date dateVal) { HeadObjectResponse metadata = HeadObjectResponse.builder() - .build(); + .build(); /*AWS SDK for Java v2 migration: Transform for ObjectMetadata setter - expirationTimeRuleId - is not supported, please manually migrate the code by setting it on the v2 request/response object.*/metadata.expirationTimeRuleId("expirationTimeRuleId"); /*AWS SDK for Java v2 migration: Transform for ObjectMetadata setter - ongoingRestore - is not supported, please manually migrate the code by setting it on the v2 request/response object.*/metadata.ongoingRestore(false); diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/before/src/main/java/foo/bar/S3Transforms.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/before/src/main/java/foo/bar/S3Transforms.java index 1eac54b1388..1eeedfdda64 100644 --- a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/before/src/main/java/foo/bar/S3Transforms.java +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven-nocompile/before/src/main/java/foo/bar/S3Transforms.java @@ -17,9 +17,12 @@ import com.amazonaws.HttpMethod; import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.AccessControlList; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.amazonaws.services.s3.model.ObjectMetadata; import com.amazonaws.services.s3.model.PutObjectRequest; +import com.amazonaws.services.s3.model.SSEAwsKeyManagementParams; +import com.amazonaws.services.s3.model.SSECustomerKey; import com.amazonaws.services.s3.transfer.TransferManager; import java.io.ByteArrayInputStream; import java.io.InputStream; @@ -54,6 +57,17 @@ void upload_streamWithoutLength(TransferManager tm, String bucket, String key) { tm.upload(requestWithStreamAndNoLength); } + void putObjectRequest_unsupportedSetters() { + SSECustomerKey sseCustomerKey = new SSECustomerKey("val"); + SSEAwsKeyManagementParams sseParams = new SSEAwsKeyManagementParams(); + AccessControlList accessControlList = new AccessControlList(); + + PutObjectRequest request = new PutObjectRequest("bucket", "key", "location") + .withSSECustomerKey(sseCustomerKey) + .withSSEAwsKeyManagementParams(sseParams) + .withAccessControlList(accessControlList); + } + void objectmetadata_unsupportedSetters(Date dateVal) { ObjectMetadata metadata = new ObjectMetadata(); diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3.java index 6fd807056ba..ff3bd49cbcc 100644 --- a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3.java +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3.java @@ -409,22 +409,26 @@ private void s3Uri(URI uri, String uriAsString) { } private void generatePresignedUrl(S3Client s3, String bucket, String key, Date expiration) { - URL urlGet1 = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/S3Presigner.builder().s3Client(s3).build() + URL urlGet1 = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/ + S3Presigner.builder().s3Client(s3).build() .presignGetObject(p -> p.getObjectRequest(r -> r.bucket(bucket).key(key)) .signatureDuration(Duration.between(Instant.now(), expiration.toInstant()))) .url(); - URL urlPut = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/S3Presigner.builder().s3Client(s3).build() + URL urlPut = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/ + S3Presigner.builder().s3Client(s3).build() .presignPutObject(p -> p.putObjectRequest(r -> r.bucket(bucket).key(key)) .signatureDuration(Duration.between(Instant.now(), expiration.toInstant()))) .url(); - URL urlGet2 = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/S3Presigner.builder().s3Client(s3).build() + URL urlGet2 = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/ + S3Presigner.builder().s3Client(s3).build() .presignGetObject(p -> p.getObjectRequest(r -> r.bucket(bucket).key(key)) .signatureDuration(Duration.between(Instant.now(), expiration.toInstant()))) .url(); - URL urlDelete = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/S3Presigner.builder().s3Client(s3).build() + URL urlDelete = /*AWS SDK for Java v2 migration: If generating multiple pre-signed URLs, it is recommended to create a single instance of S3Presigner, since creating a presigner can be expensive. If applicable, please manually refactor the transformed code.*/ + S3Presigner.builder().s3Client(s3).build() .presignDeleteObject(p -> p.deleteObjectRequest(r -> r.bucket(bucket).key(key)) .signatureDuration(Duration.between(Instant.now(), expiration.toInstant()))) .url(); diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3Streaming.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3Streaming.java index 9bab4fc5677..3b3f878e377 100644 --- a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3Streaming.java +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/after/src/main/java/foo/bar/S3Streaming.java @@ -18,8 +18,10 @@ import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; import software.amazon.awssdk.core.ResponseInputStream; import software.amazon.awssdk.core.sync.RequestBody; @@ -30,6 +32,8 @@ import software.amazon.awssdk.services.s3.model.ObjectCannedACL; import software.amazon.awssdk.services.s3.model.PutObjectRequest; import software.amazon.awssdk.services.s3.model.RequestPayer; +import software.amazon.awssdk.services.s3.model.Tag; +import software.amazon.awssdk.services.s3.model.Tagging; public class S3Streaming { @@ -61,6 +65,8 @@ void putObject_bucketKeyStreamMetadata(String bucket, String key, InputStream st HeadObjectResponse metadataWithoutLength = HeadObjectResponse.builder() .build(); /*AWS SDK for Java v2 migration: When using InputStream to upload with S3Client, Content-Length should be specified and used with RequestBody.fromInputStream(). Otherwise, the entire stream will be buffered in memory. If content length must be unknown, we recommend using the CRT-based S3 client - https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/crt-based-s3-client.html*/s3.putObject(PutObjectRequest.builder().bucket(bucket).key(key).build(), RequestBody.fromContentProvider(() -> stream, "application/octet-stream")); + + /*AWS SDK for Java v2 migration: When using InputStream to upload with S3Client, Content-Length should be specified and used with RequestBody.fromInputStream(). Otherwise, the entire stream will be buffered in memory. If content length must be unknown, we recommend using the CRT-based S3 client - https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/crt-based-s3-client.html*/s3.putObject(PutObjectRequest.builder().bucket("bucket").key("key").build(), RequestBody.fromContentProvider(() -> stream, "application/octet-stream")); } /** @@ -108,10 +114,16 @@ void putObject_requestPojoWithoutPayload(String bucket, String key) { void putObjectSetters() { + List tags = new ArrayList<>(); + Tagging objectTagging = Tagging.builder().tagSet(tags) + .build(); + PutObjectRequest putObjectRequest = PutObjectRequest.builder().bucket("bucket").key("key").websiteRedirectLocation("location") .bucket("bucketName") + .websiteRedirectLocation("redirectLocation") .acl(ObjectCannedACL.AWS_EXEC_READ) + .tagging(objectTagging) .build(); } @@ -160,7 +172,7 @@ void putObjectRequest_withMetadata() { .build(); } - void putObjectRequester_emptyMetadata() { + void putObjectRequest_emptyMetadata() { HeadObjectResponse emptyMetadata1 = HeadObjectResponse.builder() .build(); PutObjectRequest request1 =PutObjectRequest.builder().bucket("bucket").key("key").websiteRedirectLocation("location") diff --git a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/S3Streaming.java b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/S3Streaming.java index ab8243333b3..e974de1e21b 100644 --- a/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/S3Streaming.java +++ b/test/v2-migration-tests/src/test/resources/software/amazon/awssdk/v2migrationtests/maven/before/src/main/java/foo/bar/S3Streaming.java @@ -19,13 +19,17 @@ import com.amazonaws.services.s3.AmazonS3ClientBuilder; import com.amazonaws.services.s3.model.CannedAccessControlList; import com.amazonaws.services.s3.model.ObjectMetadata; +import com.amazonaws.services.s3.model.ObjectTagging; import com.amazonaws.services.s3.model.PutObjectRequest; import com.amazonaws.services.s3.model.S3Object; +import com.amazonaws.services.s3.model.Tag; import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; +import java.util.ArrayList; import java.util.Date; import java.util.HashMap; +import java.util.List; import java.util.Map; public class S3Streaming { @@ -53,6 +57,8 @@ void putObject_bucketKeyStreamMetadata(String bucket, String key, InputStream st ObjectMetadata metadataWithoutLength = new ObjectMetadata(); s3.putObject(bucket, key, stream, metadataWithoutLength); + + s3.putObject("bucket", "key", stream, new ObjectMetadata()); } /** @@ -95,10 +101,15 @@ void putObject_requestPojoWithoutPayload(String bucket, String key) { void putObjectSetters() { + List tags = new ArrayList<>(); + ObjectTagging objectTagging = new ObjectTagging(tags); + PutObjectRequest putObjectRequest = new PutObjectRequest("bucket", "key", "location") - .withBucketName("bucketName") - .withCannedAcl(CannedAccessControlList.AwsExecRead); + .withBucketName("bucketName") + .withRedirectLocation("redirectLocation") + .withCannedAcl(CannedAccessControlList.AwsExecRead) + .withTagging(objectTagging); } void putObjectRequesterPaysSetter() { @@ -141,7 +152,7 @@ void putObjectRequest_withMetadata() { PutObjectRequest request = new PutObjectRequest("bucket", "key", "location").withMetadata(metadata); } - void putObjectRequester_emptyMetadata() { + void putObjectRequest_emptyMetadata() { ObjectMetadata emptyMetadata1 = new ObjectMetadata(); PutObjectRequest request1 = new PutObjectRequest("bucket", "key", "location").withMetadata(emptyMetadata1); diff --git a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/S3PutObjectRequestToV2.java b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/S3PutObjectRequestToV2.java index 94fb449296a..151d24a95c2 100644 --- a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/S3PutObjectRequestToV2.java +++ b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/S3PutObjectRequestToV2.java @@ -18,16 +18,19 @@ import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.SUPPORTED_METADATA_TRANSFORMS; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_S3_MODEL_PKG; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.V2_TM_MODEL_PKG; +import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.addCommentForUnsupportedPutObjectRequestSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.addMetadataFields; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.createComments; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.getArgumentName; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.getSelectName; +import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.inputStreamBufferingWarningComment; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isObjectMetadataSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isPayloadSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isPutObjectRequestBuilderSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isPutObjectRequestSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isRequestMetadataSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isRequestPayerSetter; +import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.isUnsupportedPutObjectRequestSetter; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.v2S3MethodMatcher; import static software.amazon.awssdk.v2migration.internal.utils.S3TransformUtils.v2TmMethodMatcher; import static software.amazon.awssdk.v2migration.internal.utils.SdkTypeUtils.isFileType; @@ -36,7 +39,6 @@ import java.util.ArrayDeque; import java.util.Arrays; import java.util.HashMap; -import java.util.List; import java.util.Map; import java.util.Queue; import org.openrewrite.ExecutionContext; @@ -46,7 +48,6 @@ import org.openrewrite.java.JavaTemplate; import org.openrewrite.java.JavaVisitor; import org.openrewrite.java.MethodMatcher; -import org.openrewrite.java.tree.Comment; import org.openrewrite.java.tree.Expression; import org.openrewrite.java.tree.J; import software.amazon.awssdk.annotations.SdkInternalApi; @@ -106,6 +107,10 @@ public J visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) if (isRequestPayerSetter(method)) { return transformWithRequesterPays(method); } + if (isUnsupportedPutObjectRequestSetter(method)) { + method = addCommentForUnsupportedPutObjectRequestSetter(method); + return super.visitMethodInvocation(method, ctx); + } } if (isPutObjectRequestSetter(method)) { if (isRequestMetadataSetter(method)) { @@ -316,11 +321,18 @@ private J.MethodInvocation transformPutObjectWithStreamAndMetadata(J.MethodInvoc addS3Import("PutObjectRequest"); Expression metadata = method.getArguments().get(3); - String metadataName = ((J.Identifier) metadata).getSimpleName(); + String metadataName = null; + if (metadata instanceof J.Identifier) { + metadataName = ((J.Identifier) metadata).getSimpleName(); + } StringBuilder sb = new StringBuilder("PutObjectRequest.builder().bucket(#{any()}).key(#{any()})"); - addMetadataFields(sb, metadataName, metadataMap); - Expression contentLen = retrieveContentLengthForMetadataIfSet(metadataName); + + Expression contentLen = null; + if (metadataName != null) { + addMetadataFields(sb, metadataName, metadataMap); + contentLen = retrieveContentLengthForMetadataIfSet(metadataName); + } Expression[] params = {method.getArguments().get(0), method.getArguments().get(1), method.getArguments().get(2)}; @@ -473,13 +485,5 @@ private void addTmImport(String pojoName) { String fqcn = V2_TM_MODEL_PKG + pojoName; doAfterVisit(new AddImport<>(fqcn, null, false)); } - - private List inputStreamBufferingWarningComment() { - String warning = "When using InputStream to upload with S3Client, Content-Length should be specified and used " - + "with RequestBody.fromInputStream(). Otherwise, the entire stream will be buffered in memory. If" - + " content length must be unknown, we recommend using the CRT-based S3 client - " - + "https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/crt-based-s3-client.html"; - return createComments(warning); - } } } diff --git a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/NamingConversionUtils.java b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/NamingConversionUtils.java index 5cecb0a5b77..50edbb9e671 100644 --- a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/NamingConversionUtils.java +++ b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/NamingConversionUtils.java @@ -180,6 +180,8 @@ public final class NamingConversionUtils { S3_POJO_MAPPING.put("ReplicationFilter", "ReplicationRuleFilter"); S3_POJO_MAPPING.put("ReplicationAndOperator", "ReplicationRuleAndOperator"); S3_POJO_MAPPING.put("PartETag", "CompletedPart"); + S3_POJO_MAPPING.put("ObjectTagging", "Tagging"); + S3_POJO_MAPPING.put("AccessControlList", "AccessControlPolicy"); //Special Enum mapping S3_POJO_MAPPING.put("S3Event", "Event"); diff --git a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/S3TransformUtils.java b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/S3TransformUtils.java index 386cf7aa575..adad6c5d8fc 100644 --- a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/S3TransformUtils.java +++ b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/S3TransformUtils.java @@ -61,6 +61,13 @@ public final class S3TransformUtils { "httpExpiresDate" ))); + public static final Set UNSUPPORTED_PUT_OBJ_REQUEST_TRANSFORMS = Collections.unmodifiableSet(new HashSet<>( + Arrays.asList( + "sseCustomerKey", + "sseAwsKeyManagementParams", + "accessControlList" + ))); + private S3TransformUtils() { @@ -153,9 +160,29 @@ public static String getSelectName(J.MethodInvocation method) { return ((J.Identifier) select).getSimpleName(); } + private static Comment generateComment(String comment, boolean withNewLine) { + String suffix = withNewLine ? "\n" : ""; + return new TextComment(true, "AWS SDK for Java v2 migration: " + comment, suffix, Markers.EMPTY); + } + + public static Comment createComment(String comment) { + return generateComment(comment, false); + } + + public static Comment createCommentWithNewline(String comment) { + return generateComment(comment, true); + } + public static List createComments(String comment) { - return Collections.singletonList( - new TextComment(true, "AWS SDK for Java v2 migration: " + comment, "", Markers.EMPTY)); + return Arrays.asList(createComment(comment)); + } + + public static List createCommentsWithNewline(String comment) { + return Arrays.asList(createCommentWithNewline(comment)); + } + + public static boolean isUnsupportedPutObjectRequestSetter(J.MethodInvocation method) { + return UNSUPPORTED_PUT_OBJ_REQUEST_TRANSFORMS.contains(method.getSimpleName()); } public static boolean isObjectMetadataSetter(J.MethodInvocation method) { @@ -221,24 +248,34 @@ public static boolean isUnsupportedHttpMethod(String httpMethod) { return Arrays.asList("Head", "Post", "Patch").contains(httpMethod); } + public static List inputStreamBufferingWarningComment() { + String warning = "When using InputStream to upload with S3Client, Content-Length should be specified and used " + + "with RequestBody.fromInputStream(). Otherwise, the entire stream will be buffered in memory. If" + + " content length must be unknown, we recommend using the CRT-based S3 client - " + + "https://docs.aws.amazon.com/sdk-for-java/latest/developer-guide/crt-based-s3-client.html"; + return createComments(warning); + } + public static List assignedVariableHttpMethodNotSupportedComment() { String comment = "Transform for S3 generatePresignedUrl() with an assigned variable for HttpMethod is not supported." - + " Please manually migrate your code - https://sdk.amazonaws" - + ".com/java/api/latest/software/amazon/awssdk/services/s3/presigner/S3Presigner.html"; + + " Please manually migrate your code - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/presigner/S3Presigner" + + ".html"; return createComments(comment); } public static List requestPojoTransformNotSupportedComment() { - String comment = "Transforms are not supported for GeneratePresignedUrlRequest, please manually migrate your code " - + "- https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/presigner" - + "/S3Presigner.html"; + String comment = "Transforms are not supported for GeneratePresignedUrlRequest, please manually migrate your code - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/presigner/S3Presigner" + + ".html"; return createComments(comment); } public static List httpMethodNotSupportedComment(String httpMethod) { String comment = String.format("S3 generatePresignedUrl() with %s HTTP method is not supported in v2. Only GET, PUT, " - + "and DELETE are supported - https://sdk.amazonaws" - + ".com/java/api/latest/software/amazon/awssdk/services/s3/presigner/S3Presigner.html", + + "and DELETE are supported - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3" + + "/presigner/S3Presigner.html", httpMethod.toUpperCase(Locale.ROOT)); return createComments(comment); } @@ -247,6 +284,54 @@ public static List presignerSingleInstanceSuggestion() { String comment = "If generating multiple pre-signed URLs, it is recommended to create a single instance of " + "S3Presigner, since creating a presigner can be expensive. If applicable, please manually " + "refactor the transformed code."; - return createComments(comment); + return createCommentsWithNewline(comment); + } + + public static J.MethodInvocation sseAwsKeyManagementParamsNotSupportedComment(J.MethodInvocation method) { + String comment = "Transform for PutObjectRequest setter sseAwsKeyManagementParam is not supported, please manually " + + "migrate your code to use the v2 setters: ssekmsKeyId, serverSideEncryption, sseCustomerAlgorithm - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model" + + "/PutObjectRequest.Builder.html#ssekmsKeyId(java.lang.String)"; + return appendCommentToMethod(method, comment); + } + + public static J.MethodInvocation sseCustomerKeyNotSupportedComment(J.MethodInvocation method) { + String comment = "Transform for PutObjectRequest setter sseCustomerKey is not supported, please manually " + + "migrate your code to use the v2 setters: sseCustomerKey, sseCustomerKeyMD5 - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model" + + "/PutObjectRequest.Builder.html#sseCustomerKey(java.lang.String)"; + return appendCommentToMethod(method, comment); + } + + public static J.MethodInvocation accessControlListNotSupportedComment(J.MethodInvocation method) { + String comment = "Transform for PutObjectRequest setter accessControlList is not supported, please manually " + + "migrate your code to use the v2 setters: acl, grantReadACP, grantWriteACP - " + + "https://sdk.amazonaws.com/java/api/latest/software/amazon/awssdk/services/s3/model" + + "/PutObjectRequest.Builder.html#acl(java.lang.String)"; + return appendCommentToMethod(method, comment); + } + + public static J.MethodInvocation addCommentForUnsupportedPutObjectRequestSetter(J.MethodInvocation method) { + String methodName = method.getSimpleName(); + switch (methodName) { + case "sseCustomerKey": + return sseAwsKeyManagementParamsNotSupportedComment(method); + case "sseAwsKeyManagementParams": + return sseCustomerKeyNotSupportedComment(method); + case "accessControlList": + return accessControlListNotSupportedComment(method); + default: + return method; + } + } + + public static J.MethodInvocation appendCommentToMethod(J.MethodInvocation method, String comment) { + if (method.getComments().isEmpty()) { + return method.withComments(createCommentsWithNewline(comment)); + } + + List existingComments = method.getComments(); + existingComments.add(createCommentWithNewline(comment)); + return method.withComments(existingComments); } } diff --git a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/SdkTypeUtils.java b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/SdkTypeUtils.java index 85a4b494f94..667370ef1ed 100644 --- a/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/SdkTypeUtils.java +++ b/v2-migration/src/main/java/software/amazon/awssdk/v2migration/internal/utils/SdkTypeUtils.java @@ -148,7 +148,10 @@ public final class SdkTypeUtils { "com.amazonaws.services.kinesis.metrics", "com.amazonaws.services.kinesis.multilang", // Kinesis Producer Library (KCL) : amazon-kinesis-producer - "com.amazonaws.services.kinesis.producer" + "com.amazonaws.services.kinesis.producer", + // S3 POJOs with no v2 equivalent + "com.amazonaws.services.s3.model.SSEAwsKeyManagementParams", + "com.amazonaws.services.s3.model.SSECustomerKey" )); static { diff --git a/v2-migration/src/main/resources/META-INF/rewrite/change-s3-methods.yml b/v2-migration/src/main/resources/META-INF/rewrite/change-s3-methods.yml index 2034463d8b9..ad1faf18180 100644 --- a/v2-migration/src/main/resources/META-INF/rewrite/change-s3-methods.yml +++ b/v2-migration/src/main/resources/META-INF/rewrite/change-s3-methods.yml @@ -196,12 +196,6 @@ recipeList: - org.openrewrite.java.ChangeMethodName: methodPattern: com.amazonaws.services.s3.model.BucketCrossOriginConfiguration withRules(com.amazonaws.services.s3.model.CORSRule...) newMethodName: withCorsRules - - org.openrewrite.java.ChangeMethodName: - methodPattern: com.amazonaws.services.s3.model.ListObjectsRequest withBucketName(String) - newMethodName: withBucket - - org.openrewrite.java.ChangeMethodName: - methodPattern: com.amazonaws.services.s3.model.ListObjectsV2Request withBucketName(String) - newMethodName: withBucket - org.openrewrite.java.ChangeMethodName: methodPattern: com.amazonaws.services.s3.model.CopyPartRequest withSourceBucketName(String) newMethodName: withSourceBucket @@ -211,17 +205,13 @@ recipeList: - org.openrewrite.java.ChangeMethodName: methodPattern: com.amazonaws.services.s3.model.analytics.AnalyticsS3BucketDestination withBucketArn(String) newMethodName: withBucket - - org.openrewrite.java.ChangeMethodName: - methodPattern: com.amazonaws.services.s3.model.CompleteMultipartUploadRequest withBucketName(String) - newMethodName: withBucket - org.openrewrite.java.ChangeMethodName: methodPattern: com.amazonaws.services.s3.model.CompleteMultipartUploadRequest withPartETags(java.util.List) newMethodName: withMultipartUpload - - org.openrewrite.java.ChangeMethodName: - methodPattern: com.amazonaws.services.s3.model.PutObjectRequest withBucketName(String) - newMethodName: withBucket + methodPattern: com.amazonaws.services.s3.model.PutObjectRequest withRedirectLocation(String) + newMethodName: withWebsiteRedirectLocation - org.openrewrite.java.ChangeMethodName: methodPattern: com.amazonaws.services.s3.model.PutObjectRequest withCannedAcl(com.amazonaws.services.s3.model.CannedAccessControlList) newMethodName: withAcl diff --git a/v2-migration/src/main/resources/META-INF/rewrite/s3-methods-constructor-to-fluent.yml b/v2-migration/src/main/resources/META-INF/rewrite/s3-methods-constructor-to-fluent.yml index 8510bd53e26..0d5593d8e1c 100644 --- a/v2-migration/src/main/resources/META-INF/rewrite/s3-methods-constructor-to-fluent.yml +++ b/v2-migration/src/main/resources/META-INF/rewrite/s3-methods-constructor-to-fluent.yml @@ -621,4 +621,10 @@ recipeList: - withBucket - withKey - withUploadId - - withMultipartUpload \ No newline at end of file + - withMultipartUpload + - software.amazon.awssdk.v2migration.ConstructorToFluent: + clzzFqcn: com.amazonaws.services.s3.model.ObjectTagging + parameterTypes: + - java.util.List + fluentNames: + - withTagSet \ No newline at end of file